def _install_start_webserver(cls, ip_address, ssh_key, start_id): local_file = pkg_resources.resource_filename( 'octavia_tempest_plugin.contrib.httpd', 'httpd.bin') dest_file = '/dev/shm/httpd.bin' linux_client = remote_client.RemoteClient( ip_address, CONF.validation.image_ssh_user, pkey=ssh_key) linux_client.validate_authentication() with tempfile.NamedTemporaryFile() as key: key.write(ssh_key.encode('utf-8')) key.flush() cmd = ("scp -v -o UserKnownHostsFile=/dev/null " "-o StrictHostKeyChecking=no " "-o ConnectTimeout={0} -o ConnectionAttempts={1} " "-i {2} {3} {4}@{5}:{6}").format( CONF.load_balancer.scp_connection_timeout, CONF.load_balancer.scp_connection_attempts, key.name, local_file, CONF.validation.image_ssh_user, ip_address, dest_file) args = shlex.split(cmd) subprocess_args = { 'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT, 'cwd': None } proc = subprocess.Popen(args, **subprocess_args) stdout, stderr = proc.communicate() if proc.returncode != 0: raise exceptions.CommandFailed(proc.returncode, cmd, stdout, stderr) linux_client.exec_command('sudo screen -d -m {0} -port 80 ' '-id {1}'.format(dest_file, start_id)) linux_client.exec_command('sudo screen -d -m {0} -port 81 ' '-id {1}'.format(dest_file, start_id + 1))
def test_013_check_dhcp_lease(self): """Whether IP address was obtained by dhcp?""" if self.ctx.instance3 is None: self.skipTest("Instance 3 was not initialized") ssh = remote_client.RemoteClient(self.ctx.instance3.ip_address, self.ssh_user, pkey=self.keypair.material) resp = ssh.exec_command("ps -eo comm,args | grep -m 1 dhclient") args = resp.split() if len(args) <= 2 or not args[0].startswith('dhclient'): raise base.TestCasePreparationError() is_lf = False lease_file = "/var/lib/dhcp/dhclient.leases" for arg in args: if is_lf: lease_file = arg is_lf = False elif arg == "-lf": is_lf = True resp = ssh.exec_command("test -f %s && echo 1 || echo 0" % lease_file) self.assertEqual(1, int(resp)) self.ctx.lease_file = lease_file resp = ssh.exec_command("grep 'fixed-address ' %s | tail -n 1 | " "awk '{ print $2 }' | sed -e 's/;//'" % lease_file) lines = resp.splitlines() self.assertEqual(1, len(lines)) self.assertEqual(self.ctx.instance3.private_ip_address, lines[0]) date = ssh.exec_command("date -u +%Y/%m/%d%H:%M:%S") self.assertTrue(date) resp = ssh.exec_command("grep 'renew ' %s | tail -n 1 | " "awk '{ print $3$4 }' | sed -e 's/;//'" % lease_file) self.assertLess(date, resp)
def setUpClass(cls): super(UnixBenchTest, cls).setUpClass() cls._load_benchmark_data("UnixBenchTest") cfg = cls.config.cloudscaling image_name = cfg.general_image_name cls.ssh_user = cfg.general_ssh_user_name cls.image_id = cls._prepare_image_id(image_name) cls.keypair = cls._prepare_key_pair() sg = cls._prepare_security_group() cls.sec_group_name = sg.name # NOTE(apavlov): ec2-run-instances --key KEYPAIR IMAGE reservation = cls.ec2_client.run_instances(cls.image_id, instance_type=cls.instance_type, key_name=cls.keypair.name, security_groups=(cls.sec_group_name,)) cls.addResourceCleanUp(cls.destroy_reservation, reservation) cls.instance = reservation.instances[0] LOG.info("state: %s", cls.instance.state) # NOTE(apavlov): wait until it runs (ec2-describe-instances INSTANCE) cls._wait_instance_state(cls.instance, "running") cls._prepare_public_ip(cls.instance) ip_address = cls._prepare_public_ip(cls.instance) cls.ssh = remote_client.RemoteClient(ip_address, cls.ssh_user, pkey=cls.keypair.material)
def test_022_check_broadcast_visible(self): """Is broadcast traffic visible?""" if self.ctx.instance3 is None: self.skipTest("Instance 3 was not initialized") with self.TcpDumpRunner(self.ctx.instance3, self.ssh_user, self.keypair, "ip broadcast") as tdump: ssh = remote_client.RemoteClient(self.instance1.ip_address, self.ssh_user, pkey=self.keypair.material) ssh.exec_command("echo ping |" "socat - UDP4-DATAGRAM:255.255.255.255:6666," "broadcast") if not tdump.stop(): raise base.TestCasePreparationError() resp = tdump.get_result() captured = "" for line in resp.splitlines(): if line.endswith(" captured"): captured = line break tokens = captured.split() packets = int(tokens[0]) self.assertEqual(0, packets)
def __init__(self, instance, ssh_user, ssh_keypair, parameters): ssh = remote_client.RemoteClient(instance.ip_address, ssh_user, pkey=ssh_keypair.material) ssh.ssh_client.channel_timeout = float(self.timeout) self.ssh = ssh self.parameters = parameters self.thread = None
def _enable_ipv6_nic_webserver(cls, ip_address, ssh_key, ipv6_address, ipv6_prefix): linux_client = remote_client.RemoteClient( ip_address, CONF.validation.image_ssh_user, pkey=ssh_key) linux_client.validate_authentication() linux_client.exec_command('sudo ip address add {0}/{1} dev ' 'eth0'.format(ipv6_address, ipv6_prefix))
def _wait_for_validation(self, server, validation_resources): linux_client = remote_client.RemoteClient( self.get_server_ip(server, validation_resources), self.image_ssh_user, self.image_ssh_password, validation_resources['keypair']['private_key'], server=server, servers_client=self.servers_client) linux_client.validate_authentication()
def test_debug_ssh_without_console(self, mock_exec_command, mock_debug): mock_exec_command.side_effect = lib_exc.SSHTimeout server = {'id': 'fake_id'} client = remote_client.RemoteClient('192.168.1.10', 'username', server=server) self.assertRaises(lib_exc.SSHTimeout, client.exec_command, 'ls') mock_debug.assert_called_with( 'Caller: %s. Timeout trying to ssh to server %s', 'TestRemoteClient:test_debug_ssh_without_console', server)
def test_debug_ssh_with_console(self, mock_exec_command, mock_debug): mock_exec_command.side_effect = lib_exc.SSHTimeout server = {'id': 'fake_id'} client = remote_client.RemoteClient('192.168.1.10', 'username', server=server, servers_client=FakeServersClient()) self.assertRaises(lib_exc.SSHTimeout, client.exec_command, 'ls') mock_debug.assert_called_with( 'Console log for server %s: %s', server['id'], 'fake_output')
def install_iperf(instance): try: ssh = remote_client.RemoteClient(instance.ip_address, cls.ssh_user, pkey=cls.keypair.material) except exceptions.SSHTimeout: raise base.TestCasePreparationError() ssh.exec_command("sudo apt-get update && sudo apt-get upgrade -y") ssh.exec_command("sudo apt-get update") ssh.exec_command("sudo apt-get install iperf")
def test_014_check_dhcp_sends_mtu_size(self): """Check DHCP sends MTU size.""" if self.ctx.lease_file is None: self.skipTest("Dhcp lease file was not found") ssh = remote_client.RemoteClient(self.ctx.instance3.ip_address, self.ssh_user, pkey=self.keypair.material) resp = ssh.exec_command("grep 'option interface-mtu ' %s" % self.ctx.lease_file) self.assertLess(0, len(resp.splitlines()))
def test_015_check_dhcp_distribute_host_name_size(self): """Check DHCP distributes host hame.""" if self.ctx.lease_file is None: self.skipTest("Dhcp lease file was not found") ssh = remote_client.RemoteClient(self.ctx.instance3.ip_address, self.ssh_user, pkey=self.keypair.material) resp = ssh.exec_command("grep 'option host-name ' %s" % self.ctx.lease_file) self.assertLess(0, len(resp.splitlines()))
def test_011_check_network_gateway(self): """Is gateway local to subnet?""" ssh = remote_client.RemoteClient(self.instance1.ip_address, self.ssh_user, pkey=self.keypair.material) resp = ssh.exec_command("route -n | awk '{ if ($1==\"0.0.0.0\" && " "$4 ~ /.*G.*/) print $2 }'") lines = resp.splitlines() self.assertEqual(1, len(lines)) gateway = netaddr.IPAddress(lines[0]) self.ctx.gateway = gateway self.assertTrue(gateway in self.subnet_cidr)
def _has_vip_traffic(cls, ip_address, log_prefix): ssh_key = cls._get_amphora_ssh_key() linux_client = remote_client.RemoteClient( ip_address, CONF.load_balancer.amphora_ssh_user, pkey=ssh_key) linux_client.validate_authentication() try: linux_client.exec_command('sudo journalctl -t kernel | grep {0}' .format(log_prefix)) return True except exceptions.SSHExecCommandFailed: return False
def test_102_tune_nat_instance(self): """Tune NAT in NAT instance""" instance = self.ctx.nat_instance address = instance.ip_address ssh = remote_client.RemoteClient(address, self.ssh_user, pkey=self.keypair.material) ssh.exec_command("sudo iptables -t nat -A POSTROUTING -s %s " "-o eth0 -j MASQUERADE" % str(self.vpc_cidr)) ssh.exec_command("sudo sysctl -w net.ipv4.ip_forward=1") ssh.exec_command("echo $'auto eth1\niface eth1 inet dhcp\n' " "| sudo tee -a /etc/network/interfaces.d/eth1.cfg") ssh.exec_command("sudo ifup eth1")
def __enter__(self): # NOTE(ft): Iperf doesn't close stdout in server mode # but standard exec_command waits for it # so instead of use it we waits for some string in output ssh = remote_client.RemoteClient(self.instance.ip_address, self.ssh_user, pkey=self.ssh_keypair.material) ssh_conn = ssh.ssh_client._get_ssh_connection() chan = ssh_conn.get_transport().open_session() chan.get_pty() # NOTE(ft): to stop iperf with session end chan.fileno() chan.exec_command(self.cmd) started = False out_data = [] err_data = [] select_params = [chan], [], [], ssh.ssh_client.channel_timeout while True: ready = select.select(*select_params) if not any(ready): raise exceptions.TimeoutException( "Cannot start iperf server on host '{1}'.".format( self.host)) if not ready[0]: continue out_chunk = err_chunk = None if chan.recv_ready(): out_chunk = chan.recv(ssh.ssh_client.buf_size) out_data += out_chunk, if chan.recv_stderr_ready(): err_chunk = chan.recv_stderr(ssh.ssh_client.buf_size) err_data += err_chunk, if chan.exit_status_ready(): exit_status = chan.recv_exit_status() if 0 != exit_status or len(err_data) > 0: raise exceptions.SSHExecCommandFailed( command=self.cmd, exit_status=exit_status, strerror=''.join(err_data)) lines = ''.join(out_data).splitlines() for line in lines: if line.startswith("Server listening"): started = True break if (started or chan.closed and not err_chunk and not out_chunk): break self.ssh = ssh self.ssh_conn = ssh_conn self.chan = chan
def test_031_scan_gateway_ports(self): """Are gateway ports closed?""" if self.ctx.gateway is None: self.skipTest("Subnet's gateway was not found") ssh = remote_client.RemoteClient(self.instance1.ip_address, self.ssh_user, pkey=self.keypair.material) ssh.ssh_client.channel_timeout = 600 resp = ssh.exec_command("sudo nmap -PN %s" % str(self.ctx.gateway)) all_closed_msg = ("All 1000 scanned ports on %s are " % str(self.ctx.gateway)) for line in resp.splitlines(): if line.startswith(all_closed_msg): return self.fail("Some gateway ports are open")
def setUpClass(cls): super(VPC_Behavior, cls).setUpClass() cls.TcpDumpRunner.timeout = cls.config.boto.build_timeout cls.subnet = cls._prepare_vpc(cls.vpc_cidr, cls.subnet_cidr) cls.instance1 = cls._run_instance(cls.subnet) cls.instance2 = cls._run_instance(cls.subnet) cls._wait_instance_state(cls.instance1, "running") cls._wait_instance_state(cls.instance2, "running") cls.instance1.ip_address = cls._prepare_public_ip(cls.instance1) ssh = remote_client.RemoteClient(cls.instance1.ip_address, cls.ssh_user, pkey=cls.keypair.material) ssh.exec_command("sudo apt-get update") ssh.exec_command("sudo DEBIAN_FRONTEND=noninteractive apt-get -fqy " "install socat nmap") cls.ctx = cls.Context()
def _log_vip_traffic(cls, amp, log_prefix): ssh_key = cls._get_amphora_ssh_key() linux_client = remote_client.RemoteClient( amp['lb_network_ip'], CONF.load_balancer.amphora_ssh_user, pkey=ssh_key) linux_client.validate_authentication() # Allow logging from non-init namespaces # https://lore.kernel.org/patchwork/patch/673714/ linux_client.exec_command('echo 1 | sudo tee ' '/proc/sys/net/netfilter/nf_log_all_netns') linux_client.exec_command('sudo ip netns exec amphora-haproxy ' 'iptables -I INPUT 1 -d {0} -j LOG ' '--log-prefix "{1}"' .format(amp['ha_ip'], log_prefix))
def test_001_internal_vpc_tcp_150MB_throughput(self): """Measure internal VPC network throughput for 150 MBytes transmit.""" if self.keypair is None: self.skipTest("Environment was not initialized") with IPerfServer(self.instance1, self.ssh_user, self.keypair): ssh = remote_client.RemoteClient(self.instance2.ip_address, self.ssh_user, pkey=self.keypair.material) resp = ssh.exec_command("iperf -c %s -n 150M -x CMSV -y C" % self.instance1.private_ip_address) rate = self._get_rate(resp) self.addDetail( "Current", test_content.text_content("150 MBytes throughput: %s Mbits/sec" % rate)) self._check_test(rate)
def rescue_unrescue(self): rescue_password = uuidutils.generate_uuid() self.rescue_node(self.node['uuid'], rescue_password) self.assertTrue(self.ping_ip_address(self.node_ip, should_succeed=True)) # Open ssh connection to server linux_client = remote_client.RemoteClient( self.node_ip, 'rescue', password=rescue_password, ssh_timeout=CONF.baremetal.rescue_timeout) linux_client.validate_authentication() self.unrescue_node(self.node['uuid']) self.assertTrue(self.ping_ip_address(self.node_ip, should_succeed=True))
def _install_start_webserver(cls, ip_address, ssh_key, start_id): local_file = pkg_resources.resource_filename( 'octavia_tempest_plugin.contrib.httpd', 'httpd.bin') dest_file = '/dev/shm/httpd.bin' linux_client = remote_client.RemoteClient( ip_address, CONF.validation.image_ssh_user, pkey=ssh_key) linux_client.validate_authentication() with tempfile.NamedTemporaryFile() as key: key.write(ssh_key.encode('utf-8')) key.flush() cmd = ("scp -v -o UserKnownHostsFile=/dev/null " "-o StrictHostKeyChecking=no " "-o ConnectTimeout={0} -o ConnectionAttempts={1} " "-i {2} {3} {4}@{5}:{6}").format( CONF.load_balancer.scp_connection_timeout, CONF.load_balancer.scp_connection_attempts, key.name, local_file, CONF.validation.image_ssh_user, ip_address, dest_file) args = shlex.split(cmd) subprocess_args = { 'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT, 'cwd': None } proc = subprocess.Popen(args, **subprocess_args) stdout, stderr = proc.communicate() if proc.returncode != 0: raise exceptions.CommandFailed(proc.returncode, cmd, stdout, stderr) # Enabling memory overcommit allows to run golang static binaries # compiled with a recent golang toolchain (>=1.11). Those binaries # allocate a large amount of virtual memory at init time, and this # allocation fails in tempest's nano flavor (64MB of RAM) # (golang issue reported in https://github.com/golang/go/issues/28114, # follow-up: https://github.com/golang/go/issues/28081) # TODO(gthiemonge): Remove this call when golang issue is resolved. linux_client.exec_command('sudo sh -c "echo 1 > ' '/proc/sys/vm/overcommit_memory"') linux_client.exec_command('sudo screen -d -m {0} -port 80 ' '-id {1}'.format(dest_file, start_id)) linux_client.exec_command('sudo screen -d -m {0} -port 81 ' '-id {1}'.format(dest_file, start_id + 1))
def test_200_check_connectivity(self): """Check inside and outside connectivities""" web_ip = self.ctx.web_instance.ip_address db_ip = self.ctx.db_instance.private_ip_address ssh = remote_client.RemoteClient(web_ip, self.ssh_user, pkey=self.keypair.material) ssh_conn = ssh.ssh_client._get_ssh_connection() sftp = ssh_conn.open_sftp() fr = sftp.file("key.pem", 'wb') fr.set_pipelined(True) fr.write(self.keypair.material) fr.close() ssh_conn.close() ssh.exec_command('chmod 400 key.pem') ssh.exec_command("ssh -i key.pem -o UserKnownHostsFile=/dev/null " "-o StrictHostKeyChecking=no %(user)s@%(ip)s " "curl -s http://google.com" % { "user": self.ssh_user, "ip": db_ip })
def test_102_tune_nat_instance(self): """Tune NAT in NAT instance""" instance = self.ctx.nat_instance address = instance.ip_address ssh = remote_client.RemoteClient(address, self.ssh_user, pkey=self.keypair.material) # NOTE(ft): We must use tty mode, because some images (like Amazon # Linux) has restrictions (requiretty flag in /etc/sudoers) ssh_conn = ssh.ssh_client._get_ssh_connection() chan = ssh_conn.get_transport().open_session() chan.get_pty() chan.exec_command("sudo iptables -t nat -A POSTROUTING -s %s " "-o eth0 -j MASQUERADE" % str(self.vpc_cidr)) chan.close() chan = ssh_conn.get_transport().open_session() chan.get_pty() chan.exec_command("sudo sysctl -w net.ipv4.ip_forward=1") chan.close() ssh_conn.close()
def test_021_check_traffic_visibility(self): """Are other VMs visible?""" if self.ctx.instance3 is None: self.skipTest("Instance 3 was not initialized") with self.TcpDumpRunner(self.ctx.instance3, self.ssh_user, self.keypair, "ip proto \\\\icmp") as tdump: ssh = remote_client.RemoteClient(self.instance1.ip_address, self.ssh_user, pkey=self.keypair.material) ssh.exec_command("ping -c 1 %s" % self.instance2.private_ip_address) if not tdump.stop(): raise base.TestCasePreparationError() resp = tdump.get_result() for line in resp.splitlines(): if line.endswith("packets captured"): captured = line break tokens = captured.split() packets = int(tokens[0]) self.assertEqual(0, packets)
def rescue_instance(self, instance, node, server_ip, servers_client=None): """Rescue the instance, verify we can ping and SSH.""" if servers_client is None: servers_client = self.os_primary.servers_client rescuing_instance = servers_client.rescue_server(instance['id']) rescue_password = rescuing_instance['adminPass'] self.wait_provisioning_state(node['uuid'], BaremetalProvisionStates.RESCUE, timeout=CONF.baremetal.rescue_timeout) waiters.wait_for_server_status(servers_client, instance['id'], 'RESCUE') # Ping server ip self.assertTrue(self.ping_ip_address(server_ip)) # Open ssh connection to server linux_client = remote_client.RemoteClient( server_ip, 'rescue', password=rescue_password, server=self.instance, servers_client=servers_client, ssh_timeout=CONF.baremetal.rescue_timeout) linux_client.validate_authentication()
def test_exec_command(self, mock_ssh_exec_command): client = remote_client.RemoteClient('192.168.1.10', 'username') client.exec_command('ls') mock_ssh_exec_command.assert_called_once_with( 'set -eu -o pipefail; PATH=$PATH:/sbin; ls')
def test_verify_created_server_ephemeral_disk(self): # Verify that the ephemeral disk is created when creating server flavor_base = self.flavors_client.show_flavor( self.flavor_ref)['flavor'] def create_flavor_with_extra_specs(): flavor_with_eph_disk_name = data_utils.rand_name('eph_flavor') flavor_with_eph_disk_id = data_utils.rand_int_id(start=1000) ram = flavor_base['ram'] vcpus = flavor_base['vcpus'] disk = flavor_base['disk'] # Create a flavor with extra specs flavor = (self.flavor_client.create_flavor( name=flavor_with_eph_disk_name, ram=ram, vcpus=vcpus, disk=disk, id=flavor_with_eph_disk_id, ephemeral=1))['flavor'] self.addCleanup(flavor_clean_up, flavor['id']) return flavor['id'] def create_flavor_without_extra_specs(): flavor_no_eph_disk_name = data_utils.rand_name('no_eph_flavor') flavor_no_eph_disk_id = data_utils.rand_int_id(start=1000) ram = flavor_base['ram'] vcpus = flavor_base['vcpus'] disk = flavor_base['disk'] # Create a flavor without extra specs flavor = (self.flavor_client.create_flavor( name=flavor_no_eph_disk_name, ram=ram, vcpus=vcpus, disk=disk, id=flavor_no_eph_disk_id))['flavor'] self.addCleanup(flavor_clean_up, flavor['id']) return flavor['id'] def flavor_clean_up(flavor_id): self.flavor_client.delete_flavor(flavor_id) self.flavor_client.wait_for_resource_deletion(flavor_id) flavor_with_eph_disk_id = create_flavor_with_extra_specs() admin_pass = self.image_ssh_password server_with_eph_disk = self.create_test_server( validatable=True, wait_until='ACTIVE', adminPass=admin_pass, flavor=flavor_with_eph_disk_id) server_with_eph_disk = self.client.show_server( server_with_eph_disk['id'])['server'] linux_client = remote_client.RemoteClient( self.get_server_ip(server_with_eph_disk), self.ssh_user, admin_pass, self.validation_resources['keypair']['private_key'], server=server_with_eph_disk, servers_client=self.client) cmd = 'sudo touch /mnt/tempest.txt' linux_client.exec_command(cmd) lxd = client.Client() profile = lxd.profiles.get( server_with_eph_disk['OS-EXT-SRV-ATTR:instance_name']) tempfile = '%s/tempest.txt' % profile.devices['ephemeral0']['source'] self.assertTrue(os.path.exists(tempfile))
def _run_scenario(self, scenario_func, snapshot=None): # NOTE(apavlov): ec2-run-instances --key KEYPAIR IMAGE reservation = self.ec2_client.run_instances( self.image_id, instance_type=self.instance_type, key_name=self.keypair.name, security_groups=(self.sec_group_name, )) self.addResourceCleanUp(self.destroy_reservation, reservation) instance = reservation.instances[0] LOG.info("state: %s", instance.state) # NOTE(apavlov): wait until it runs (ec2-describe-instances INSTANCE) if instance.state != "running": self.assertInstanceStateWait(instance, "running") # NOTE(apavlov): ec2-create-volume -z ZONE -s SIZE_GB zone = instance.placement volume = self.ec2_client.create_volume(1, zone, snapshot=snapshot) self.addResourceCleanUp(self.destroy_volume_wait, volume) # NOTE(apavlov): wait it (ec2-describe-volumes VOLUME) self.assertVolumeStatusWait(volume, "available") ip_address = self._prepare_public_ip(instance) ssh = remote_client.RemoteClient(ip_address, self.ssh_user, pkey=self.keypair.material) # NOTE(apavlov): ec2-attach-volume -d /dev/XXX -i INSTANCE VOLUME # and wait until it will be available part_lines = ssh.get_partitions().split('\n') volume.attach(instance.id, "/dev/" + self.volume_attach_name) def _volume_state(): volume.update(validate=True) return volume.status self.assertVolumeStatusWait(_volume_state, "in-use") boto_wait.re_search_wait(_volume_state, "in-use") def _part_state(): current = ssh.get_partitions().split('\n') if len(current) > len(part_lines): return 1 if len(current) < len(part_lines): return -1 return 0 boto_wait.state_wait(_part_state, 1) part_lines_new = ssh.get_partitions().split('\n') self.volume_name = utils.detect_new_volume(part_lines, part_lines_new) part_lines = part_lines_new self._correct_ns_if_needed(ssh) snapshot = scenario_func(ssh, volume.id) # NOTE(apavlov): stop this instance(imagine that it will be used) instance.stop() LOG.info("state: %s", instance.state) if instance.state != "stopped": self.assertInstanceStateWait(instance, "stopped") return snapshot
def test_validate_authentication(self, mock_test_connection_auth): client = remote_client.RemoteClient('192.168.1.10', 'username') client.validate_authentication() mock_test_connection_auth.assert_called_once_with()