예제 #1
0
def ssh_copy_id(log, addr, passwords, hop=None):
    """
    Use "ssh-copy-id" to copy ssh id, try passwords if asked for.
    """
    session = None
    try:
        cmd = ("ssh-copy-id -o StrictHostKeyChecking=no -o ControlMaster=auto "
               "-o ControlPath='/var/tmp/%r@%h-%p' "
               "-o ControlPersist=60 -o UserKnownHostsFile=/dev/null "
               f"root@{addr}")
        if hop:
            cmd = hop.get_ssh_cmd() + " -t " + cmd
        session = aexpect.Expect(cmd,
                                 output_func=log.debug,
                                 output_prefix=">> ")
        try:
            session.read_until_any_line_matches(["password:"******"password:"******">> ")
        return False
    finally:
        if session:
            session.close()
예제 #2
0
    def test_badly_behaved(self):
        """
        Make sure avocado can cleanly get out of a loop of badly behaved tests.
        """
        bad_test_basename = ('wontquit-%s' %
                             data_factory.generate_random_string(5))
        bad_test = script.TemporaryScript(bad_test_basename,
                                          BAD_TEST,
                                          'avocado_interrupt_test',
                                          mode=DEFAULT_MODE)

        bad_test.save()

        os.chdir(basedir)
        cmd_line = ('./scripts/avocado run --sysinfo=off --job-results-dir %s '
                    '%s %s %s' %
                    (self.tmpdir, bad_test.path, bad_test.path, bad_test.path))
        proc = aexpect.Expect(command=cmd_line, linesep='')
        proc.read_until_last_line_matches(os.path.basename(bad_test.path))
        proc.sendline('\x03')
        proc.read_until_last_line_matches('Interrupt requested. Waiting 2 '
                                          'seconds for test to finish '
                                          '(ignoring new Ctrl+C until then)')
        # We have to actually wait 2 seconds until the ignore window is over
        time.sleep(2.5)
        proc.sendline('\x03')
        proc.read_until_last_line_matches('TESTS TIME : %d s')
        wait.wait_for(lambda: not proc.is_alive(), timeout=1)

        # Make sure the bad test will be really gone from the process table
        def wait_until_no_badtest():
            bad_test_processes = []

            old_psutil = False
            try:
                process_list = psutil.pids()
            except AttributeError:
                process_list = psutil.get_pid_list()
                old_psutil = True

            for p in process_list:
                try:
                    p_obj = psutil.Process(p)
                    if p_obj is not None:
                        if old_psutil:
                            cmdline_list = psutil.Process(p).cmdline
                        else:
                            cmdline_list = psutil.Process(p).cmdline()
                        if bad_test.path in " ".join(cmdline_list):
                            bad_test_processes.append(p_obj)
                # psutil.NoSuchProcess happens when the original
                # process already ended and left the process table
                except psutil.NoSuchProcess:
                    pass

            return len(bad_test_processes) == 0

        wait.wait_for(wait_until_no_badtest, timeout=2)
        # Make sure the Killing test subprocess message did appear
        self.assertIn('Killing test subprocess', proc.get_output())
예제 #3
0
def remote_scp(command, password_list, log_filename=None, transfer_timeout=600,
               login_timeout=20):
    """
    Transfer files using SCP, given a command line.

    :param command: The command to execute
        (e.g. "scp -r foobar root@localhost:/tmp/").
    :param password_list: Password list to send in reply to a password prompt.
    :param log_filename: If specified, log all output to this file
    :param transfer_timeout: The time duration (in seconds) to wait for the
            transfer to complete.
    :param login_timeout: The maximal time duration (in seconds) to wait for
            each step of the login procedure (i.e. the "Are you sure" prompt
            or the password prompt)
    :raise: Whatever _remote_scp() raises
    """
    logging.debug("Trying to SCP with command '%s', timeout %ss",
                  command, transfer_timeout)
    if log_filename:
        output_func = utils_misc.log_line
        output_params = (log_filename,)
    else:
        output_func = None
        output_params = ()
    session = aexpect.Expect(command,
                             output_func=output_func,
                             output_params=output_params)
    try:
        _remote_scp(session, password_list, transfer_timeout, login_timeout)
    finally:
        session.close()
예제 #4
0
    def test_well_behaved(self):
        """
        Make sure avocado can cleanly get out of a loop of well behaved tests.
        """
        good_test_basename = ('goodtest-%s.py' %
                              data_factory.generate_random_string(5))
        good_test = script.TemporaryScript(good_test_basename,
                                           GOOD_TEST,
                                           'avocado_interrupt_test',
                                           mode=DEFAULT_MODE)
        good_test.save()

        os.chdir(basedir)
        cmd_line = ('%s run --sysinfo=off --job-results-dir %s '
                    '%s %s %s' % (AVOCADO, self.tmpdir, good_test.path,
                                  good_test.path, good_test.path))
        proc = aexpect.Expect(command=cmd_line, linesep='')
        proc.read_until_last_line_matches(os.path.basename(good_test.path))
        proc.sendline('\x03')
        proc.read_until_last_line_matches('TESTS TIME : %d s')
        wait.wait_for(lambda: not proc.is_alive(), timeout=1)

        # Make sure the good test will be really gone from the process table
        def wait_until_no_goodtest():
            good_test_processes = []

            old_psutil = False
            try:
                process_list = psutil.pids()
            except AttributeError:
                process_list = psutil.get_pid_list()
                old_psutil = True

            for p in process_list:
                try:
                    p_obj = psutil.Process(p)
                    if p_obj is not None:
                        if old_psutil:
                            cmdline_list = psutil.Process(p).cmdline
                        else:
                            try:
                                cmdline_list = psutil.Process(p).cmdline()
                            except psutil.AccessDenied:
                                cmdline_list = []
                        if good_test.path in " ".join(cmdline_list):
                            good_test_processes.append(p_obj)
                # psutil.NoSuchProcess happens when the original
                # process already ended and left the process table
                except psutil.NoSuchProcess:
                    pass

            return len(good_test_processes) == 0

        wait.wait_for(wait_until_no_goodtest, timeout=2)
        # Make sure the Killing test subprocess message is not there
        self.assertNotIn('Killing test subprocess', proc.get_output())
        # Make sure the Interrupted requested sentence is there
        self.assertIn(
            'Interrupt requested. Waiting 2 seconds for test to '
            'finish (ignoring new Ctrl+C until then)', proc.get_output())
예제 #5
0
def scp_to_remote(host, port, username, password, local_path, remote_path,
                  limit="", output_func=None, timeout=600):
    """
    Copy files to a remote host (guest) through scp.

    Args:
        limit: Speed limit of file transfer, it means bandwidth.
    """
    transfer_timeout = timeout
    login_timeout = 60
    if limit != "":
        limit = "-l %s" % (limit)

    command = "scp"
    command += (" -r "
                "-v -o UserKnownHostsFile=/dev/null "
                "-o StrictHostKeyChecking=no "
                "-o PreferredAuthentications=password %s "
                r"-P %s %s %s@\[%s\]:%s" %
                (limit, port, pipes.quote(local_path), username, host, pipes.quote(remote_path)))
    logging.debug("Trying to SCP with command '%s', timeout %ss", command, transfer_timeout)
    output_params = ()
    session = aexpect.Expect(command,
                             output_func=output_func,
                             output_params=output_params)
    try:
        _scp_operation(session, password, transfer_timeout, login_timeout)
    finally:
        session.close()
예제 #6
0
def send_data_from_guest_to_host(guest_session,
                                 nc_vsock_bin,
                                 guest_cid,
                                 tmp_file,
                                 file_size=1000):
    """
    Generate a temp file and transfer it from guest to host via vsock

    :param guest_session: Guest session object
    :param nc_vsock_bin: Path to nc-vsock binary
    :param guest_cid: Guest cid to connected
    :param file_size: Desired file size to be transferred
    :return: The host nc-vsock connection process
    """

    cmd_generate = 'dd if=/dev/urandom of=%s count=%s bs=1M' % (tmp_file,
                                                                file_size)
    guest_session.cmd_status(cmd_generate, timeout=600)
    port = random.randrange(1, 6000)
    cmd_transfer = '%s -l %s < %s' % (nc_vsock_bin, port, tmp_file)
    error_context.context(
        'Transfer file from guest via command: %s' % cmd_transfer,
        logging.info)
    guest_session.sendline(cmd_transfer)
    cmd_receive = '%s %s %s > %s' % (nc_vsock_bin, guest_cid, port, tmp_file)
    return aexpect.Expect(cmd_receive,
                          auto_close=True,
                          output_func=utils_misc.log_line,
                          output_params=('%s.log' % tmp_file, ))
예제 #7
0
    def _check_install_key_required(self):
        def _safe_ssh_ping():
            try:
                self._ssh_ping()
                return True
            except (SSHPermissionDeniedError, process.CmdError):
                return None

        if not self.key_file and self.password:
            try:
                self._ssh_ping()
            except (SSHPermissionDeniedError, process.CmdError):
                copy_id_cmd = ('ssh-copy-id -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p %s %s@%s' %
                               (self.port, self.user, self.hostname))
                while True:
                    try:
                        expect = aexpect.Expect(copy_id_cmd)
                        expect.read_until_output_matches(['.*password:'******'Waiting for password-less SSH')

                if result is None:
                    raise SSHPermissionDeniedError('Unable to configure '
                                                   'password less SSH. '
                                                   'Output of %s: %s' %
                                                   (copy_id_cmd,
                                                    expect.get_output()))
                else:
                    self.log.info('Successfully configured SSH key auth')
예제 #8
0
 def test_kill_stopped_sleep(self):
     sleep = process.run("which sleep", ignore_status=True, shell=True)
     if sleep.exit_status:
         self.skipTest("Sleep binary not found in PATH")
     sleep = "'%s 60'" % sleep.stdout.strip()
     proc = aexpect.Expect("./scripts/avocado run %s --job-results-dir %s "
                           "--sysinfo=off --job-timeout 3" %
                           (sleep, self.tmpdir))
     proc.read_until_output_matches(["\(1/1\)"],
                                    timeout=3,
                                    internal_timeout=0.01)
     # We need pid of the avocado, not the shell executing it
     pid = int(process.get_children_pids(proc.get_pid())[0])
     os.kill(pid, signal.SIGTSTP)  # This freezes the process
     deadline = time.time() + 9
     while time.time() < deadline:
         if not proc.is_alive():
             break
         time.sleep(0.1)
     else:
         proc.kill(signal.SIGKILL)
         self.fail("Avocado process still alive 5s after job-timeout:\n%s" %
                   proc.get_output())
     output = proc.get_output()
     self.assertIn(
         "ctrl+z pressed, stopping test", output, "SIGTSTP "
         "message not in the output, test was probably not "
         "stopped.")
     self.assertIn(
         "TIME", output, "TIME not in the output, avocado "
         "probably died unexpectadly")
     self.assertEqual(proc.get_status(), 1, "Avocado did not finish with "
                      "1.")
예제 #9
0
        def _test_unix_communication(session, guest_path, host_path, test):
            """
            Test unix socket communication between host and guest through
            channel
            """
            nc_session = aexpect.Expect('nc -U "%s"' % host_path)
            try:
                # Test message passing from guest to host
                msg = "What hath God wrought"
                try:
                    session.cmd_status('echo "%s" > %s' % (msg, guest_path),
                                       timeout=1)
                except aexpect.ShellTimeoutError as detail:
                    pass
                nc_session.read_until_last_line_matches(msg, timeout=1)

                # Test message passing from host to guest
                nc_session.sendline(msg)
                try:
                    session.cmd_output('cat %s' % guest_path, timeout=1)
                except aexpect.ShellTimeoutError as detail:
                    if detail.output.strip() != msg:
                        test.fail("Expect receive '%s' in guest, "
                                  "But got %s" %
                                  (msg, detail.output))
            finally:
                nc_session.close()
예제 #10
0
 def open_session(self, a_id):
     """
     Restore connection to existing session identified by a_id
     """
     # Allow this to be called more than once w/o consequence
     self.close_session(warn_if_nonexist=self.used)
     aexpect.Expect(a_id=a_id)
     self.used = True
예제 #11
0
 def new_session(self, command):
     """
     Create and set new opaque session object
     """
     # Allow this to be called more than once w/o consequence
     self.close_session(warn_if_nonexist=self.used)
     self.session = aexpect.Expect(command, auto_close=False)
     self.used = True
예제 #12
0
def remote_commander(client, host, port, username, password, prompt,
                     linesep="\n", log_filename=None, timeout=10, path=None):
    """
    Log into a remote host (guest) using SSH/Telnet/Netcat.

    :param client: The client to use ('ssh', 'telnet' or 'nc')
    :param host: Hostname or IP address
    :param port: Port to connect to
    :param username: Username (if required)
    :param password: Password (if required)
    :param prompt: Shell prompt (regular expression)
    :param linesep: The line separator to use when sending lines
            (e.g. '\\n' or '\\r\\n')
    :param log_filename: If specified, log all output to this file
    :param timeout: The maximal time duration (in seconds) to wait for
            each step of the login procedure (i.e. the "Are you sure" prompt
            or the password prompt)
    :param path: The path to place where remote_runner.py is placed.
    :raise LoginBadClientError: If an unknown client is requested
    :raise: Whatever handle_prompts() raises
    :return: A ShellSession object.
    """
    if path is None:
        path = data_dir.get_tmp_dir()
    if client == "ssh":
        cmd = ("ssh -o UserKnownHostsFile=/dev/null "
               "-o PreferredAuthentications=password "
               "-p %s %s@%s %s agent_base64" %
               (port, username, host, os.path.join(path, "remote_runner.py")))
    elif client == "telnet":
        cmd = "telnet -l %s %s %s" % (username, host, port)
    elif client == "nc":
        cmd = "nc %s %s" % (host, port)
    else:
        raise LoginBadClientError(client)

    logging.debug("Login command: '%s'", cmd)
    session = aexpect.Expect(cmd, linesep=linesep)
    try:
        handle_prompts(session, username, password, prompt, timeout)
    except Exception:
        session.close()
        raise
    if log_filename:
        log_file = utils_misc.get_log_filename(log_filename)
        session.set_output_func(utils_misc.log_line)
        session.set_output_params((log_file,))
        session.set_log_file(os.path.basename(log_file))

    session.send_ctrl("raw")
    # Wrap io interfaces.
    inw = messenger.StdIOWrapperInBase64(session._get_fd("tail"))
    outw = AexpectIOWrapperOut(session)
    # Create commander

    cmd = remote_master.CommanderMaster(inw, outw, False)
    return cmd
예제 #13
0
def nc_vsock_connect(nc_vsock_bin, guest_cid, port):
    """
    Connect to vsock port from host, cmd: nc-vsock $guest_cid $port

    :param nc_vsock_bin: path of binary nc-vsock
    :param guest_cid: guest cid to connect
    :param port: port to connect
    :return: The vsock session from host side, being waiting for input
    """
    nc_vsock_cmd = "%s %s %s" % (nc_vsock_bin, guest_cid, port)
    logging.info("Connect to the vsock port on host: %s", nc_vsock_cmd)
    return aexpect.Expect(nc_vsock_cmd,
                          auto_close=False,
                          output_func=utils_misc.log_line,
                          output_params=("vsock_%s_%s" % (guest_cid, port), ))
예제 #14
0
 def test_kill_stopped_sleep(self):
     sleep = process.run("which sleep", ignore_status=True, shell=True)
     if sleep.exit_status:
         self.skipTest("Sleep binary not found in PATH")
     sleep = "'%s 60'" % sleep.stdout.strip()
     proc = aexpect.Expect("./scripts/avocado run %s --job-results-dir %s "
                           "--sysinfo=off --job-timeout 3" %
                           (sleep, self.tmpdir))
     proc.read_until_output_matches(["\(1/1\)"],
                                    timeout=3,
                                    internal_timeout=0.01)
     # We need pid of the avocado, not the shell executing it
     pid = int(process.get_children_pids(proc.get_pid())[0])
     os.kill(pid, signal.SIGTSTP)  # This freezes the process
     deadline = time.time() + 9
     while time.time() < deadline:
         if not proc.is_alive():
             break
         time.sleep(0.1)
     else:
         proc.kill(signal.SIGKILL)
         self.fail("Avocado process still alive 5s after job-timeout:\n%s" %
                   proc.get_output())
     output = proc.get_output()
     self.assertIn(
         "ctrl+z pressed, stopping test", output, "SIGTSTP "
         "message not in the output, test was probably not "
         "stopped.")
     self.assertIn(
         "TIME", output, "TIME not in the output, avocado "
         "probably died unexpectadly")
     self.assertEqual(proc.get_status(), 8, "Avocado did not finish with "
                      "1.")
     sleep_dir = astring.string_to_safe_path("1-" + sleep[1:-1])
     debug_log = os.path.join(self.tmpdir, "latest", "test-results",
                              sleep_dir, "debug.log")
     debug_log = open(debug_log).read()
     self.assertIn(
         "Runner error occurred: Timeout reached", debug_log,
         "Runner error occurred: Timeout reached message not "
         "in the test's debug.log:\n%s" % debug_log)
     self.assertNotIn(
         "Traceback (most recent", debug_log, "Traceback "
         "present in the test's debug.log file, but it was "
         "suppose to be stopped and unable to produce it.\n"
         "%s" % debug_log)
예제 #15
0
    def test_well_behaved(self):
        """
        Make sure avocado can cleanly get out of a loop of well behaved tests.
        """
        good_test_basename = ('goodtest-%s.py' %
                              data_factory.generate_random_string(5))
        good_test = script.TemporaryScript(good_test_basename,
                                           GOOD_TEST,
                                           'avocado_interrupt_test',
                                           mode=0755)
        good_test.save()

        os.chdir(basedir)
        cmd_line = (
            './scripts/avocado run --sysinfo=off --job-results-dir %s '
            '%s %s %s' %
            (self.tmpdir, good_test.path, good_test.path, good_test.path))
        proc = aexpect.Expect(command=cmd_line, linesep='')
        proc.read_until_last_line_matches(os.path.basename(good_test.path))
        proc.sendline('\x03')
        proc.read_until_last_line_matches('TIME       : %d s')
        wait.wait_for(lambda: not proc.is_alive(), timeout=1)

        # Make sure the good test will be really gone from the process table
        def wait_until_no_goodtest():
            good_test_processes = []
            for p in psutil.pids():
                p_obj = None
                try:
                    p_obj = psutil.Process(p)
                except psutil.NoSuchProcess:
                    pass
                if p_obj is not None:
                    if good_test.path in " ".join(psutil.Process(p).cmdline()):
                        good_test_processes.append(p_obj)
            return len(good_test_processes) == 0

        wait.wait_for(wait_until_no_goodtest, timeout=2)
        # Make sure the Killing test subprocess message is not there
        self.assertNotIn('Killing test subprocess', proc.get_output())
        # Make sure the Interrupted requested sentence is there
        self.assertIn(
            'Interrupt requested. Waiting 2 seconds for test to '
            'finish (ignoring new Ctrl+C until then)', proc.get_output())
예제 #16
0
def vsock_connect(tool_bin, guest_cid, port):
    """
    Connect to vsock port from host

    :param tool_bin: path of binary vsock test tool
    :param guest_cid: guest cid to connect
    :param port: port to connect
    :return: The vsock session from host side, being waiting for input
    """

    if "ncat" in tool_bin:
        conn_cmd = "%s --vsock %s %s" % (tool_bin, guest_cid, port)
    if "nc-vsock" in tool_bin:
        conn_cmd = "%s %s %s" % (tool_bin, guest_cid, port)
    LOG_JOB.info("Connect to the vsock port on host: %s", conn_cmd)

    return aexpect.Expect(conn_cmd,
                          auto_close=False,
                          output_func=utils_misc.log_line,
                          output_params=("vsock_%s_%s" % (guest_cid, port), ))
예제 #17
0
def run(test, params, env):
    """
    Vsock basic function test

    1. Boot guest with vhost-vsock-pci device
    2. Download and compile nc-vsock on both guest and host
    3. Start listening inside guest, nc-vsock -l $port
    4. Connect guest CID from host, nc-vsock $guest_cid $port
    5. Input character, e.g. 'Hello world'
    6. Check if guest receive the content correctly

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment
    """
    def clean(tmp_file=None):
        """ Clean the environment """
        cmd_rm = "rm -rf %s*" % nc_vsock_bin
        if tmp_file:
            cmd_rm += "; rm -rf %s" % tmp_file
        session.cmd_output_safe(cmd_rm)
        process.system(cmd_rm, ignore_status=True)
        if host_vsock_session.is_alive():
            host_vsock_session.close()
        session.close()

    vm = env.get_vm(params["main_vm"])
    tmp_file = "/tmp/vsock_file_%s" % utils_misc.generate_random_string(6)
    session = vm.wait_for_login()
    # TODO: Close selinux as temporary workaround for qemu bug 1656738
    # should be removed when fixed
    session.cmd_output("setenforce 0")
    nc_vsock_bin = compile_nc_vsock(test, vm, session)
    vsock_dev = params["vsocks"].split()[0]
    guest_cid = vm.devices.get(vsock_dev).get_param("guest-cid")
    port = random.randrange(1, 6000)
    nc_vsock_listen(nc_vsock_bin, port, session)
    host_vsock_session = nc_vsock_connect(nc_vsock_bin, guest_cid, port)
    connected_str = r"Connection from cid*"
    send_data = "Hello world"
    check_received_data(test, session, connected_str)
    error_context.context('Input "Hello world" to vsock.', logging.info)
    host_vsock_session.sendline(send_data)
    check_received_data(test, session, send_data)
    host_vsock_session.close()
    try:
        session.read_up_to_prompt(timeout=10)
    except aexpect.ExpectTimeoutError:
        test.fail("nc-vsock listening prcoess inside guest"
                  " does not exit after close host nc-vsock connection.")
    finally:
        session.close()

    # Transfer data from guest to host
    session = vm.wait_for_login()
    cmd_generate = 'dd if=/dev/urandom of=%s count=1000 bs=1M' % tmp_file
    session.cmd_status(cmd_generate)
    cmd_transfer = '%s -l %s < %s &' % (nc_vsock_bin, port, tmp_file)
    error_context.context(
        'Transfer file from guest via command: %s' % cmd_transfer,
        logging.info)
    session.cmd_status(cmd_transfer)
    time.sleep(1)  # wait nc-vsock start listening
    cmd_receive = '%s %s %s > %s' % (nc_vsock_bin, guest_cid, port, tmp_file)
    rec_session = aexpect.Expect(cmd_receive,
                                 auto_close=True,
                                 output_func=utils_misc.log_line,
                                 output_params=('%s.log' % tmp_file, ))
    utils_misc.wait_for(lambda: not rec_session.is_alive(), timeout=20)
    cmd_chksum = 'md5sum %s' % tmp_file
    md5_origin = session.cmd_output(cmd_chksum).split()[0]
    md5_received = process.system_output(cmd_chksum).split()[0].decode()
    if md5_received != md5_origin:
        clean(tmp_file)
        test.fail('Data transfer not integrated, the original md5 value'
                  ' is %s, while the md5 value received on host is %s' %
                  (md5_origin, md5_received))
    clean(tmp_file)