Example #1
0
def postprocess_vm(test, params, env, name):
    """
    Postprocess a single VM object according to the instructions in params.
    Kill the VM if requested and get a screendump.

    :param test: An Autotest test object.
    :param params: A dict containing VM postprocessing parameters.
    :param env: The environment (a dict-like object).
    :param name: The name of the VM object.
    """
    vm = env.get_vm(name)
    if not vm:
        return

    # Close all SSH sessions that might be active to this VM
    for s in vm.remote_sessions[:]:
        try:
            s.close()
            vm.remote_sessions.remove(s)
        except Exception:
            pass

    if params.get("kill_vm") == "yes":
        kill_vm_timeout = float(params.get("kill_vm_timeout", 0))
        if kill_vm_timeout:
            utils_misc.wait_for(vm.is_dead, kill_vm_timeout, 0, 1)
        vm.destroy(gracefully=params.get("kill_vm_gracefully") == "yes")
Example #2
0
    def reboot(self, session=None, method="shell", nic_index=0, timeout=240):
        """
        Reboot the VM and wait for it to come back up by trying to log in until
        timeout expires.

        @param session: A shell session object or None.
        @param method: Reboot method.  Can be "shell" (send a shell reboot
                command).
        @param nic_index: Index of NIC to access in the VM, when logging in
                after rebooting.
        @param timeout: Time to wait for login to succeed (after rebooting).
        @return: A new shell session object.
        """
        error.base_context("rebooting '%s'" % self.name, logging.info)
        error.context("before reboot")
        session = session or self.login()
        error.context()

        if method == "shell":
            session.sendline(self.params.get("reboot_command"))
        else:
            raise virt_vm.VMRebootError("Unknown reboot method: %s" % method)

        error.context("waiting for guest to go down", logging.info)
        if not utils_misc.wait_for(lambda: not session.is_responsive(timeout=30), 120, 0, 1):
            raise virt_vm.VMRebootError("Guest refuses to go down")
        session.close()

        error.context("logging in after reboot", logging.info)
        return self.wait_for_login(nic_index, timeout=timeout)
Example #3
0
    def destroy(self, gracefully=True, free_mac_addresses=True):
        """
        Destroy the VM.

        If gracefully is True, first attempt to shutdown the VM with a shell
        command. If that fails, send SIGKILL to the qemu process.

        @param gracefully: If True, an attempt will be made to end the VM
                using a shell command before trying to end the qemu process
                with a 'quit' or a kill signal.
        @param free_mac_addresses: If vm is undefined with libvirt, also
                                   release/reset associated mac address
        """
        try:
            # Is it already dead?
            if self.is_alive():
                logging.debug("Destroying VM")
                if gracefully and self.params.get("shutdown_command"):
                    # Try to destroy with shell command
                    logging.debug("Trying to shutdown VM with shell command")
                    try:
                        session = self.login()
                    except (remote.LoginError, virt_vm.VMError), e:
                        logging.debug(e)
                    else:
                        try:
                            # Send the shutdown command
                            session.sendline(self.params.get("shutdown_command"))
                            logging.debug("Shutdown command sent; waiting for VM "
                                          "to go down...")
                            if utils_misc.wait_for(self.is_dead, 60, 1, 1):
                                logging.debug("VM is down")
                                return
                        finally:
                            session.close()
                virsh.destroy(self.name, uri=self.connect_uri)

        finally:
            if self.serial_console:
                self.serial_console.close()
            for f in ([self.get_testlog_filename(),
                       self.get_serial_console_filename()]):
                try:
                    os.unlink(f)
                except OSError:
                    pass
            if hasattr(self, "migration_file"):
                try:
                    os.unlink(self.migration_file)
                except OSError:
                    pass

        if free_mac_addresses:
            if self.is_persistent():
                logging.warning("Requested MAC address release from "
                                "persistent vm %s. Ignoring." % self.name)
            else:
                logging.debug("Releasing MAC addresses for vm %s." % self.name)
                for nic_name in self.virtnet.nic_name_list():
                    self.virtnet.free_mac_address(nic_name)
Example #4
0
 def start(self):
     """
     Starts this VM.
     """
     self.uuid = virsh.domuuid(self.name, uri=self.connect_uri)
     # Pull in mac addresses from libvirt guest definition
     for index, nic in enumerate(self.virtnet):
         try:
             mac = self.get_virsh_mac_address(index)
             if not nic.has_key("mac"):
                 logging.debug("Updating nic %d with mac %s on vm %s" % (index, mac, self.name))
                 nic.mac = mac
             elif nic.mac != mac:
                 logging.warning(
                     "Requested mac %s doesn't match mac %s " "as defined for vm %s" % (nic.mac, mac, self.name)
                 )
             # TODO: Checkout/Set nic_model, nettype, netdst also
         except virt_vm.VMMACAddressMissingError:
             logging.warning("Nic %d requested by test but not defined for" " vm %s" % (index, self.name))
     if virsh.start(self.name, uri=self.connect_uri):
         # Wait for the domain to be created
         has_started = utils_misc.wait_for(
             func=self.is_alive, timeout=60, text=("waiting for domain %s " "to start" % self.name)
         )
         if has_started is None:
             raise virt_vm.VMStartError(self.name, "libvirt domain not " "active after start")
         self.uuid = virsh.domuuid(self.name, uri=self.connect_uri)
     else:
         raise virt_vm.VMStartError(self.name, "libvirt domain failed " "to start")
Example #5
0
    def _start_tcpdump(self):
        port = self._params.get('shell_port')
        prompt = self._params.get('shell_prompt')
        address = self._params.get('ovirt_node_address')
        username = self._params.get('ovirt_node_user')
        password = self._params.get('ovirt_node_password')

        cmd = "%s -npvi any 'port 68'" % utils_misc.find_command("tcpdump")
        if self._params.get("remote_preprocess") == "yes":
            login_cmd = ("ssh -o UserKnownHostsFile=/dev/null -o "
                         "PreferredAuthentications=password -p %s %s@%s" %
                         (port, username, address))

            self._tcpdump = aexpect.ShellSession(
                login_cmd,
                output_func=_update_address_cache,
                output_params=(self,))

            remote.handle_prompts(self._tcpdump, username, password, prompt)
            self._tcpdump.sendline(cmd)

        else:
            self._tcpdump = aexpect.Tail(command=cmd,
                                         output_func=_tcpdump_handler,
                                         output_params=(self, "tcpdump.log"))

        if utils_misc.wait_for(lambda: not self._tcpdump.is_alive(),
                               0.1, 0.1, 1.0):
            logging.warn("Could not start tcpdump")
            logging.warn("Status: %s", self._tcpdump.get_status())
            msg = utils_misc.format_str_for_message(self._tcpdump.get_output())
            logging.warn("Output: %s", msg)
Example #6
0
    def read_until_output_matches(
        self, patterns, filter=lambda x: x, timeout=60, internal_timeout=None, print_func=None
    ):
        """
        Read using read_nonblocking until a match is found using match_patterns,
        or until timeout expires. Before attempting to search for a match, the
        data is filtered using the filter function provided.

        @brief: Read from child using read_nonblocking until a pattern
                matches.
        @param patterns: List of strings (regular expression patterns)
        @param filter: Function to apply to the data read from the child before
                attempting to match it against the patterns (should take and
                return a string)
        @param timeout: The duration (in seconds) to wait until a match is
                found
        @param internal_timeout: The timeout to pass to read_nonblocking
        @param print_func: A function to be used to print the data being read
                (should take a string parameter)
        @return: Tuple containing the match index and the data read so far
        @raise ExpectTimeoutError: Raised if timeout expires
        @raise ExpectProcessTerminatedError: Raised if the child process
                terminates while waiting for output
        @raise ExpectError: Raised if an unknown error occurs
        """
        fd = self._get_fd("expect")
        o = ""
        end_time = time.time() + timeout
        while True:
            try:
                r, w, x = select.select([fd], [], [], max(0, end_time - time.time()))
            except (select.error, TypeError):
                break
            if not r:
                raise ExpectTimeoutError(patterns, o)
            # Read data from child
            data = self.read_nonblocking(internal_timeout, end_time - time.time())
            if not data:
                break
            # Print it if necessary
            if print_func:
                for line in data.splitlines():
                    print_func(line)
            # Look for patterns
            o += data
            match = self.match_patterns(filter(o), patterns)
            if match is not None:
                return match, o

        # Check if the child has terminated
        if utils_misc.wait_for(lambda: not self.is_alive(), 5, 0, 0.1):
            raise ExpectProcessTerminatedError(patterns, self.get_status(), o)
        else:
            # This shouldn't happen
            raise ExpectError(patterns, o)
Example #7
0
 def wait_for_get_address(self, nic_index_or_name, timeout=30, internal_timeout=1):
     """
     Wait for a nic to acquire an IP address, then return it.
     """
     # Don't let VMIPAddressMissingError/VMAddressVerificationError through
     def _get_address():
         try:
             return self.get_address(nic_index_or_name)
         except (VMIPAddressMissingError, VMAddressVerificationError):
             return False
     if not utils_misc.wait_for(_get_address, timeout, internal_timeout):
         raise VMIPAddressMissingError(self.virtnet[nic_index_or_name].mac)
     return self.get_address(nic_index_or_name)
Example #8
0
    def _start_tcpdump(self):

        cmd_template = "%s -npvvvi any 'port 68 or port 546'"
        if self._params.get("remote_preprocess") == "yes":
            client = self._params.get('remote_shell_client', 'ssh')
            port = self._params.get('remote_shell_port', '22')
            prompt = self._params.get('remote_shell_prompt', '#')
            address = self._params.get('remote_node_address')
            username = self._params.get('remote_node_user')
            password = self._params.get('remote_node_password')
            rsession = None
            try:
                rsession = remote.remote_login(client, address,
                                               port, username,
                                               password, prompt)
                tcpdump_bin = rsession.cmd_output("which tcpdump")
                rsession.close()
            except process.CmdError:
                rsession.close()
                raise exceptions.TestError("Can't find tcpdump binary!")

            cmd = cmd_template % tcpdump_bin.strip()
            logging.debug("Run '%s' on host '%s'", cmd, address)
            login_cmd = ("ssh -o UserKnownHostsFile=/dev/null "
                         "-o StrictHostKeyChecking=no "
                         "-o PreferredAuthentications=password -p %s %s@%s" %
                         (port, username, address))

            self._tcpdump = aexpect.ShellSession(
                login_cmd,
                output_func=_update_address_cache,
                output_params=(self,))

            remote.handle_prompts(self._tcpdump, username, password, prompt)
            self._tcpdump.sendline(cmd)

        else:
            cmd = cmd_template % utils_path.find_command("tcpdump")
            self._tcpdump = aexpect.Tail(command=cmd,
                                         output_func=_tcpdump_handler,
                                         output_params=(self, "tcpdump.log"))

        if utils_misc.wait_for(lambda: not self._tcpdump.is_alive(),
                               0.1, 0.1, 1.0):
            logging.warn("Could not start tcpdump")
            logging.warn("Status: %s", self._tcpdump.get_status())
            msg = utils_misc.format_str_for_message(self._tcpdump.get_output())
            logging.warn("Output: %s", msg)
Example #9
0
    def wait_for_get_address(self, nic_index_or_name, timeout=30, internal_timeout=1, ip_version="ipv4"):
        """
        Wait for a nic to acquire an IP address, then return it.
        For ipv6 linklocal address, we can generate it by nic mac,
        so we can ignore this case
        """
        # Don't let VMIPAddressMissingError/VMAddressVerificationError through
        def _get_address():
            try:
                return self.get_address(nic_index_or_name)
            except (VMIPAddressMissingError, VMAddressVerificationError):
                return False

        if not utils_misc.wait_for(_get_address, timeout, internal_timeout):
            raise VMIPAddressMissingError(self.virtnet[nic_index_or_name].mac)
        return self.get_address(nic_index_or_name)
Example #10
0
    def wait_for_get_address(self, nic_index_or_name, timeout=30,
                             internal_timeout=1, ip_version='ipv4'):
        """
        Wait for a nic to acquire an IP address, then return it.
        For ipv6 linklocal address, we can generate it by nic mac,
        so we can ignore this case
        """
        # Don't let VMIPAddressMissingError/VMAddressVerificationError through
        def _get_address():
            try:
                return self.get_address(nic_index_or_name)
            except (VMIPAddressMissingError, VMAddressVerificationError):
                return False

        if not utils_misc.wait_for(_get_address, timeout, internal_timeout):
            if self.is_dead():
                raise VMIPAddressMissingError(self.virtnet[nic_index_or_name].mac)
            try:
                s_session = None
                # for windows guest make sure your guest supports
                # login by serial_console
                s_session = self.wait_for_serial_login()
                nic_mac = self.get_mac_address(nic_index_or_name)
                os_type = self.params.get("os_type")
                try:
                    utils_net.renew_guest_ip(s_session, nic_mac,
                                             os_type, ip_version)
                    return self.get_address(nic_index_or_name)
                except (VMIPAddressMissingError, VMAddressVerificationError):
                    try:
                        nic_address = utils_net.get_guest_ip_addr(s_session,
                                                                  nic_mac,
                                                                  os_type,
                                                                  ip_version)
                        if nic_address:
                            mac_key = nic_mac
                            if ip_version == "ipv6":
                                mac_key = "%s_6" % nic_mac
                            self.address_cache[mac_key.lower()] = nic_address
                            return nic_address
                    except Exception, err:
                        logging.debug("Can not get guest address, '%s'" % err)
                        raise VMIPAddressMissingError(nic_mac)
            finally:
                if s_session:
                    s_session.close()
        return self.get_address(nic_index_or_name)
Example #11
0
    def setup(self):
        """
        Access the iscsi target. And return the local raw device name.
        """
        if self.iscsidevice.logged_in():
            logging.warn("Session already present. Don't need to" " login again")
        else:
            self.iscsidevice.login()

        if utils_misc.wait_for(self.iscsidevice.get_device_name, self.iscsi_init_timeout):
            device_name = self.iscsidevice.get_device_name()
        else:
            raise error.TestError("Can not get iscsi device name in host" " in %ss" % self.iscsi_init_timeout)

        if self.device_id:
            device_name += self.device_id
        return device_name
Example #12
0
 def wait_for_get_address(self, nic_index_or_name, timeout=30,
                          internal_timeout=1, ip_version='ipv4'):
     """
     Wait for a nic to acquire an IP address, then return it.
     """
     # Don't let VMIPAddressMissingError/VMAddressVerificationError through
     def _get_address():
         try:
             return self.get_address(nic_index_or_name)
         except (VMIPAddressMissingError, VMAddressVerificationError):
             return False
     if not utils_misc.wait_for(_get_address, timeout, internal_timeout):
         try:
             s_session = None
             s_session = self.wait_for_serial_login()
             nic_mac = self.get_mac_address(nic_index_or_name)
             os_type = self.params.get("os_type")
             try:
                 utils_net.renew_guest_ip(s_session, nic_mac, os_type)
                 return self.get_address(nic_index_or_name)
             except (VMIPAddressMissingError, VMAddressVerificationError):
                 try:
                     nic_address = utils_net.get_guest_ip_addr(s_session,
                                                               nic_mac,
                                                               os_type,
                                                               ip_version)
                     if nic_address:
                         self.address_cache[nic_mac.lower()] = nic_address
                         return nic_address
                 except Exception, err:
                     logging.debug("Can not get guest address, '%s'" % err)
                     raise VMIPAddressMissingError(nic_mac)
         finally:
             if s_session:
                 s_session.close()
     return self.get_address(nic_index_or_name)
Example #13
0
def preprocess(test, params, env):
    """
    Preprocess all VMs and images according to the instructions in params.
    Also, collect some host information, such as the KVM version.

    :param test: An Autotest test object.
    :param params: A dict containing all VM and image parameters.
    :param env: The environment (a dict-like object).
    """
    error.context("preprocessing")
    # First, let's verify if this test does require root or not. If it
    # does and the test suite is running as a regular user, we shall just
    # throw a TestNAError exception, which will skip the test.
    if params.get('requires_root', 'no') == 'yes':
        utils_misc.verify_running_as_root()

    port = params.get('shell_port')
    prompt = params.get('shell_prompt')
    address = params.get('ovirt_node_address')
    username = params.get('ovirt_node_user')
    password = params.get('ovirt_node_password')

    setup_pb = False
    for nic in params.get('nics', "").split():
        nic_params = params.object_params(nic)
        if nic_params.get('netdst') == 'private':
            setup_pb = True
            params_pb = nic_params
            params['netdst_%s' % nic] = nic_params.get("priv_brname", 'atbr0')

    if setup_pb:
        brcfg = test_setup.PrivateBridgeConfig(params_pb)
        brcfg.setup()

    base_dir = data_dir.get_data_dir()
    if params.get("storage_type") == "iscsi":
        iscsidev = qemu_storage.Iscsidev(params, base_dir, "iscsi")
        params["image_name"] = iscsidev.setup()
        params["image_raw_device"] = "yes"

    # Start tcpdump if it isn't already running
    if "address_cache" not in env:
        env["address_cache"] = {}
    if "tcpdump" in env and not env["tcpdump"].is_alive():
        env["tcpdump"].close()
        del env["tcpdump"]
    if "tcpdump" not in env and params.get("run_tcpdump", "yes") == "yes":
        cmd = "%s -npvi any 'port 68'" % utils_misc.find_command("tcpdump")
        if params.get("remote_preprocess") == "yes":
            login_cmd = ("ssh -o UserKnownHostsFile=/dev/null -o \
                         PreferredAuthentications=password -p %s %s@%s" %
                         (port, username, address))
            env["tcpdump"] = aexpect.ShellSession(
                login_cmd,
                output_func=_update_address_cache,
                output_params=(env["address_cache"],))
            remote.handle_prompts(env["tcpdump"], username, password, prompt)
            env["tcpdump"].sendline(cmd)
        else:
            env["tcpdump"] = aexpect.Tail(
                command=cmd,
                output_func=_tcpdump_handler,
                output_params=(env["address_cache"], "tcpdump.log",))

        if utils_misc.wait_for(lambda: not env["tcpdump"].is_alive(),
                               0.1, 0.1, 1.0):
            logging.warn("Could not start tcpdump")
            logging.warn("Status: %s" % env["tcpdump"].get_status())
            logging.warn("Output:" + utils_misc.format_str_for_message(
                env["tcpdump"].get_output()))

    # Destroy and remove VMs that are no longer needed in the environment
    requested_vms = params.objects("vms")
    for key in env.keys():
        vm = env[key]
        if not isinstance(vm, virt_vm.BaseVM):
            continue
        if not vm.name in requested_vms:
            vm.destroy()
            del env[key]

    if (params.get("auto_cpu_model") == "yes" and
            params.get("vm_type") == "qemu"):
        if not env.get("cpu_model"):
            env["cpu_model"] = utils_misc.get_qemu_best_cpu_model(params)
        params["cpu_model"] = env.get("cpu_model")

    kvm_ver_cmd = params.get("kvm_ver_cmd", "")

    if kvm_ver_cmd:
        try:
            cmd_result = utils.run(kvm_ver_cmd)
            kvm_version = cmd_result.stdout.strip()
        except error.CmdError:
            kvm_version = "Unknown"
    else:
        # Get the KVM kernel module version and write it as a keyval
        if os.path.exists("/dev/kvm"):
            try:
                kvm_version = open("/sys/module/kvm/version").read().strip()
            except Exception:
                kvm_version = os.uname()[2]
        else:
            logging.warning("KVM module not loaded")
            kvm_version = "Unknown"

    logging.debug("KVM version: %s" % kvm_version)
    test.write_test_keyval({"kvm_version": kvm_version})

    # Get the KVM userspace version and write it as a keyval
    kvm_userspace_ver_cmd = params.get("kvm_userspace_ver_cmd", "")

    if kvm_userspace_ver_cmd:
        try:
            cmd_result = utils.run(kvm_userspace_ver_cmd)
            kvm_userspace_version = cmd_result.stdout.strip()
        except error.CmdError:
            kvm_userspace_version = "Unknown"
    else:
        qemu_path = utils_misc.get_qemu_binary(params)
        version_line = commands.getoutput("%s -help | head -n 1" % qemu_path)
        matches = re.findall("[Vv]ersion .*?,", version_line)
        if matches:
            kvm_userspace_version = " ".join(matches[0].split()[1:]).strip(",")
        else:
            kvm_userspace_version = "Unknown"

    logging.debug("KVM userspace version: %s" % kvm_userspace_version)
    test.write_test_keyval({"kvm_userspace_version": kvm_userspace_version})

    if params.get("setup_hugepages") == "yes":
        h = test_setup.HugePageConfig(params)
        suggest_mem = h.setup()
        if suggest_mem is not None:
            params['mem'] = suggest_mem
        if params.get("vm_type") == "libvirt":
            utils_libvirtd.libvirtd_restart()

    if params.get("setup_thp") == "yes":
        thp = test_setup.TransparentHugePageConfig(test, params)
        thp.setup()

    if params.get("setup_ksm") == "yes":
        ksm = test_setup.KSMConfig(params, env)
        ksm.setup(env)

    # Execute any pre_commands
    if params.get("pre_command"):
        process_command(test, params, env, params.get("pre_command"),
                        int(params.get("pre_command_timeout", "600")),
                        params.get("pre_command_noncritical") == "yes")

    # if you want set "pci=nomsi" before test, set "disable_pci_msi = yes"
    # and pci_msi_sensitive = "yes"
    if params.get("pci_msi_sensitive", "no") == "yes":
        disable_pci_msi = params.get("disable_pci_msi", "no")
        image_filename = storage.get_image_filename(params,
                                                    data_dir.get_data_dir())
        grub_file = params.get("grub_file", "/boot/grub2/grub.cfg")
        kernel_cfg_pos_reg = params.get("kernel_cfg_pos_reg",
                                        r".*vmlinuz-\d+.*")
        msi_keyword = params.get("msi_keyword", " pci=nomsi")

        disk_obj = utils_disk.GuestFSModiDisk(image_filename)
        kernel_config_ori = disk_obj.read_file(grub_file)
        kernel_config = re.findall(kernel_cfg_pos_reg, kernel_config_ori)
        if not kernel_config:
            raise error.TestError("Cannot find the kernel config, reg is %s" %
                                  kernel_cfg_pos_reg)
        kernel_config_line = kernel_config[0]

        kernel_need_modify = False
        if disable_pci_msi == "yes":
            if not re.findall(msi_keyword, kernel_config_line):
                kernel_config_set = kernel_config_line + msi_keyword
                kernel_need_modify = True
        else:
            if re.findall(msi_keyword, kernel_config_line):
                kernel_config_set = re.sub(msi_keyword, "", kernel_config_line)
                kernel_need_modify = True

        if kernel_need_modify:
            for vm in env.get_all_vms():
                if vm:
                    vm.destroy()
                    env.unregister_vm(vm.name)
            disk_obj.replace_image_file_content(grub_file, kernel_config_line,
                                                kernel_config_set)
        logging.debug("Guest cmdline 'pci=nomsi' setting is: [ %s ]" %
                      disable_pci_msi)

    kernel_extra_params = params.get("kernel_extra_params")
    if kernel_extra_params:
        image_filename = storage.get_image_filename(params,
                                                    data_dir.get_data_dir())
        grub_file = params.get("grub_file", "/boot/grub2/grub.cfg")
        kernel_cfg_pos_reg = params.get("kernel_cfg_pos_reg",
                                        r".*vmlinuz-\d+.*")

        disk_obj = utils_disk.GuestFSModiDisk(image_filename)
        kernel_config_ori = disk_obj.read_file(grub_file)
        kernel_config = re.findall(kernel_cfg_pos_reg, kernel_config_ori)
        if not kernel_config:
            raise error.TestError("Cannot find the kernel config, reg is %s" %
                                  kernel_cfg_pos_reg)
        kernel_config_line = kernel_config[0]

        kernel_need_modify = False
        if not re.findall(kernel_extra_params, kernel_config_line):
            kernel_config_set = kernel_config_line + kernel_extra_params
            kernel_need_modify = True

        if kernel_need_modify:
            for vm in env.get_all_vms():
                if vm:
                    vm.destroy()
                    env.unregister_vm(vm.name)
            disk_obj.replace_image_file_content(grub_file, kernel_config_line,
                                                kernel_config_set)
        logging.debug("Guest cmdline extra_params setting is: [ %s ]" %
                      kernel_extra_params)

    # Clone master image from vms.
    base_dir = data_dir.get_data_dir()
    if params.get("master_images_clone"):
        for vm_name in params.get("vms").split():
            vm = env.get_vm(vm_name)
            if vm:
                vm.destroy(free_mac_addresses=False)
                env.unregister_vm(vm_name)

            vm_params = params.object_params(vm_name)
            for image in vm_params.get("master_images_clone").split():
                image_obj = qemu_storage.QemuImg(params, base_dir, image)
                image_obj.clone_image(params, vm_name, image, base_dir)

    # Preprocess all VMs and images
    if params.get("not_preprocess", "no") == "no":
        process(test, params, env, preprocess_image, preprocess_vm)

    # Start the screendump thread
    if params.get("take_regular_screendumps") == "yes":
        global _screendump_thread, _screendump_thread_termination_event
        _screendump_thread_termination_event = threading.Event()
        _screendump_thread = threading.Thread(target=_take_screendumps,
                                              name='ScreenDump',
                                              args=(test, params, env))
        _screendump_thread.start()

    return params
Example #14
0
def preprocess(test, params, env):
    """
    Preprocess all VMs and images according to the instructions in params.
    Also, collect some host information, such as the KVM version.

    @param test: An Autotest test object.
    @param params: A dict containing all VM and image parameters.
    @param env: The environment (a dict-like object).
    """
    error.context("preprocessing")
    # First, let's verify if this test does require root or not. If it
    # does and the test suite is running as a regular user, we shall just
    # throw a TestNAError exception, which will skip the test.
    if params.get('requires_root', 'no') == 'yes':
        utils_test.verify_running_as_root()

    port = params.get('shell_port')
    prompt = params.get('shell_prompt')
    address = params.get('ovirt_node_address')
    username = params.get('ovirt_node_user')
    password = params.get('ovirt_node_password')

    # Start tcpdump if it isn't already running
    if "address_cache" not in env:
        env["address_cache"] = {}
    if "tcpdump" in env and not env["tcpdump"].is_alive():
        env["tcpdump"].close()
        del env["tcpdump"]
    if "tcpdump" not in env and params.get("run_tcpdump", "yes") == "yes":
        cmd = "%s -npvi any 'dst port 68'" % utils_misc.find_command("tcpdump")
        if params.get("remote_preprocess") == "yes":
            login_cmd = ("ssh -o UserKnownHostsFile=/dev/null -o \
                         PreferredAuthentications=password -p %s %s@%s" %
                         (port, username, address))
            env["tcpdump"] = aexpect.ShellSession(
                login_cmd,
                output_func=_update_address_cache,
                output_params=(env["address_cache"],))
            remote._remote_login(env["tcpdump"], username, password, prompt)
            env["tcpdump"].sendline(cmd)
        else:
            env["tcpdump"] = aexpect.Tail(
                command=cmd,
                output_func=_update_address_cache,
                output_params=(env["address_cache"],))

        if utils_misc.wait_for(lambda: not env["tcpdump"].is_alive(),
                              0.1, 0.1, 1.0):
            logging.warn("Could not start tcpdump")
            logging.warn("Status: %s" % env["tcpdump"].get_status())
            logging.warn("Output:" + utils_misc.format_str_for_message(
                env["tcpdump"].get_output()))

    # Destroy and remove VMs that are no longer needed in the environment
    requested_vms = params.objects("vms")
    for key in env.keys():
        vm = env[key]
        if not isinstance(vm, virt_vm.BaseVM):
            continue
        if not vm.name in requested_vms:
            vm.destroy()
            del env[key]

    # Get Host cpu type
    if params.get("auto_cpu_model") == "yes":
        if not env.get("cpu_model"):
            env["cpu_model"] = utils_misc.get_cpu_model()
        params["cpu_model"] = env.get("cpu_model")

    kvm_ver_cmd = params.get("kvm_ver_cmd", "")

    if kvm_ver_cmd:
        try:
            cmd_result = utils.run(kvm_ver_cmd)
            kvm_version = cmd_result.stdout.strip()
        except error.CmdError:
            kvm_version = "Unknown"
    else:
        # Get the KVM kernel module version and write it as a keyval
        if os.path.exists("/dev/kvm"):
            try:
                kvm_version = open("/sys/module/kvm/version").read().strip()
            except Exception:
                kvm_version = os.uname()[2]
        else:
            logging.warning("KVM module not loaded")
            kvm_version = "Unknown"

    logging.debug("KVM version: %s" % kvm_version)
    test.write_test_keyval({"kvm_version": kvm_version})

    # Get the KVM userspace version and write it as a keyval
    kvm_userspace_ver_cmd = params.get("kvm_userspace_ver_cmd", "")

    if kvm_userspace_ver_cmd:
        try:
            cmd_result = utils.run(kvm_userspace_ver_cmd)
            kvm_userspace_version = cmd_result.stdout.strip()
        except error.CmdError:
            kvm_userspace_version = "Unknown"
    else:
        qemu_path = utils_misc.get_path(test.bindir,
                                        params.get("qemu_binary", "qemu"))
        version_line = commands.getoutput("%s -help | head -n 1" % qemu_path)
        matches = re.findall("[Vv]ersion .*?,", version_line)
        if matches:
            kvm_userspace_version = " ".join(matches[0].split()[1:]).strip(",")
        else:
            kvm_userspace_version = "Unknown"

    logging.debug("KVM userspace version: %s" % kvm_userspace_version)
    test.write_test_keyval({"kvm_userspace_version": kvm_userspace_version})

    if params.get("setup_hugepages") == "yes":
        h = test_setup.HugePageConfig(params)
        h.setup()
        if params.get("vm_type") == "libvirt":
            libvirt_vm.libvirtd_restart()

    if params.get("setup_thp") == "yes":
        thp = test_setup.TransparentHugePageConfig(test, params)
        thp.setup()

    # Execute any pre_commands
    if params.get("pre_command"):
        process_command(test, params, env, params.get("pre_command"),
                        int(params.get("pre_command_timeout", "600")),
                        params.get("pre_command_noncritical") == "yes")

    #Clone master image from vms.
    base_dir = data_dir.get_data_dir()
    if params.get("master_images_clone"):
        for vm_name in params.get("vms").split():
            vm = env.get_vm(vm_name)
            if vm:
                vm.destroy(free_mac_addresses=False)
                env.unregister_vm(vm_name)

            vm_params = params.object_params(vm_name)
            for image in vm_params.get("master_images_clone").split():
                image_obj = qemu_storage.QemuImg(params, base_dir, image)
                image_obj.clone_image(params, vm_name, image, base_dir)

    # Preprocess all VMs and images
    if params.get("not_preprocess","no") == "no":
        process(test, params, env, preprocess_image, preprocess_vm)

    # Start the screendump thread
    if params.get("take_regular_screendumps") == "yes":
        global _screendump_thread, _screendump_thread_termination_event
        _screendump_thread_termination_event = threading.Event()
        _screendump_thread = threading.Thread(target=_take_screendumps,
                                              args=(test, params, env))
        _screendump_thread.start()
Example #15
0
            video = video_maker.GstPythonVideoMaker()
            if (video.has_element('vp8enc') and video.has_element('webmmux')):
                video_file = os.path.join(test.debugdir, "%s-%s.webm" %
                                          (vm.name, test.iteration))
            else:
                video_file = os.path.join(test.debugdir, "%s-%s.ogg" %
                                          (vm.name, test.iteration))
            video.start(screendump_dir, video_file)

        except Exception, detail:
            logging.info("Video creation failed for vm %s: %s", vm.name, detail)

    if params.get("kill_vm") == "yes":
        kill_vm_timeout = float(params.get("kill_vm_timeout", 0))
        if kill_vm_timeout:
            utils_misc.wait_for(vm.is_dead, kill_vm_timeout, 0, 1)
        vm.destroy(gracefully = params.get("kill_vm_gracefully") == "yes")


def process_command(test, params, env, command, command_timeout,
                    command_noncritical):
    """
    Pre- or post- custom commands to be executed before/after a test is run

    @param test: An Autotest test object.
    @param params: A dict containing all VM and image parameters.
    @param env: The environment (a dict-like object).
    @param command: Command to be run.
    @param command_timeout: Timeout for command execution.
    @param command_noncritical: If True test will not fail if command fails.
    """
Example #16
0
    def get_address(self, index=0):
        """
        Return the IP address of a NIC or guest (in host space).

        :param index: Name or index of the NIC whose address is requested.
        :return: 'localhost': Port redirection is in use
        :return: IP address of NIC if valid in arp cache.
        :raise VMMACAddressMissingError: If no MAC address is defined for the
                requested NIC
        :raise VMIPAddressMissingError: If no IP address is found for the the
                NIC's MAC address
        :raise VMAddressVerificationError: If the MAC-IP address mapping cannot
                be verified (using arping)
        """
        nic = self.virtnet[index]
        self.ip_version = self.params.get("ip_version", "ipv4").lower()
        # TODO: Determine port redirection in use w/o checking nettype
        if nic.nettype not in ['bridge', 'macvtap']:
            hostname = socket.gethostname()
            return socket.gethostbyname(hostname)
        if not nic.has_key('mac') and self.params.get('vm_type') == 'libvirt':
            # Look it up from xml
            nic.mac = self.get_virsh_mac_address(index)
        # else TODO: Look up mac from existing qemu-kvm process
        if not nic.has_key('mac'):
            raise VMMACAddressMissingError(index)
        if self.ip_version == "ipv4":
            # Get the IP address from arp cache, try upper and lower case
            arp_ip = self.address_cache.get(nic.mac.upper())
            if not arp_ip:
                arp_ip = self.address_cache.get(nic.mac.lower())

            if not arp_ip and os.geteuid() != 0:
                # For non-root, tcpdump won't work for finding IP address,
                # try arp
                ip_map = utils_net.parse_arp()
                arp_ip = ip_map.get(nic.mac.lower())
                if arp_ip:
                    self.address_cache[nic.mac.lower()] = arp_ip

            if not arp_ip:
                raise VMIPAddressMissingError(nic.mac)

            # Make sure the IP address is assigned to one or more macs
            # for this guest
            macs = self.virtnet.mac_list()

            # SR-IOV cards may not be in same subnet with the card used by
            # host by default, so arp checks won't work. Therefore, do not
            # raise VMAddressVerificationError when SR-IOV is used.
            nic_params = self.params.object_params(nic.nic_name)
            pci_assignable = nic_params.get("pci_assignable") != "no"

            if not utils_net.verify_ip_address_ownership(arp_ip, macs):
                if pci_assignable:
                    msg = "Could not verify DHCP lease: %s-> %s." % (nic.mac,
                                                                     arp_ip)
                    msg += (" Maybe %s is not in the same subnet "
                            "as the host (SR-IOV in use)" % arp_ip)
                    logging.error(msg)
                else:
                    raise VMAddressVerificationError(nic.mac, arp_ip)

            logging.debug('Found/Verified IP %s for VM %s NIC %s',
                          arp_ip, self.name, str(index))
            return arp_ip

        elif self.ip_version == "ipv6":
            # Try to get and return IPV6 address
            if self.params.get('using_linklocal') == "yes":
                ipv6_addr = utils_net.ipv6_from_mac_addr(nic.mac)
            # Using global address
            else:
                mac_key = "%s_6" % nic.mac
                ipv6_addr = self.address_cache.get(mac_key.lower())
            if not ipv6_addr:
                raise VMIPAddressMissingError(nic.mac)
            # Check whether the ipv6 address is reachable
            utils_net.refresh_neigh_table(nic.netdst, ipv6_addr)
            if not utils_misc.wait_for(lambda: utils_net.neigh_reachable(
                                       ipv6_addr, nic.netdst),
                                       30, 0, 1, "Wait neighbour reachable"):
                raise VMAddressVerificationError(nic.mac, ipv6_addr)
            return ipv6_addr
Example #17
0
    def create(self,
               name=None,
               params=None,
               root_dir=None,
               timeout=5.0,
               migration_mode=None,
               mac_source=None):
        """
        Start the VM by running a qemu command.
        All parameters are optional. If name, params or root_dir are not
        supplied, the respective values stored as class attributes are used.

        @param name: The name of the object
        @param params: A dict containing VM params
        @param root_dir: Base directory for relative filenames
        @param migration_mode: If supplied, start VM for incoming migration
                using this protocol (either 'tcp', 'unix' or 'exec')
        @param migration_exec_cmd: Command to embed in '-incoming "exec: ..."'
                (e.g. 'gzip -c -d filename') if migration_mode is 'exec'
        @param mac_source: A VM object from which to copy MAC addresses. If not
                specified, new addresses will be generated.

        @raise VMCreateError: If qemu terminates unexpectedly
        @raise VMKVMInitError: If KVM initialization fails
        @raise VMHugePageError: If hugepage initialization fails
        @raise VMImageMissingError: If a CD image is missing
        @raise VMHashMismatchError: If a CD image hash has doesn't match the
                expected hash
        @raise VMBadPATypeError: If an unsupported PCI assignment type is
                requested
        @raise VMPAError: If no PCI assignable devices could be assigned
        """
        error.context("creating '%s'" % self.name)
        self.destroy(free_mac_addresses=False)

        if name is not None:
            self.name = name
        if params is not None:
            self.params = params
        if root_dir is not None:
            self.root_dir = root_dir
        name = self.name
        params = self.params
        root_dir = self.root_dir

        # Verify the md5sum of the ISO images
        for cdrom in params.objects("cdroms"):
            if params.get("medium") == "import":
                break
            cdrom_params = params.object_params(cdrom)
            iso = cdrom_params.get("cdrom")
            if ((self.driver_type == 'xen')
                    and (params.get('hvm_or_pv') == 'pv')
                    and (os.path.basename(iso) == 'ks.iso')):
                continue
            if iso:
                iso = utils_misc.get_path(root_dir, iso)
                if not os.path.exists(iso):
                    raise virt_vm.VMImageMissingError(iso)
                compare = False
                if cdrom_params.get("md5sum_1m"):
                    logging.debug("Comparing expected MD5 sum with MD5 sum of "
                                  "first MB of ISO file...")
                    actual_hash = utils.hash_file(iso, 1048576, method="md5")
                    expected_hash = cdrom_params.get("md5sum_1m")
                    compare = True
                elif cdrom_params.get("md5sum"):
                    logging.debug("Comparing expected MD5 sum with MD5 sum of "
                                  "ISO file...")
                    actual_hash = utils.hash_file(iso, method="md5")
                    expected_hash = cdrom_params.get("md5sum")
                    compare = True
                elif cdrom_params.get("sha1sum"):
                    logging.debug("Comparing expected SHA1 sum with SHA1 sum "
                                  "of ISO file...")
                    actual_hash = utils.hash_file(iso, method="sha1")
                    expected_hash = cdrom_params.get("sha1sum")
                    compare = True
                if compare:
                    if actual_hash == expected_hash:
                        logging.debug("Hashes match")
                    else:
                        raise virt_vm.VMHashMismatchError(
                            actual_hash, expected_hash)

        # Make sure the following code is not executed by more than one thread
        # at the same time
        lockfile = open("/tmp/libvirt-autotest-vm-create.lock", "w+")
        fcntl.lockf(lockfile, fcntl.LOCK_EX)

        try:
            # Handle port redirections
            redir_names = params.objects("redirs")
            host_ports = utils_misc.find_free_ports(5000, 6000,
                                                    len(redir_names))
            self.redirs = {}
            for i in range(len(redir_names)):
                redir_params = params.object_params(redir_names[i])
                guest_port = int(redir_params.get("guest_port"))
                self.redirs[guest_port] = host_ports[i]

            # Find available PCI devices
            self.pci_devices = []
            for device in params.objects("pci_devices"):
                self.pci_devices.append(device)

            # Find available VNC port, if needed
            if params.get("display") == "vnc":
                if params.get("vnc_autoport") == "yes":
                    self.vnc_port = None
                    self.vnc_autoport = True
                else:
                    self.vnc_port = utils_misc.find_free_port(5900, 6100)
                    self.vnc_autoport = False

            # Find available spice port, if needed
            if params.get("spice"):
                self.spice_port = utils_misc.find_free_port(8000, 8100)

            # Find random UUID if specified 'uuid = random' in config file
            if params.get("uuid") == "random":
                f = open("/proc/sys/kernel/random/uuid")
                self.uuid = f.read().strip()
                f.close()

            # Generate or copy MAC addresses for all NICs
            for nic in self.virtnet:
                nic_params = dict(nic)
                if mac_source:
                    # Will raise exception if source doesn't
                    # have cooresponding nic
                    logging.debug("Copying mac for nic %s from VM %s" %
                                  (nic.nic_name, mac_source.nam))
                    nic_params['mac'] = mac_source.get_mac_address(
                        nic.nic_name)
                # __make_libvirt_command() calls vm.add_nic (i.e. on a copy)
                nic = self.add_nic(**nic_params)
                logging.debug('VM.create activating nic %s' % nic)
                self.activate_nic(nic.nic_name)

            # Make qemu command
            install_command = self.__make_libvirt_command()

            logging.info("Running libvirt command (reformatted):")
            for item in install_command.replace(" -", " \n    -").splitlines():
                logging.info("%s", item)
            utils.run(install_command, verbose=False)
            # Wait for the domain to be created
            utils_misc.wait_for(func=self.is_alive,
                                timeout=60,
                                text=("waiting for domain %s to start" %
                                      self.name))
            self.uuid = virsh.domuuid(self.name, uri=self.connect_uri)

            # Establish a session with the serial console
            if self.only_pty == True:
                self.serial_console = aexpect.ShellSession(
                    "virsh console %s" % self.name,
                    auto_close=False,
                    output_func=utils_misc.log_line,
                    output_params=("serial-%s.log" % name, ))
            else:
                self.serial_console = aexpect.ShellSession(
                    "tail -f %s" % self.get_serial_console_filename(),
                    auto_close=False,
                    output_func=utils_misc.log_line,
                    output_params=("serial-%s.log" % name, ))

        finally:
            fcntl.lockf(lockfile, fcntl.LOCK_UN)
            lockfile.close()
Example #18
0
def preprocess(test, params, env):
    """
    Preprocess all VMs and images according to the instructions in params.
    Also, collect some host information, such as the KVM version.

    @param test: An Autotest test object.
    @param params: A dict containing all VM and image parameters.
    @param env: The environment (a dict-like object).
    """
    error.context("preprocessing")
    # First, let's verify if this test does require root or not. If it
    # does and the test suite is running as a regular user, we shall just
    # throw a TestNAError exception, which will skip the test.
    if params.get('requires_root', 'no') == 'yes':
        utils_test.verify_running_as_root()

    port = params.get('shell_port')
    prompt = params.get('shell_prompt')
    address = params.get('ovirt_node_address')
    username = params.get('ovirt_node_user')
    password = params.get('ovirt_node_password')

    # Start tcpdump if it isn't already running
    if "address_cache" not in env:
        env["address_cache"] = {}
    if "tcpdump" in env and not env["tcpdump"].is_alive():
        env["tcpdump"].close()
        del env["tcpdump"]
    if "tcpdump" not in env and params.get("run_tcpdump", "yes") == "yes":
        cmd = "%s -npvi any 'port 68'" % utils_misc.find_command("tcpdump")
        if params.get("remote_preprocess") == "yes":
            login_cmd = ("ssh -o UserKnownHostsFile=/dev/null -o \
                         PreferredAuthentications=password -p %s %s@%s" %
                         (port, username, address))
            env["tcpdump"] = aexpect.ShellSession(
                login_cmd,
                output_func=_update_address_cache,
                output_params=(env["address_cache"], ))
            remote.handle_prompts(env["tcpdump"], username, password, prompt)
            env["tcpdump"].sendline(cmd)
        else:
            env["tcpdump"] = aexpect.Tail(command=cmd,
                                          output_func=_tcpdump_handler,
                                          output_params=(
                                              env["address_cache"],
                                              "tcpdump.log",
                                          ))

        if utils_misc.wait_for(lambda: not env["tcpdump"].is_alive(), 0.1, 0.1,
                               1.0):
            logging.warn("Could not start tcpdump")
            logging.warn("Status: %s" % env["tcpdump"].get_status())
            logging.warn(
                "Output:" +
                utils_misc.format_str_for_message(env["tcpdump"].get_output()))

    # Destroy and remove VMs that are no longer needed in the environment
    requested_vms = params.objects("vms")
    for key in env.keys():
        vm = env[key]
        if not isinstance(vm, virt_vm.BaseVM):
            continue
        if not vm.name in requested_vms:
            vm.destroy()
            del env[key]

    if (params.get("auto_cpu_model") == "yes"
            and params.get("vm_type") == "qemu"):
        if not env.get("cpu_model"):
            env["cpu_model"] = utils_misc.get_qemu_best_cpu_model(params)
        params["cpu_model"] = env.get("cpu_model")

    kvm_ver_cmd = params.get("kvm_ver_cmd", "")

    if kvm_ver_cmd:
        try:
            cmd_result = utils.run(kvm_ver_cmd)
            kvm_version = cmd_result.stdout.strip()
        except error.CmdError:
            kvm_version = "Unknown"
    else:
        # Get the KVM kernel module version and write it as a keyval
        if os.path.exists("/dev/kvm"):
            try:
                kvm_version = open("/sys/module/kvm/version").read().strip()
            except Exception:
                kvm_version = os.uname()[2]
        else:
            logging.warning("KVM module not loaded")
            kvm_version = "Unknown"

    logging.debug("KVM version: %s" % kvm_version)
    test.write_test_keyval({"kvm_version": kvm_version})

    # Get the KVM userspace version and write it as a keyval
    kvm_userspace_ver_cmd = params.get("kvm_userspace_ver_cmd", "")

    if kvm_userspace_ver_cmd:
        try:
            cmd_result = utils.run(kvm_userspace_ver_cmd)
            kvm_userspace_version = cmd_result.stdout.strip()
        except error.CmdError:
            kvm_userspace_version = "Unknown"
    else:
        qemu_path = utils_misc.get_path(test.bindir,
                                        params.get("qemu_binary", "qemu"))
        version_line = commands.getoutput("%s -help | head -n 1" % qemu_path)
        matches = re.findall("[Vv]ersion .*?,", version_line)
        if matches:
            kvm_userspace_version = " ".join(matches[0].split()[1:]).strip(",")
        else:
            kvm_userspace_version = "Unknown"

    logging.debug("KVM userspace version: %s" % kvm_userspace_version)
    test.write_test_keyval({"kvm_userspace_version": kvm_userspace_version})

    if params.get("setup_hugepages") == "yes":
        h = test_setup.HugePageConfig(params)
        h.setup()
        if params.get("vm_type") == "libvirt":
            libvirt_vm.libvirtd_restart()

    if params.get("setup_thp") == "yes":
        thp = test_setup.TransparentHugePageConfig(test, params)
        thp.setup()

    # Execute any pre_commands
    if params.get("pre_command"):
        process_command(test, params, env, params.get("pre_command"),
                        int(params.get("pre_command_timeout", "600")),
                        params.get("pre_command_noncritical") == "yes")

    #Clone master image from vms.
    base_dir = data_dir.get_data_dir()
    if params.get("master_images_clone"):
        for vm_name in params.get("vms").split():
            vm = env.get_vm(vm_name)
            if vm:
                vm.destroy(free_mac_addresses=False)
                env.unregister_vm(vm_name)

            vm_params = params.object_params(vm_name)
            for image in vm_params.get("master_images_clone").split():
                image_obj = qemu_storage.QemuImg(params, base_dir, image)
                image_obj.clone_image(params, vm_name, image, base_dir)

    # Preprocess all VMs and images
    if params.get("not_preprocess", "no") == "no":
        process(test, params, env, preprocess_image, preprocess_vm)

    # Start the screendump thread
    if params.get("take_regular_screendumps") == "yes":
        global _screendump_thread, _screendump_thread_termination_event
        _screendump_thread_termination_event = threading.Event()
        _screendump_thread = threading.Thread(target=_take_screendumps,
                                              name='ScreenDump',
                                              args=(test, params, env))
        _screendump_thread.start()
Example #19
0
def preprocess(test, params, env):
    """
    Preprocess all VMs and images according to the instructions in params.
    Also, collect some host information, such as the KVM version.

    @param test: An Autotest test object.
    @param params: A dict containing all VM and image parameters.
    @param env: The environment (a dict-like object).
    """
    error.context("preprocessing")
    port = params.get("shell_port")
    prompt = params.get("shell_prompt")
    address = params.get("ovirt_node_address")
    username = params.get("ovirt_node_user")
    password = params.get("ovirt_node_password")

    # Start tcpdump if it isn't already running
    if "address_cache" not in env:
        env["address_cache"] = {}
    if "tcpdump" in env and not env["tcpdump"].is_alive():
        env["tcpdump"].close()
        del env["tcpdump"]
    if "tcpdump" not in env and params.get("run_tcpdump", "yes") == "yes":
        cmd = "%s -npvi any 'dst port 68'" % utils_misc.find_command("tcpdump")
        if params.get("remote_preprocess") == "yes":
            logging.debug("Starting tcpdump '%s' on remote host", cmd)
            login_cmd = (
                "ssh -o UserKnownHostsFile=/dev/null -o \
                         PreferredAuthentications=password -p %s %s@%s"
                % (port, username, address)
            )
            env["tcpdump"] = aexpect.ShellSession(
                login_cmd, output_func=_update_address_cache, output_params=(env["address_cache"],)
            )
            remote._remote_login(env["tcpdump"], username, password, prompt)
            env["tcpdump"].sendline(cmd)
        else:
            logging.debug("Starting tcpdump '%s' on local host", cmd)
            env["tcpdump"] = aexpect.Tail(
                command=cmd, output_func=_update_address_cache, output_params=(env["address_cache"],)
            )

        if utils_misc.wait_for(lambda: not env["tcpdump"].is_alive(), 0.1, 0.1, 1.0):
            logging.warn("Could not start tcpdump")
            logging.warn("Status: %s" % env["tcpdump"].get_status())
            logging.warn("Output:" + utils_misc.format_str_for_message(env["tcpdump"].get_output()))

    # Destroy and remove VMs that are no longer needed in the environment
    requested_vms = params.objects("vms")
    for key in env.keys():
        vm = env[key]
        if not utils_misc.is_vm(vm):
            continue
        if not vm.name in requested_vms:
            logging.debug("VM '%s' found in environment but not required for " "test, destroying it" % vm.name)
            vm.destroy()
            del env[key]

    # Get Host cpu type
    if params.get("auto_cpu_model") == "yes":
        if not env.get("cpu_model"):
            env["cpu_model"] = utils_misc.get_cpu_model()
        params["cpu_model"] = env.get("cpu_model")

    kvm_ver_cmd = params.get("kvm_ver_cmd", "")

    if kvm_ver_cmd:
        try:
            cmd_result = utils.run(kvm_ver_cmd)
            kvm_version = cmd_result.stdout.strip()
        except error.CmdError, e:
            kvm_version = "Unknown"
Example #20
0
    def create(self, name=None, params=None, root_dir=None, timeout=5.0, migration_mode=None, mac_source=None):
        """
        Start the VM by running a qemu command.
        All parameters are optional. If name, params or root_dir are not
        supplied, the respective values stored as class attributes are used.

        @param name: The name of the object
        @param params: A dict containing VM params
        @param root_dir: Base directory for relative filenames
        @param migration_mode: If supplied, start VM for incoming migration
                using this protocol (either 'tcp', 'unix' or 'exec')
        @param migration_exec_cmd: Command to embed in '-incoming "exec: ..."'
                (e.g. 'gzip -c -d filename') if migration_mode is 'exec'
        @param mac_source: A VM object from which to copy MAC addresses. If not
                specified, new addresses will be generated.

        @raise VMCreateError: If qemu terminates unexpectedly
        @raise VMKVMInitError: If KVM initialization fails
        @raise VMHugePageError: If hugepage initialization fails
        @raise VMImageMissingError: If a CD image is missing
        @raise VMHashMismatchError: If a CD image hash has doesn't match the
                expected hash
        @raise VMBadPATypeError: If an unsupported PCI assignment type is
                requested
        @raise VMPAError: If no PCI assignable devices could be assigned
        """
        error.context("creating '%s'" % self.name)
        self.destroy(free_mac_addresses=False)

        if name is not None:
            self.name = name
        if params is not None:
            self.params = params
        if root_dir is not None:
            self.root_dir = root_dir
        name = self.name
        params = self.params
        root_dir = self.root_dir

        # Verify the md5sum of the ISO images
        for cdrom in params.objects("cdroms"):
            if params.get("medium") == "import":
                break
            cdrom_params = params.object_params(cdrom)
            iso = cdrom_params.get("cdrom")
            if (
                (self.driver_type == "xen")
                and (params.get("hvm_or_pv") == "pv")
                and (os.path.basename(iso) == "ks.iso")
            ):
                continue
            if iso:
                iso = utils_misc.get_path(data_dir.get_data_dir(), iso)
                if not os.path.exists(iso):
                    raise virt_vm.VMImageMissingError(iso)
                compare = False
                if cdrom_params.get("md5sum_1m"):
                    logging.debug("Comparing expected MD5 sum with MD5 sum of " "first MB of ISO file...")
                    actual_hash = utils.hash_file(iso, 1048576, method="md5")
                    expected_hash = cdrom_params.get("md5sum_1m")
                    compare = True
                elif cdrom_params.get("md5sum"):
                    logging.debug("Comparing expected MD5 sum with MD5 sum of " "ISO file...")
                    actual_hash = utils.hash_file(iso, method="md5")
                    expected_hash = cdrom_params.get("md5sum")
                    compare = True
                elif cdrom_params.get("sha1sum"):
                    logging.debug("Comparing expected SHA1 sum with SHA1 sum " "of ISO file...")
                    actual_hash = utils.hash_file(iso, method="sha1")
                    expected_hash = cdrom_params.get("sha1sum")
                    compare = True
                if compare:
                    if actual_hash == expected_hash:
                        logging.debug("Hashes match")
                    else:
                        raise virt_vm.VMHashMismatchError(actual_hash, expected_hash)

        # Make sure the following code is not executed by more than one thread
        # at the same time
        lockfile = open("/tmp/libvirt-autotest-vm-create.lock", "w+")
        fcntl.lockf(lockfile, fcntl.LOCK_EX)

        try:
            # Handle port redirections
            redir_names = params.objects("redirs")
            host_ports = utils_misc.find_free_ports(5000, 6000, len(redir_names))
            self.redirs = {}
            for i in range(len(redir_names)):
                redir_params = params.object_params(redir_names[i])
                guest_port = int(redir_params.get("guest_port"))
                self.redirs[guest_port] = host_ports[i]

            # Find available PCI devices
            self.pci_devices = []
            for device in params.objects("pci_devices"):
                self.pci_devices.append(device)

            # Find available VNC port, if needed
            if params.get("display") == "vnc":
                if params.get("vnc_autoport") == "yes":
                    self.vnc_port = None
                    self.vnc_autoport = True
                else:
                    self.vnc_port = utils_misc.find_free_port(5900, 6100)
                    self.vnc_autoport = False

            # Find available spice port, if needed
            if params.get("spice"):
                self.spice_port = utils_misc.find_free_port(8000, 8100)

            # Find random UUID if specified 'uuid = random' in config file
            if params.get("uuid") == "random":
                f = open("/proc/sys/kernel/random/uuid")
                self.uuid = f.read().strip()
                f.close()

            # Generate or copy MAC addresses for all NICs
            for nic in self.virtnet:
                nic_params = dict(nic)
                if mac_source:
                    # Will raise exception if source doesn't
                    # have cooresponding nic
                    logging.debug("Copying mac for nic %s from VM %s" % (nic.nic_name, mac_source.nam))
                    nic_params["mac"] = mac_source.get_mac_address(nic.nic_name)
                # make_create_command() calls vm.add_nic (i.e. on a copy)
                nic = self.add_nic(**nic_params)
                logging.debug("VM.create activating nic %s" % nic)
                self.activate_nic(nic.nic_name)

            # Make qemu command
            install_command = self.make_create_command()

            logging.info("Running libvirt command (reformatted):")
            for item in install_command.replace(" -", " \n    -").splitlines():
                logging.info("%s", item)
            utils.run(install_command, verbose=False)
            # Wait for the domain to be created
            utils_misc.wait_for(func=self.is_alive, timeout=60, text=("waiting for domain %s to start" % self.name))
            self.uuid = virsh.domuuid(self.name, uri=self.connect_uri)

            # Establish a session with the serial console
            if self.only_pty == True:
                self.serial_console = aexpect.ShellSession(
                    "virsh console %s" % self.name,
                    auto_close=False,
                    output_func=utils_misc.log_line,
                    output_params=("serial-%s.log" % name,),
                )
            else:
                self.serial_console = aexpect.ShellSession(
                    "tail -f %s" % self.get_serial_console_filename(),
                    auto_close=False,
                    output_func=utils_misc.log_line,
                    output_params=("serial-%s.log" % name,),
                )

        finally:
            fcntl.lockf(lockfile, fcntl.LOCK_UN)
            lockfile.close()
Example #21
0
                video_file = os.path.join(
                    test.debugdir, "%s-%s.webm" % (vm.name, test.iteration))
            else:
                video_file = os.path.join(
                    test.debugdir, "%s-%s.ogg" % (vm.name, test.iteration))
            logging.debug("Encoding video file %s", video_file)
            video.start(screendump_dir, video_file)

        except Exception, detail:
            logging.info("Video creation failed for vm %s: %s", vm.name,
                         detail)

    if params.get("kill_vm") == "yes":
        kill_vm_timeout = float(params.get("kill_vm_timeout", 0))
        if kill_vm_timeout:
            utils_misc.wait_for(vm.is_dead, kill_vm_timeout, 0, 1)
        vm.destroy(gracefully=params.get("kill_vm_gracefully") == "yes")


def process_command(test, params, env, command, command_timeout,
                    command_noncritical):
    """
    Pre- or post- custom commands to be executed before/after a test is run

    @param test: An Autotest test object.
    @param params: A dict containing all VM and image parameters.
    @param env: The environment (a dict-like object).
    @param command: Command to be run.
    @param command_timeout: Timeout for command execution.
    @param command_noncritical: If True test will not fail if command fails.
    """