Renamed folder with tests to make them consistent with cvp-runner.groovy
and CVP jobs in cluster Jenkins
Return rsync service into inconsistency_rule
Related-Task: #PROD-23604(PROD:23604)
Change-Id: I94afe350bd1d9c184bafe8e9e270aeb4c6c24c50
diff --git a/test_set/cvp-spt/utils/__init__.py b/test_set/cvp-spt/utils/__init__.py
new file mode 100644
index 0000000..36cf239
--- /dev/null
+++ b/test_set/cvp-spt/utils/__init__.py
@@ -0,0 +1,111 @@
+import os
+import yaml
+import requests
+import re
+import sys, traceback
+import itertools
+import helpers
+from utils import os_client
+
+
+class salt_remote:
+ def cmd(self, tgt, fun, param=None, expr_form=None, tgt_type=None):
+ config = get_configuration()
+ url = config['SALT_URL']
+ proxies = {"http": None, "https": None}
+ headers = {'Accept': 'application/json'}
+ login_payload = {'username': config['SALT_USERNAME'],
+ 'password': config['SALT_PASSWORD'], 'eauth': 'pam'}
+ accept_key_payload = {'fun': fun, 'tgt': tgt, 'client': 'local',
+ 'expr_form': expr_form, 'tgt_type': tgt_type,
+ 'timeout': config['salt_timeout']}
+ if param:
+ accept_key_payload['arg'] = param
+
+ try:
+ login_request = requests.post(os.path.join(url, 'login'),
+ headers=headers, data=login_payload,
+ proxies=proxies)
+ if login_request.ok:
+ request = requests.post(url, headers=headers,
+ data=accept_key_payload,
+ cookies=login_request.cookies,
+ proxies=proxies)
+ return request.json()['return'][0]
+ except Exception:
+ print "\033[91m\nConnection to SaltMaster " \
+ "was not established.\n" \
+ "Please make sure that you " \
+ "provided correct credentials.\033[0m\n"
+ traceback.print_exc(file=sys.stdout)
+ sys.exit()
+
+
+def init_salt_client():
+ local = salt_remote()
+ return local
+
+
+def compile_pairs (nodes):
+ result = {}
+ if len(nodes) %2 != 0:
+ nodes.pop(1)
+ pairs = zip(*[iter(nodes)]*2)
+ for pair in pairs:
+ result[pair[0]+'<>'+pair[1]] = pair
+ return result
+
+
+def get_pairs():
+ # TODO
+ # maybe collect cmp from nova service-list
+ config = get_configuration()
+ local_salt_client = init_salt_client()
+ cmp_hosts = config.get('CMP_HOSTS') or []
+ skipped_nodes = config.get('skipped_nodes') or []
+ if skipped_nodes:
+ print "Notice: {0} nodes will be skipped for vm2vm test".format(skipped_nodes)
+ if not cmp_hosts:
+ nodes = local_salt_client.cmd(
+ 'I@nova:compute',
+ 'test.ping',
+ expr_form='compound')
+ cmp_hosts = [node.split('.')[0] for node in nodes.keys() if node not in skipped_nodes]
+ return compile_pairs(cmp_hosts)
+
+
+def get_hw_pairs():
+ config = get_configuration()
+ local_salt_client = init_salt_client()
+ hw_nodes = config.get('HW_NODES') or []
+ skipped_nodes = config.get('skipped_nodes') or []
+ if skipped_nodes:
+ print "Notice: {0} nodes will be skipped for hw2hw test".format(skipped_nodes)
+ if not hw_nodes:
+ nodes = local_salt_client.cmd(
+ 'I@salt:control or I@nova:compute',
+ 'test.ping',
+ expr_form='compound')
+ hw_nodes = [node for node in nodes.keys() if node not in skipped_nodes]
+ print local_salt_client.cmd(expr_form='compound', tgt="L@"+','.join(hw_nodes),
+ fun='pkg.install', param=['iperf'])
+ return compile_pairs(hw_nodes)
+
+def get_configuration():
+ """function returns configuration for environment
+ and for test if it's specified"""
+
+ global_config_file = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), "../global_config.yaml")
+ with open(global_config_file, 'r') as file:
+ global_config = yaml.load(file)
+ for param in global_config.keys():
+ if param in os.environ.keys():
+ if ',' in os.environ[param]:
+ global_config[param] = []
+ for item in os.environ[param].split(','):
+ global_config[param].append(item)
+ else:
+ global_config[param] = os.environ[param]
+
+ return global_config
diff --git a/test_set/cvp-spt/utils/helpers.py b/test_set/cvp-spt/utils/helpers.py
new file mode 100644
index 0000000..97a3bae
--- /dev/null
+++ b/test_set/cvp-spt/utils/helpers.py
@@ -0,0 +1,79 @@
+import texttable as tt
+
+class helpers(object):
+ def __init__ (self, local_salt_client):
+ self.local_salt_client = local_salt_client
+
+ def start_iperf_between_hosts(self, global_results, node_i, node_j, ip_i, ip_j, net_name):
+ result = []
+ direct_raw_results = self.start_iperf_client(node_i, ip_j)
+ result.append(direct_raw_results)
+ print "1 forward"
+ forward = "1 thread:\n"
+ forward += direct_raw_results + " Gbits/sec"
+
+ direct_raw_results = self.start_iperf_client(node_i, ip_j, 10)
+ result.append(direct_raw_results)
+ print "10 forward"
+ forward += "\n\n10 thread:\n"
+ forward += direct_raw_results + " Gbits/sec"
+
+ reverse_raw_results = self.start_iperf_client(node_j, ip_i)
+ result.append(reverse_raw_results)
+ print "1 backward"
+ backward = "1 thread:\n"
+ backward += reverse_raw_results + " Gbits/sec"
+
+ reverse_raw_results = self.start_iperf_client(node_j, ip_i, 10)
+ result.append(reverse_raw_results)
+ print "10 backward"
+ backward += "\n\n10 thread:\n"
+ backward += reverse_raw_results + " Gbits/sec"
+ global_results.append([node_i, node_j,
+ net_name, forward, backward])
+
+ self.kill_iperf_processes(node_i)
+ self.kill_iperf_processes(node_j)
+ return result
+
+ def draw_table_with_results(self, global_results):
+ tab = tt.Texttable()
+ header = [
+ 'node name 1',
+ 'node name 2',
+ 'network',
+ 'bandwidth >',
+ 'bandwidth <',
+ ]
+ tab.set_cols_align(['l', 'l', 'l', 'l', 'l'])
+ tab.set_cols_width([27, 27, 15, 20, '20'])
+ tab.header(header)
+ for row in global_results:
+ tab.add_row(row)
+ s = tab.draw()
+ print s
+
+ def start_iperf_client(self, minion_name, target_ip, thread_count=None):
+ iperf_command = 'timeout --kill-after=20 19 iperf -c {0}'.format(target_ip)
+ if thread_count:
+ iperf_command += ' -P {0}'.format(thread_count)
+ output = self.local_salt_client.cmd(tgt=minion_name,
+ fun='cmd.run',
+ param=[iperf_command])
+ # self.kill_iperf_processes(minion_name)
+ try:
+ result = output.values()[0].split('\n')[-1].split(' ')[-2:]
+ if result[1] == 'Mbits/sec':
+ return str(float(result[0])*0.001)
+ if result[1] != 'Gbits/sec':
+ return "0"
+ return result[0]
+ except:
+ print "No iperf result between {} and {} (maybe they don't have connectivity)".format(minion_name, target_ip)
+
+
+ def kill_iperf_processes(self, minion_name):
+ kill_command = "for pid in $(pgrep iperf); do kill $pid; done"
+ output = self.local_salt_client.cmd(tgt=minion_name,
+ fun='cmd.run',
+ param=[kill_command])
diff --git a/test_set/cvp-spt/utils/os_client.py b/test_set/cvp-spt/utils/os_client.py
new file mode 100644
index 0000000..c17617f
--- /dev/null
+++ b/test_set/cvp-spt/utils/os_client.py
@@ -0,0 +1,396 @@
+from cinderclient import client as cinder_client
+from glanceclient import client as glance_client
+from keystoneauth1 import identity as keystone_identity
+from keystoneauth1 import session as keystone_session
+from keystoneclient.v3 import client as keystone_client
+from neutronclient.v2_0 import client as neutron_client
+from novaclient import client as novaclient
+
+import os
+import random
+import time
+
+
+class OfficialClientManager(object):
+ """Manager that provides access to the official python clients for
+ calling various OpenStack APIs.
+ """
+
+ CINDERCLIENT_VERSION = 3
+ GLANCECLIENT_VERSION = 2
+ KEYSTONECLIENT_VERSION = 3
+ NEUTRONCLIENT_VERSION = 2
+ NOVACLIENT_VERSION = 2
+ INTERFACE = 'admin'
+ if "OS_ENDPOINT_TYPE" in os.environ.keys():
+ INTERFACE = os.environ["OS_ENDPOINT_TYPE"]
+
+ def __init__(self, username=None, password=None,
+ tenant_name=None, auth_url=None, endpoint_type="internalURL",
+ cert=False, domain="Default", **kwargs):
+ self.traceback = ""
+
+ self.client_attr_names = [
+ "auth",
+ "compute",
+ "network",
+ "volume",
+ "image",
+ ]
+ self.username = username
+ self.password = password
+ self.tenant_name = tenant_name
+ self.project_name = tenant_name
+ self.auth_url = auth_url
+ self.endpoint_type = endpoint_type
+ self.cert = cert
+ self.domain = domain
+ self.kwargs = kwargs
+
+ # Lazy clients
+ self._auth = None
+ self._compute = None
+ self._network = None
+ self._volume = None
+ self._image = None
+
+ @classmethod
+ def _get_auth_session(cls, username=None, password=None,
+ tenant_name=None, auth_url=None, cert=None,
+ domain='Default'):
+ if None in (username, password, tenant_name):
+ print(username, password, tenant_name)
+ msg = ("Missing required credentials for identity client. "
+ "username: {username}, password: {password}, "
+ "tenant_name: {tenant_name}").format(
+ username=username,
+ password=password,
+ tenant_name=tenant_name, )
+ raise msg
+
+ if cert and "https" not in auth_url:
+ auth_url = auth_url.replace("http", "https")
+
+ if cls.KEYSTONECLIENT_VERSION == (2, 0):
+ # auth_url = "{}{}".format(auth_url, "v2.0/")
+ auth = keystone_identity.v2.Password(
+ username=username,
+ password=password,
+ auth_url=auth_url,
+ tenant_name=tenant_name)
+ else:
+ auth_url = "{}{}".format(auth_url, "/v3")
+ auth = keystone_identity.v3.Password(
+ auth_url=auth_url,
+ user_domain_name=domain,
+ username=username,
+ password=password,
+ project_domain_name=domain,
+ project_name=tenant_name)
+
+ auth_session = keystone_session.Session(auth=auth, verify=cert)
+ # auth_session.get_auth_headers()
+ return auth_session
+
+ @classmethod
+ def get_auth_client(cls, username=None, password=None,
+ tenant_name=None, auth_url=None, cert=None,
+ domain='Default', **kwargs):
+ session = cls._get_auth_session(
+ username=username,
+ password=password,
+ tenant_name=tenant_name,
+ auth_url=auth_url,
+ cert=cert,
+ domain=domain)
+ keystone = keystone_client.Client(version=cls.KEYSTONECLIENT_VERSION,
+ session=session, **kwargs)
+ keystone.management_url = auth_url
+ return keystone
+
+ @classmethod
+ def get_compute_client(cls, username=None, password=None,
+ tenant_name=None, auth_url=None, cert=None,
+ domain='Default', **kwargs):
+ session = cls._get_auth_session(
+ username=username, password=password, tenant_name=tenant_name,
+ auth_url=auth_url, cert=cert, domain=domain)
+ service_type = 'compute'
+ compute_client = novaclient.Client(
+ version=cls.NOVACLIENT_VERSION, session=session,
+ service_type=service_type, os_cache=False, **kwargs)
+ return compute_client
+
+ @classmethod
+ def get_network_client(cls, username=None, password=None,
+ tenant_name=None, auth_url=None, cert=None,
+ domain='Default', **kwargs):
+ session = cls._get_auth_session(
+ username=username, password=password, tenant_name=tenant_name,
+ auth_url=auth_url, cert=cert, domain=domain)
+ service_type = 'network'
+ return neutron_client.Client(
+ service_type=service_type, session=session, interface=cls.INTERFACE, **kwargs)
+
+ @classmethod
+ def get_volume_client(cls, username=None, password=None,
+ tenant_name=None, auth_url=None, cert=None,
+ domain='Default', **kwargs):
+ session = cls._get_auth_session(
+ username=username, password=password, tenant_name=tenant_name,
+ auth_url=auth_url, cert=cert, domain=domain)
+ service_type = 'volume'
+ return cinder_client.Client(
+ version=cls.CINDERCLIENT_VERSION,
+ service_type=service_type,
+ interface=cls.INTERFACE,
+ session=session, **kwargs)
+
+ @classmethod
+ def get_image_client(cls, username=None, password=None,
+ tenant_name=None, auth_url=None, cert=None,
+ domain='Default', **kwargs):
+ session = cls._get_auth_session(
+ username=username, password=password, tenant_name=tenant_name,
+ auth_url=auth_url, cert=cert, domain=domain)
+ service_type = 'image'
+ return glance_client.Client(
+ version=cls.GLANCECLIENT_VERSION,
+ service_type=service_type,
+ session=session, interface=cls.INTERFACE,
+ **kwargs)
+
+ @property
+ def auth(self):
+ if self._auth is None:
+ self._auth = self.get_auth_client(
+ self.username, self.password, self.tenant_name, self.auth_url,
+ self.cert, self.domain, endpoint_type=self.endpoint_type
+ )
+ return self._auth
+
+ @property
+ def compute(self):
+ if self._compute is None:
+ self._compute = self.get_compute_client(
+ self.username, self.password, self.tenant_name, self.auth_url,
+ self.cert, self.domain, endpoint_type=self.endpoint_type
+ )
+ return self._compute
+
+ @property
+ def network(self):
+ if self._network is None:
+ self._network = self.get_network_client(
+ self.username, self.password, self.tenant_name, self.auth_url,
+ self.cert, self.domain, endpoint_type=self.endpoint_type
+ )
+ return self._network
+
+ @property
+ def volume(self):
+ if self._volume is None:
+ self._volume = self.get_volume_client(
+ self.username, self.password, self.tenant_name, self.auth_url,
+ self.cert, self.domain, endpoint_type=self.endpoint_type
+ )
+ return self._volume
+
+ @property
+ def image(self):
+ if self._image is None:
+ self._image = self.get_image_client(
+ self.username, self.password, self.tenant_name, self.auth_url,
+ self.cert, self.domain
+ )
+ return self._image
+
+
+class OSCliActions(object):
+ def __init__(self, os_clients):
+ self.os_clients = os_clients
+
+ def get_admin_tenant(self):
+ # TODO Keystone v3 doesnt have tenants attribute
+ return self.os_clients.auth.projects.find(name="admin")
+
+ # TODO: refactor
+ def get_cirros_image(self):
+ images_list = list(self.os_clients.image.images.list(name='TestVM'))
+ if images_list:
+ image = images_list[0]
+ else:
+ image = self.os_clients.image.images.create(
+ name="TestVM",
+ disk_format='qcow2',
+ container_format='bare')
+ with file_cache.get_file(settings.CIRROS_QCOW2_URL) as f:
+ self.os_clients.image.images.upload(image.id, f)
+ return image
+
+ def get_internal_network(self):
+ networks = [
+ net for net in self.os_clients.network.list_networks()["networks"]
+ if net["admin_state_up"] and not net["router:external"] and
+ len(net["subnets"])
+ ]
+ if networks:
+ net = networks[0]
+ else:
+ net = self.create_network_resources()
+ return net
+
+ def get_external_network(self):
+ networks = [
+ net for net in self.os_clients.network.list_networks()["networks"]
+ if net["admin_state_up"] and net["router:external"] and
+ len(net["subnets"])
+ ]
+ if networks:
+ ext_net = networks[0]
+ else:
+ ext_net = self.create_fake_external_network()
+ return ext_net
+
+ def create_flavor(self, name, ram=256, vcpus=1, disk=2):
+ return self.os_clients.compute.flavors.create(name, ram, vcpus, disk)
+
+ def create_sec_group(self, rulesets=None):
+ if rulesets is None:
+ rulesets = [
+ {
+ # ssh
+ 'ip_protocol': 'tcp',
+ 'from_port': 22,
+ 'to_port': 22,
+ 'cidr': '0.0.0.0/0',
+ },
+ {
+ # iperf
+ 'ip_protocol': 'tcp',
+ 'from_port':5001,
+ 'to_port': 5001,
+ 'cidr': '0.0.0.0/0',
+ },
+ {
+ # ping
+ 'ip_protocol': 'icmp',
+ 'from_port': -1,
+ 'to_port': -1,
+ 'cidr': '0.0.0.0/0',
+ }
+ ]
+ sg_name = "spt-test-secgroup-{}".format(random.randrange(100, 999))
+ sg_desc = sg_name + " SPT"
+ secgroup = self.os_clients.compute.security_groups.create(
+ sg_name, sg_desc)
+ for ruleset in rulesets:
+ self.os_clients.compute.security_group_rules.create(
+ secgroup.id, **ruleset)
+ return secgroup
+
+
+ def wait(predicate, interval=5, timeout=60, timeout_msg="Waiting timed out"):
+ start_time = time.time()
+ if not timeout:
+ return predicate()
+ while not predicate():
+ if start_time + timeout < time.time():
+ raise exceptions.TimeoutError(timeout_msg)
+
+ seconds_to_sleep = max(
+ 0,
+ min(interval, start_time + timeout - time.time()))
+ time.sleep(seconds_to_sleep)
+
+ return timeout + start_time - time.time()
+
+ def create_basic_server(self, image=None, flavor=None, net=None,
+ availability_zone=None, sec_groups=(),
+ keypair=None,
+ wait_timeout=3 * 60):
+ os_conn = self.os_clients
+ image = image or self.get_cirros_image()
+ flavor = flavor or self.get_micro_flavor()
+ net = net or self.get_internal_network()
+ kwargs = {}
+ if sec_groups:
+ kwargs['security_groups'] = sec_groups
+ server = os_conn.compute.servers.create(
+ "spt-test-server-{}".format(random.randrange(100, 999)),
+ image, flavor, nics=[{"net-id": net["id"]}],
+ availability_zone=availability_zone, key_name=keypair, **kwargs)
+ # TODO
+ #if wait_timeout:
+ # self.wait(
+ # lambda: os_conn.compute.servers.get(server).status == "ACTIVE",
+ # timeout=wait_timeout,
+ # timeout_msg=(
+ # "Create server {!r} failed by timeout. "
+ # "Please, take a look at OpenStack logs".format(server.id)))
+ return server
+
+ def create_network(self, tenant_id):
+ net_name = "spt-test-net-{}".format(random.randrange(100, 999))
+ net_body = {
+ 'network': {
+ 'name': net_name,
+ 'tenant_id': tenant_id
+ }
+ }
+ net = self.os_clients.network.create_network(net_body)['network']
+ return net
+ #yield net
+ #self.os_clients.network.delete_network(net['id'])
+
+ def create_subnet(self, net, tenant_id, cidr=None):
+ subnet_name = "spt-test-subnet-{}".format(random.randrange(100, 999))
+ subnet_body = {
+ 'subnet': {
+ "name": subnet_name,
+ 'network_id': net['id'],
+ 'ip_version': 4,
+ 'cidr': cidr if cidr else '10.1.7.0/24',
+ 'tenant_id': tenant_id
+ }
+ }
+ subnet = self.os_clients.network.create_subnet(subnet_body)['subnet']
+ return subnet
+ #yield subnet
+ #self.os_clients.network.delete_subnet(subnet['id'])
+
+ def create_router(self, ext_net, tenant_id):
+ name = 'spt-test-router-{}'.format(random.randrange(100, 999))
+ router_body = {
+ 'router': {
+ 'name': name,
+ 'external_gateway_info': {
+ 'network_id': ext_net['id']
+ },
+ 'tenant_id': tenant_id
+ }
+ }
+ router = self.os_clients.network.create_router(router_body)['router']
+ return router
+ #yield router
+ #self.os_clients.network.delete_router(router['id'])
+
+ def create_network_resources(self):
+ tenant_id = self.get_admin_tenant().id
+ ext_net = self.get_external_network()
+ net = self.create_network(tenant_id)
+ subnet = self.create_subnet(net, tenant_id)
+ #router = self.create_router(ext_net, tenant_id)
+ #self.os_clients.network.add_interface_router(
+ # router['id'], {'subnet_id': subnet['id']})
+
+ private_net_id = net['id']
+ # floating_ip_pool = ext_net['id']
+
+ return net
+ #yield private_net_id, floating_ip_pool
+ #yield private_net_id
+ #
+ #self.os_clients.network.remove_interface_router(
+ # router['id'], {'subnet_id': subnet['id']})
+ #self.os_clients.network.remove_gateway_router(router['id'])
diff --git a/test_set/cvp-spt/utils/ssh.py b/test_set/cvp-spt/utils/ssh.py
new file mode 100644
index 0000000..66551eb
--- /dev/null
+++ b/test_set/cvp-spt/utils/ssh.py
@@ -0,0 +1,140 @@
+import cStringIO
+import logging
+import select
+import utils
+import paramiko
+
+
+logger = logging.getLogger(__name__)
+
+# Suppress paramiko logging
+logging.getLogger("paramiko").setLevel(logging.WARNING)
+
+
+class SSHTransport(object):
+ def __init__(self, address, username, password=None,
+ private_key=None, look_for_keys=False, *args, **kwargs):
+
+ self.address = address
+ self.username = username
+ self.password = password
+ if private_key is not None:
+ self.private_key = paramiko.RSAKey.from_private_key(
+ cStringIO.StringIO(private_key))
+ else:
+ self.private_key = None
+
+ self.look_for_keys = look_for_keys
+ self.buf_size = 1024
+ self.channel_timeout = 10.0
+
+ def _get_ssh_connection(self):
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(
+ paramiko.AutoAddPolicy())
+ ssh.connect(self.address, username=self.username,
+ password=self.password, pkey=self.private_key,
+ timeout=self.channel_timeout)
+ logger.debug("Successfully connected to: {0}".format(self.address))
+ return ssh
+
+ def _get_sftp_connection(self):
+ transport = paramiko.Transport((self.address, 22))
+ transport.connect(username=self.username,
+ password=self.password,
+ pkey=self.private_key)
+
+ return paramiko.SFTPClient.from_transport(transport)
+
+ def exec_sync(self, cmd):
+ logger.debug("Executing {0} on host {1}".format(cmd, self.address))
+ ssh = self._get_ssh_connection()
+ transport = ssh.get_transport()
+ channel = transport.open_session()
+ channel.fileno()
+ channel.exec_command(cmd)
+ channel.shutdown_write()
+ out_data = []
+ err_data = []
+ poll = select.poll()
+ poll.register(channel, select.POLLIN)
+
+ while True:
+ ready = poll.poll(self.channel_timeout)
+ if not any(ready):
+ continue
+ if not ready[0]:
+ continue
+ out_chunk = err_chunk = None
+ if channel.recv_ready():
+ out_chunk = channel.recv(self.buf_size)
+ out_data += out_chunk,
+ if channel.recv_stderr_ready():
+ err_chunk = channel.recv_stderr(self.buf_size)
+ err_data += err_chunk,
+ if channel.closed and not err_chunk and not out_chunk:
+ break
+ exit_status = channel.recv_exit_status()
+ logger.debug("Command {0} executed with status: {1}"
+ .format(cmd, exit_status))
+ return (
+ exit_status, ''.join(out_data).strip(), ''.join(err_data).strip())
+
+ def exec_command(self, cmd):
+ exit_status, stdout, stderr = self.exec_sync(cmd)
+ return stdout
+
+ def check_call(self, command, error_info=None, expected=None,
+ raise_on_err=True):
+ """Execute command and check for return code
+ :type command: str
+ :type error_info: str
+ :type expected: list
+ :type raise_on_err: bool
+ :rtype: ExecResult
+ :raises: DevopsCalledProcessError
+ """
+ if expected is None:
+ expected = [0]
+ ret = self.exec_sync(command)
+ exit_code, stdout_str, stderr_str = ret
+ if exit_code not in expected:
+ message = (
+ "{append}Command '{cmd}' returned exit code {code} while "
+ "expected {expected}\n"
+ "\tSTDOUT:\n"
+ "{stdout}"
+ "\n\tSTDERR:\n"
+ "{stderr}".format(
+ append=error_info + '\n' if error_info else '',
+ cmd=command,
+ code=exit_code,
+ expected=expected,
+ stdout=stdout_str,
+ stderr=stderr_str
+ ))
+ logger.error(message)
+ if raise_on_err:
+ exit()
+ return ret
+
+ def put_file(self, source_path, destination_path):
+ sftp = self._get_sftp_connection()
+ sftp.put(source_path, destination_path)
+ sftp.close()
+
+ def get_file(self, source_path, destination_path):
+ sftp = self._get_sftp_connection()
+ sftp.get(source_path, destination_path)
+ sftp.close()
+
+
+class prepare_iperf(object):
+
+ def __init__(self,fip,user='ubuntu',password='password', private_key=None):
+ transport = SSHTransport(fip, user, password, private_key)
+ config = utils.get_configuration()
+ preparation_cmd = config.get('iperf_prep_string') or ['']
+ transport.exec_command(preparation_cmd)
+ transport.exec_command('sudo apt-get update; sudo apt-get install -y iperf')
+ transport.exec_command('nohup iperf -s > file 2>&1 &')