1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
15 from subprocess import Popen, PIPE, call
16 from multiprocessing import Pool
17 from tempfile import NamedTemporaryFile
18 from os.path import basename
19 from robot.api import logger
20 from robot.libraries.BuiltIn import BuiltIn
22 from constants import Constants as con
23 from topology import NodeType
25 __all__ = ["SetupFramework"]
28 def pack_framework_dir():
29 """Pack the testing WS into temp file, return its name."""
31 tmpfile = NamedTemporaryFile(suffix=".tgz", prefix="openvpp-testing-")
32 file_name = tmpfile.name
36 shlex.split("tar --exclude-vcs -zcf {0} .".format(file_name)),
37 stdout=PIPE, stderr=PIPE)
38 (stdout, stderr) = proc.communicate()
43 return_code = proc.wait()
45 raise Exception("Could not pack testing framework.")
50 def copy_tarball_to_node(tarball, node):
51 logger.console('Copying tarball to {0}'.format(node['host']))
55 ssh.scp(tarball, "/tmp/")
58 def extract_tarball_at_node(tarball, node):
59 logger.console('Extracting tarball to {0} on {1}'.format(
60 con.REMOTE_FW_DIR, node['host']))
64 cmd = 'sudo rm -rf {1}; mkdir {1} ; tar -zxf {0} -C {1}; ' \
65 'rm -f {0}'.format(tarball, con.REMOTE_FW_DIR)
66 (ret_code, stdout, stderr) = ssh.exec_command(cmd, timeout=30)
68 logger.error('Unpack error: {0}'.format(stderr))
69 raise Exception('Failed to unpack {0} at node {1}'.format(
70 tarball, node['host']))
73 def create_env_directory_at_node(node):
74 """Create fresh virtualenv to a directory, install pip requirements."""
75 logger.console('Extracting virtualenv, installing requirements.txt '
76 'on {0}'.format(node['host']))
79 (ret_code, stdout, stderr) = ssh.exec_command(
80 'cd {0} && rm -rf env && virtualenv env && '
81 '. env/bin/activate && '
82 'pip install -r requirements.txt'.format(con.REMOTE_FW_DIR), timeout=100)
84 logger.error('Virtualenv creation error: {0}'.format(stdout + stderr))
85 raise Exception('Virtualenv setup failed')
87 logger.console('Virtualenv created on {0}'.format(node['host']))
90 tarball, remote_tarball, node = args
91 copy_tarball_to_node(tarball, node)
92 extract_tarball_at_node(remote_tarball, node)
93 if node['type'] == NodeType.TG:
94 create_env_directory_at_node(node)
97 def delete_local_tarball(tarball):
98 call(shlex.split('sh -c "rm {0} > /dev/null 2>&1"'.format(tarball)))
101 class SetupFramework(object):
102 """Setup suite run on topology nodes.
104 Many VAT/CLI based tests need the scripts at remote hosts before executing
105 them. This class packs the whole testing directory and copies it over
106 to all nodes in topology under /tmp/
112 def setup_framework(self, nodes):
113 """Pack the whole directory and extract in temp on each node."""
115 tarball = pack_framework_dir()
116 msg = 'Framework packed to {0}'.format(tarball)
119 remote_tarball = "/tmp/{0}".format(basename(tarball))
121 # Turn off loggining since we use multiprocessing
122 log_level = BuiltIn().set_log_level('NONE')
123 params = ((tarball, remote_tarball, node) for node in nodes.values())
124 pool = Pool(processes=len(nodes))
125 result = pool.map_async(setup_node, params)
130 'Executed node setups in parallel, waiting for processes to end')
133 logger.info('Results: {0}'.format(result.get()))
136 BuiltIn().set_log_level(log_level)
137 logger.trace('Test framework copied to all topology nodes')
138 delete_local_tarball(tarball)