Example #1
0
    def get_address(self, index=0):
        """
        Return the address of a NIC of the guest, in host space.

        If port redirection is used, return 'localhost' (the NIC has no IP
        address of its own).  Otherwise return the NIC's IP address.

        @param index: Index of the NIC whose address is requested.
        """
        nics = kvm_utils.get_sub_dict_names(self.params, "nics")
        nic_name = nics[index]
        nic_params = kvm_utils.get_sub_dict(self.params, nic_name)
        if nic_params.get("nic_mode") == "tap":
            mac, ip = kvm_utils.get_mac_ip_pair_from_dict(nic_params)
            if not mac:
                logging.debug("MAC address unavailable")
                return None
            if not ip or nic_params.get("always_use_tcpdump") == "yes":
                # Get the IP address from the cache
                ip = self.address_cache.get(mac)
                if not ip:
                    logging.debug("Could not find IP address for MAC address: " "%s" % mac)
                    return None
                # Make sure the IP address is assigned to this guest
                nic_dicts = [kvm_utils.get_sub_dict(self.params, nic) for nic in nics]
                macs = [kvm_utils.get_mac_ip_pair_from_dict(dict)[0] for dict in nic_dicts]
                if not kvm_utils.verify_ip_address_ownership(ip, macs):
                    logging.debug("Could not verify MAC-IP address mapping: " "%s ---> %s" % (mac, ip))
                    return None
            return ip
        else:
            return "localhost"
    def chk_fmt_model(device, fmt_model, info_cmd, str):
        f_fail = 0
        devices = kvm_utils.get_sub_dict_names(params, device)
        for chk_device in devices:
            expected = kvm_utils.get_sub_dict(params, chk_device).get(fmt_model)
            if not expected:
                expected = "rtl8139"
            try:
                o = vm.monitor.info(info_cmd)
            except kvm_monitor.MonitorError, e:
                f_fail += 1
                logging.error(e)
                logging.error("info/query monitor command failed (%s)",
                              info_cmd)

            device_found = re.findall(str, o)
            logging.debug("Found devices: %s" % device_found)
            found = False
            for fm in device_found:
                if expected in fm:
                    found = True

            if not found:
                f_fail += 1
                logging.error("%s model mismatch:")
                logging.error("    Assigned to VM: %s" % expected)
                logging.error("    Reported by OS: %s" % device_found)
Example #3
0
    def get_address(self, index=0):
        """
        Return the address of a NIC of the guest, in host space.

        If port redirection is used, return 'localhost' (the NIC has no IP
        address of its own).  Otherwise return the NIC's IP address.

        @param index: Index of the NIC whose address is requested.
        """
        nics = kvm_utils.get_sub_dict_names(self.params, "nics")
        nic_name = nics[index]
        nic_params = kvm_utils.get_sub_dict(self.params, nic_name)
        if nic_params.get("nic_mode") == "tap":
            mac = self.get_mac_address(index)
            if not mac:
                logging.debug("MAC address unavailable")
                return None
            mac = mac.lower()
            # Get the IP address from the cache
            ip = self.address_cache.get(mac)
            if not ip:
                logging.debug("Could not find IP address for MAC address: %s" %
                              mac)
                return None
            # Make sure the IP address is assigned to this guest
            macs = [self.get_mac_address(i) for i in range(len(nics))]
            if not kvm_utils.verify_ip_address_ownership(ip, macs):
                logging.debug("Could not verify MAC-IP address mapping: "
                              "%s ---> %s" % (mac, ip))
                return None
            return ip
        else:
            return "localhost"
Example #4
0
def postprocess_on_error(test, params, env):
    """
    Perform postprocessing operations required only if the test failed.

    @param test: An Autotest test object.
    @param params: A dict containing all VM and image parameters.
    @param env: The environment (a dict-like object).
    """
    params.update(kvm_utils.get_sub_dict(params, "on_error"))
Example #5
0
    def get_ifname(self, nic_index=0):
        """
        Return the ifname of a tap device associated with a NIC.

        @param nic_index: Index of the NIC
        """
        nics = kvm_utils.get_sub_dict_names(self.params, "nics")
        nic_name = nics[nic_index]
        nic_params = kvm_utils.get_sub_dict(self.params, nic_name)
        if nic_params.get("nic_ifname"):
            return nic_params.get("nic_ifname")
        else:
            return "t%d-%s" % (nic_index, self.instance[-11:])
Example #6
0
def process(test, params, env, image_func, vm_func):
    """
    Pre- or post-process VMs and images according to the instructions in params.
    Call image_func for each image listed in params and vm_func for each VM.

    @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 image_func: A function to call for each image.
    @param vm_func: A function to call for each VM.
    """
    # Get list of VMs specified for this test
    vm_names = kvm_utils.get_sub_dict_names(params, "vms")
    for vm_name in vm_names:
        vm_params = kvm_utils.get_sub_dict(params, vm_name)
        # Get list of images specified for this VM
        image_names = kvm_utils.get_sub_dict_names(vm_params, "images")
        for image_name in image_names:
            image_params = kvm_utils.get_sub_dict(vm_params, image_name)
            # Call image_func for each image
            image_func(test, image_params)
        # Call vm_func for each vm
        vm_func(test, vm_params, env, vm_name)
Example #7
0
    def get_port(self, port, nic_index=0):
        """
        Return the port in host space corresponding to port in guest space.

        @param port: Port number in host space.
        @param nic_index: Index of the NIC.
        @return: If port redirection is used, return the host port redirected
                to guest port port. Otherwise return port.
        """
        nic_name = kvm_utils.get_sub_dict_names(self.params, "nics")[nic_index]
        nic_params = kvm_utils.get_sub_dict(self.params, nic_name)
        if nic_params.get("nic_mode") == "tap":
            return port
        else:
            if not self.redirs.has_key(port):
                logging.warn("Warning: guest port %s requested but not " "redirected" % port)
            return self.redirs.get(port)
Example #8
0
    def create(self, name=None, params=None, root_dir=None, for_migration=False, timeout=5.0):
        """
        Start the VM by running a qemu command.
        All parameters are optional. The following applies to all parameters
        but for_migration: If a parameter is not supplied, the corresponding
        value stored in the class attributes is used, and if it is supplied,
        it is stored for later use.

        @param name: The name of the object
        @param params: A dict containing VM params
        @param root_dir: Base directory for relative filenames
        @param for_migration: If True, start the VM with the -incoming
        option
        """
        self.destroy()

        if name != None:
            self.name = name
        if params != None:
            self.params = params
        if root_dir != None:
            self.root_dir = root_dir
        name = self.name
        params = self.params
        root_dir = self.root_dir

        # Verify the md5sum of the ISO image
        iso = params.get("cdrom")
        if iso:
            iso = kvm_utils.get_path(root_dir, iso)
            if not os.path.exists(iso):
                logging.error("ISO file not found: %s" % iso)
                return False
            compare = False
            if params.get("md5sum_1m"):
                logging.debug("Comparing expected MD5 sum with MD5 sum of " "first MB of ISO file...")
                actual_md5sum = kvm_utils.md5sum_file(iso, 1048576)
                expected_md5sum = params.get("md5sum_1m")
                compare = True
            elif params.get("md5sum"):
                logging.debug("Comparing expected MD5 sum with MD5 sum of ISO " "file...")
                actual_md5sum = kvm_utils.md5sum_file(iso)
                expected_md5sum = params.get("md5sum")
                compare = True
            if compare:
                if actual_md5sum == expected_md5sum:
                    logging.debug("MD5 sums match")
                else:
                    logging.error("Actual MD5 sum differs from expected one")
                    return False

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

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

            # Find available VNC port, if needed
            if params.get("display") == "vnc":
                self.vnc_port = kvm_utils.find_free_port(5900, 6000)

            # 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()

            # Make qemu command
            qemu_command = self.make_qemu_command()

            # Is this VM supposed to accept incoming migrations?
            if for_migration:
                # Find available migration port
                self.migration_port = kvm_utils.find_free_port(5200, 6000)
                # Add -incoming option to the qemu command
                qemu_command += " -incoming tcp:0:%d" % self.migration_port

            logging.debug("Running qemu command:\n%s", qemu_command)
            self.process = kvm_subprocess.run_bg(qemu_command, None, logging.debug, "(qemu) ")

            if not self.process.is_alive():
                logging.error("VM could not be created; " "qemu command failed:\n%s" % qemu_command)
                logging.error("Status: %s" % self.process.get_status())
                logging.error("Output:" + kvm_utils.format_str_for_message(self.process.get_output()))
                self.destroy()
                return False

            if not kvm_utils.wait_for(self.is_alive, timeout, 0, 1):
                logging.error("VM is not alive for some reason; " "qemu command:\n%s" % qemu_command)
                self.destroy()
                return False

            # Get the output so far, to see if we have any problems with
            # hugepage setup.
            output = self.process.get_output()

            if "alloc_mem_area" in output:
                logging.error("Could not allocate hugepage memory; " "qemu command:\n%s" % qemu_command)
                logging.error("Output:" + kvm_utils.format_str_for_message(self.process.get_output()))
                return False

            logging.debug("VM appears to be alive with PID %d", self.process.get_pid())
            return True

        finally:
            fcntl.lockf(lockfile, fcntl.LOCK_UN)
            lockfile.close()
Example #9
0
    def make_qemu_command(self, name=None, params=None, root_dir=None):
        """
        Generate a qemu command line. All parameters are optional. If a
        parameter is not supplied, the corresponding value stored in the
        class attributes is used.

        @param name: The name of the object
        @param params: A dict containing VM params
        @param root_dir: Base directory for relative filenames

        @note: The params dict should contain:
               mem -- memory size in MBs
               cdrom -- ISO filename to use with the qemu -cdrom parameter
               extra_params -- a string to append to the qemu command
               shell_port -- port of the remote shell daemon on the guest
               (SSH, Telnet or the home-made Remote Shell Server)
               shell_client -- client program to use for connecting to the
               remote shell daemon on the guest (ssh, telnet or nc)
               x11_display -- if specified, the DISPLAY environment variable
               will be be set to this value for the qemu process (useful for
               SDL rendering)
               images -- a list of image object names, separated by spaces
               nics -- a list of NIC object names, separated by spaces

               For each image in images:
               drive_format -- string to pass as 'if' parameter for this
               image (e.g. ide, scsi)
               image_snapshot -- if yes, pass 'snapshot=on' to qemu for
               this image
               image_boot -- if yes, pass 'boot=on' to qemu for this image
               In addition, all parameters required by get_image_filename.

               For each NIC in nics:
               nic_model -- string to pass as 'model' parameter for this
               NIC (e.g. e1000)
        """
        if name == None:
            name = self.name
        if params == None:
            params = self.params
        if root_dir == None:
            root_dir = self.root_dir

        # Start constructing the qemu command
        qemu_cmd = ""
        # Set the X11 display parameter if requested
        if params.get("x11_display"):
            qemu_cmd += "DISPLAY=%s " % params.get("x11_display")
        # Add the qemu binary
        qemu_cmd += kvm_utils.get_path(root_dir, params.get("qemu_binary", "qemu"))
        # Add the VM's name
        qemu_cmd += " -name '%s'" % name
        # Add the monitor socket parameter
        qemu_cmd += " -monitor unix:%s,server,nowait" % self.monitor_file_name

        for image_name in kvm_utils.get_sub_dict_names(params, "images"):
            image_params = kvm_utils.get_sub_dict(params, image_name)
            if image_params.get("boot_drive") == "no":
                continue
            qemu_cmd += " -drive file=%s" % get_image_filename(image_params, root_dir)
            if image_params.get("drive_format"):
                qemu_cmd += ",if=%s" % image_params.get("drive_format")
            if image_params.get("drive_cache"):
                qemu_cmd += ",cache=%s" % image_params.get("drive_cache")
            if image_params.get("drive_serial"):
                qemu_cmd += ",serial=%s" % image_params.get("drive_serial")
            if image_params.get("image_snapshot") == "yes":
                qemu_cmd += ",snapshot=on"
            if image_params.get("image_boot") == "yes":
                qemu_cmd += ",boot=on"

        vlan = 0
        for nic_name in kvm_utils.get_sub_dict_names(params, "nics"):
            nic_params = kvm_utils.get_sub_dict(params, nic_name)
            # Handle the '-net nic' part
            qemu_cmd += " -net nic,vlan=%d" % vlan
            if nic_params.get("nic_model"):
                qemu_cmd += ",model=%s" % nic_params.get("nic_model")
            if nic_params.has_key("address_index"):
                mac, ip = kvm_utils.get_mac_ip_pair_from_dict(nic_params)
                if mac:
                    qemu_cmd += ",macaddr=%s" % mac
            # Handle the '-net tap' or '-net user' part
            mode = nic_params.get("nic_mode", "user")
            qemu_cmd += " -net %s,vlan=%d" % (mode, vlan)
            if mode == "tap":
                if nic_params.get("nic_ifname"):
                    qemu_cmd += ",ifname=%s" % nic_params.get("nic_ifname")
                script_path = nic_params.get("nic_script")
                if script_path:
                    script_path = kvm_utils.get_path(root_dir, script_path)
                    qemu_cmd += ",script=%s" % script_path
                script_path = nic_params.get("nic_downscript")
                if script_path:
                    script_path = kvm_utils.get_path(root_dir, script_path)
                    qemu_cmd += ",downscript=%s" % script_path
            # Proceed to next NIC
            vlan += 1

        mem = params.get("mem")
        if mem:
            qemu_cmd += " -m %s" % mem

        iso = params.get("cdrom")
        if iso:
            iso = kvm_utils.get_path(root_dir, iso)
            qemu_cmd += " -cdrom %s" % iso

        extra_params = params.get("extra_params")
        if extra_params:
            qemu_cmd += " %s" % extra_params

        for redir_name in kvm_utils.get_sub_dict_names(params, "redirs"):
            redir_params = kvm_utils.get_sub_dict(params, redir_name)
            guest_port = int(redir_params.get("guest_port"))
            host_port = self.redirs.get(guest_port)
            qemu_cmd += " -redir tcp:%s::%s" % (host_port, guest_port)

        if params.get("display") == "vnc":
            qemu_cmd += " -vnc :%d" % (self.vnc_port - 5900)
        elif params.get("display") == "sdl":
            qemu_cmd += " -sdl"
        elif params.get("display") == "nographic":
            qemu_cmd += " -nographic"

        if params.get("uuid") == "random":
            qemu_cmd += " -uuid %s" % self.uuid
        elif params.get("uuid"):
            qemu_cmd += " -uuid %s" % params.get("uuid")

        return qemu_cmd
Example #10
0
def run_pci_hotplug(test, params, env):
    """
    Test hotplug of PCI devices.

    (Elements between [] are configurable test parameters)
    1) PCI add a deivce (NIC / block)
    2) Compare output of monitor command 'info pci'.
    3) Compare output of guest command [reference_cmd].
    4) Verify whether pci_model is shown in [pci_find_cmd].
    5) Check whether the newly added PCI device works fine.
    6) PCI delete the device, verify whether could remove the PCI device.

    @param test:   KVM test object.
    @param params: Dictionary with the test parameters.
    @param env:    Dictionary with test environment.
    """
    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
    timeout = int(params.get("login_timeout", 360))
    session = kvm_test_utils.wait_for_login(vm, timeout=timeout)

    # Modprobe the module if specified in config file
    module = params.get("modprobe_module")
    if module:
        session.cmd("modprobe %s" % module)

    # Get output of command 'info pci' as reference
    info_pci_ref = vm.monitor.info("pci")

    # Get output of command as reference
    reference = session.cmd_output(params.get("reference_cmd"))

    tested_model = params.get("pci_model")
    test_type = params.get("pci_type")
    image_format = params.get("image_format_stg")

    # Probe qemu to verify what is the supported syntax for PCI hotplug
    cmd_output = vm.monitor.cmd("?")
    if len(re.findall("\ndevice_add", cmd_output)) > 0:
        cmd_type = "device_add"
    elif len(re.findall("\npci_add", cmd_output)) > 0:
        cmd_type = "pci_add"
    else:
        raise error.TestError("Unknow version of qemu")

    if cmd_type == "pci_add":
        if test_type == "nic":
            pci_add_cmd = "pci_add pci_addr=auto nic model=%s" % tested_model
        elif test_type == "block":
            image_params = kvm_utils.get_sub_dict(params, "stg")
            image_filename = kvm_vm.get_image_filename(image_params,
                                                       test.bindir)
            pci_add_cmd = ("pci_add pci_addr=auto storage file=%s,if=%s" %
                           (image_filename, tested_model))
        # Execute pci_add (should be replaced by a proper monitor method call)
        add_output = vm.monitor.cmd(pci_add_cmd)
        if not "OK domain" in add_output:
            raise error.TestFail("Add PCI device failed. "
                                 "Monitor command is: %s, Output: %r" %
                                 (pci_add_cmd, add_output))
        after_add = vm.monitor.info("pci")

    elif cmd_type == "device_add":
        driver_id = test_type + "-" + kvm_utils.generate_random_id()
        id = test_type + "-" + kvm_utils.generate_random_id()
        if test_type == "nic":
            if tested_model == "virtio":
                tested_model = "virtio-net-pci"
            pci_add_cmd = "device_add id=%s,driver=%s" % (id, tested_model)

        elif test_type == "block":
            image_params = kvm_utils.get_sub_dict(params, "stg")
            image_filename = kvm_vm.get_image_filename(image_params,
                                                       test.bindir)
            if tested_model == "virtio":
                tested_model = "virtio-blk-pci"

            if tested_model == "scsi":
                tested_model = "scsi-disk"

            driver_add_cmd = (" __com.redhat_drive_add "
                              "file=%s,format=%s,id=%s" %
                              (image_filename, image_format, driver_id))
            pci_add_cmd = ("device_add id=%s,driver=%s,drive=%s" %
                           (id, tested_model, driver_id))
            driver_output = vm.monitor.cmd(driver_add_cmd)

        # Check if the device is support in qemu
        devices_support = vm.monitor.cmd("%s ?" % cmd_type)
        if len(re.findall(tested_model, devices_support)) > 0:
            add_output = vm.monitor.cmd(pci_add_cmd)
        else:
            raise error.TestError("%s doesn't support device: %s" %
                                  (cmd_type, tested_model))
        after_add = vm.monitor.info("pci")

        if not id in after_add:
            raise error.TestFail("Add device failed. Monitor command is: %s"
                                 ". Output: %r" % (pci_add_cmd, add_output))

    # Define a helper function to delete the device
    def pci_del(ignore_failure=False):
        if cmd_type == "pci_add":
            result_domain, bus, slot, function = add_output.split(',')
            domain = int(result_domain.split()[2])
            bus = int(bus.split()[1])
            slot = int(slot.split()[1])
            pci_addr = "%x:%x:%x" % (domain, bus, slot)
            cmd = "pci_del pci_addr=%s" % pci_addr
        elif cmd_type == "device_add":
            cmd = "device_del %s" % id
        # This should be replaced by a proper monitor method call
        vm.monitor.cmd(cmd)

        def device_removed():
            after_del = vm.monitor.info("pci")
            return after_del != after_add

        if (not kvm_utils.wait_for(device_removed, 10, 0, 1)
            and not ignore_failure):
            raise error.TestFail("Failed to hot remove PCI device: %s. "
                                 "Monitor command: %s" %
                                 (tested_model, cmd))

    try:
        # Compare the output of 'info pci'
        if after_add == info_pci_ref:
            raise error.TestFail("No new PCI device shown after executing "
                                 "monitor command: 'info pci'")

        # Define a helper function to compare the output
        def new_shown():
            o = session.cmd_output(params.get("reference_cmd"))
            return o != reference

        secs = int(params.get("wait_secs_for_hook_up"))
        if not kvm_utils.wait_for(new_shown, 30, secs, 3):
            raise error.TestFail("No new device shown in output of command "
                                 "executed inside the guest: %s" %
                                 params.get("reference_cmd"))

        # Define a helper function to catch PCI device string
        def find_pci():
            o = session.cmd_output(params.get("find_pci_cmd"))
            return params.get("match_string") in o

        if not kvm_utils.wait_for(find_pci, 30, 3, 3):
            raise error.TestFail("PCI %s %s device not found in guest. "
                                 "Command was: %s" %
                                 (tested_model, test_type,
                                  params.get("find_pci_cmd")))

        # Test the newly added device
        try:
            session.cmd(params.get("pci_test_cmd"))
        except kvm_subprocess.ShellError, e:
            raise error.TestFail("Check for %s device failed after PCI "
                                 "hotplug. Output: %r" % (test_type, e.output))

        session.close()
def run_whql_submission(test, params, env):
    """
    WHQL submission test:
    1) Log into the guest (the client machine) and into a DTM server machine
    2) Copy the automation program binary (dsso_test_binary) to the server machine
    3) Run the automation program
    4) Pass the program all relevant parameters (e.g. device_data)
    5) Wait for the program to terminate
    6) Parse and report job results
    (logs and HTML reports are placed in test.bindir)

    @param test: kvm test object
    @param params: Dictionary with the test parameters
    @param env: Dictionary with test environment.
    """
    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
    session = kvm_test_utils.wait_for_login(vm, 0, 240)

    # Collect parameters
    server_address = params.get("server_address")
    server_shell_port = int(params.get("server_shell_port"))
    server_file_transfer_port = int(params.get("server_file_transfer_port"))
    server_studio_path = params.get("server_studio_path", "%programfiles%\\ " "Microsoft Driver Test Manager\\Studio")
    dsso_test_binary = params.get("dsso_test_binary", "deps/whql_submission_15.exe")
    dsso_test_binary = kvm_utils.get_path(test.bindir, dsso_test_binary)
    test_device = params.get("test_device")
    job_filter = params.get("job_filter", ".*")
    test_timeout = float(params.get("test_timeout", 600))
    wtt_services = params.get("wtt_services")

    # Restart WTT service(s) on the client
    logging.info("Restarting WTT services on client")
    for svc in wtt_services.split():
        kvm_test_utils.stop_windows_service(session, svc)
    for svc in wtt_services.split():
        kvm_test_utils.start_windows_service(session, svc)

    # Copy dsso_test_binary to the server
    rss_file_transfer.upload(
        server_address, server_file_transfer_port, dsso_test_binary, server_studio_path, timeout=60
    )

    # Open a shell session with the server
    server_session = kvm_utils.remote_login(
        "nc", server_address, server_shell_port, "", "", session.prompt, session.linesep
    )
    server_session.set_status_test_command(session.status_test_command)

    # Get the computer names of the server and client
    cmd = "echo %computername%"
    server_name = server_session.cmd_output(cmd).strip()
    client_name = session.cmd_output(cmd).strip()
    session.close()

    # Run the automation program on the server
    server_session.cmd("cd %s" % server_studio_path)
    cmd = "%s %s %s %s %s %s" % (
        os.path.basename(dsso_test_binary),
        server_name,
        client_name,
        "%s_pool" % client_name,
        "%s_submission" % client_name,
        test_timeout,
    )
    server_session.sendline(cmd)

    # Helper function: wait for a given prompt and raise an exception if an
    # error occurs
    def find_prompt(prompt):
        m, o = server_session.read_until_last_line_matches(
            [prompt, server_session.prompt], print_func=logging.info, timeout=600
        )
        if m != 0:
            errors = re.findall("^Error:.*$", o, re.I | re.M)
            if errors:
                raise error.TestError(errors[0])
            else:
                raise error.TestError("Error running automation program: " "could not find '%s' prompt" % prompt)

    # Tell the automation program which device to test
    find_prompt("Device to test:")
    server_session.sendline(test_device)

    # Tell the automation program which jobs to run
    find_prompt("Jobs to run:")
    server_session.sendline(job_filter)

    # Give the automation program all the device data supplied by the user
    find_prompt("DeviceData name:")
    for dd in kvm_utils.get_sub_dict_names(params, "device_data"):
        dd_params = kvm_utils.get_sub_dict(params, dd)
        if dd_params.get("dd_name") and dd_params.get("dd_data"):
            server_session.sendline(dd_params.get("dd_name"))
            server_session.sendline(dd_params.get("dd_data"))
    server_session.sendline()

    # Give the automation program all the descriptor information supplied by
    # the user
    find_prompt("Descriptor path:")
    for desc in kvm_utils.get_sub_dict_names(params, "descriptors"):
        desc_params = kvm_utils.get_sub_dict(params, desc)
        if desc_params.get("desc_path"):
            server_session.sendline(desc_params.get("desc_path"))
    server_session.sendline()

    # Wait for the automation program to terminate
    try:
        o = server_session.read_up_to_prompt(print_func=logging.info, timeout=test_timeout + 300)
        # (test_timeout + 300 is used here because the automation program is
        # supposed to terminate cleanly on its own when test_timeout expires)
        done = True
    except kvm_subprocess.ExpectError, e:
        o = e.output
        done = False
Example #12
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.
        """
        self.destroy()

        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 image
        iso = params.get("cdrom")
        if iso:
            iso = kvm_utils.get_path(root_dir, iso)
            if not os.path.exists(iso):
                logging.error("ISO file not found: %s" % iso)
                return False
            compare = False
            if 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 = params.get("md5sum_1m")
                compare = True
            elif 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 = params.get("md5sum")
                compare = True
            elif 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 = params.get("sha1sum")
                compare = True
            if compare:
                if actual_hash == expected_hash:
                    logging.debug("Hashes match")
                else:
                    logging.error("Actual hash differs from expected one")
                    return False

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

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

            # Generate netdev IDs for all NICs
            self.netdev_id = []
            for nic in kvm_utils.get_sub_dict_names(params, "nics"):
                self.netdev_id.append(kvm_utils.generate_random_id())

            # Find available VNC port, if needed
            if params.get("display") == "vnc":
                self.vnc_port = kvm_utils.find_free_port(5900, 6100)

            # 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
            num_nics = len(kvm_utils.get_sub_dict_names(params, "nics"))
            for vlan in range(num_nics):
                nic_name = kvm_utils.get_sub_dict_names(params, "nics")[vlan]
                nic_params = kvm_utils.get_sub_dict(params, nic_name)
                if nic_params.get("nic_mac", None):
                    mac = nic_params.get("nic_mac")
                    kvm_utils.set_mac_address(self.instance, vlan, mac)
                else:
                    mac = mac_source and mac_source.get_mac_address(vlan)
                    if mac:
                        kvm_utils.set_mac_address(self.instance, vlan, mac)
                    else:
                        kvm_utils.generate_mac_address(self.instance, vlan)

            # Assign a PCI assignable device
            self.pci_assignable = None
            pa_type = params.get("pci_assignable")
            if pa_type in ["vf", "pf", "mixed"]:
                pa_devices_requested = params.get("devices_requested")

                # Virtual Functions (VF) assignable devices
                if pa_type == "vf":
                    self.pci_assignable = kvm_utils.PciAssignable(
                        type=pa_type,
                        driver=params.get("driver"),
                        driver_option=params.get("driver_option"),
                        devices_requested=pa_devices_requested)
                # Physical NIC (PF) assignable devices
                elif pa_type == "pf":
                    self.pci_assignable = kvm_utils.PciAssignable(
                        type=pa_type,
                        names=params.get("device_names"),
                        devices_requested=pa_devices_requested)
                # Working with both VF and PF
                elif pa_type == "mixed":
                    self.pci_assignable = kvm_utils.PciAssignable(
                        type=pa_type,
                        driver=params.get("driver"),
                        driver_option=params.get("driver_option"),
                        names=params.get("device_names"),
                        devices_requested=pa_devices_requested)

                self.pa_pci_ids = self.pci_assignable.request_devs()

                if self.pa_pci_ids:
                    logging.debug("Successfuly assigned devices: %s",
                                  self.pa_pci_ids)
                else:
                    logging.error("No PCI assignable devices were assigned "
                                  "and 'pci_assignable' is defined to %s "
                                  "on your config file. Aborting VM creation.",
                                  pa_type)
                    return False

            elif pa_type and pa_type != "no":
                logging.warn("Unsupported pci_assignable type: %s", pa_type)

            # Make qemu command
            qemu_command = self.make_qemu_command()

            # Add migration parameters if required
            if migration_mode == "tcp":
                self.migration_port = kvm_utils.find_free_port(5200, 6000)
                qemu_command += " -incoming tcp:0:%d" % self.migration_port
            elif migration_mode == "unix":
                self.migration_file = "/tmp/migration-unix-%s" % self.instance
                qemu_command += " -incoming unix:%s" % self.migration_file
            elif migration_mode == "exec":
                self.migration_port = kvm_utils.find_free_port(5200, 6000)
                qemu_command += (' -incoming "exec:nc -l %s"' %
                                 self.migration_port)

            logging.debug("Running qemu command:\n%s", qemu_command)
            self.process = kvm_subprocess.run_bg(qemu_command, None,
                                                 logging.debug, "(qemu) ")

            # Make sure the process was started successfully
            if not self.process.is_alive():
                logging.error("VM could not be created; "
                              "qemu command failed:\n%s" % qemu_command)
                logging.error("Status: %s" % self.process.get_status())
                logging.error("Output:" + kvm_utils.format_str_for_message(
                    self.process.get_output()))
                self.destroy()
                return False

            # Establish monitor connections
            self.monitors = []
            for monitor_name in kvm_utils.get_sub_dict_names(params,
                                                             "monitors"):
                monitor_params = kvm_utils.get_sub_dict(params, monitor_name)
                # Wait for monitor connection to succeed
                end_time = time.time() + timeout
                while time.time() < end_time:
                    try:
                        if monitor_params.get("monitor_type") == "qmp":
                            # Add a QMP monitor
                            monitor = kvm_monitor.QMPMonitor(
                                monitor_name,
                                self.get_monitor_filename(monitor_name))
                        else:
                            # Add a "human" monitor
                            monitor = kvm_monitor.HumanMonitor(
                                monitor_name,
                                self.get_monitor_filename(monitor_name))
                    except kvm_monitor.MonitorError, e:
                        logging.warn(e)
                    else:
                        if monitor.is_responsive():
                            break
                    time.sleep(1)
                else:
                    logging.error("Could not connect to monitor '%s'" %
                                  monitor_name)
                    self.destroy()
                    return False
                # Add this monitor to the list
                self.monitors += [monitor]

            # Get the output so far, to see if we have any problems with
            # KVM modules or with hugepage setup.
            output = self.process.get_output()

            if re.search("Could not initialize KVM", output, re.IGNORECASE):
                logging.error("Could not initialize KVM; "
                              "qemu command:\n%s" % qemu_command)
                logging.error("Output:" + kvm_utils.format_str_for_message(
                              self.process.get_output()))
                self.destroy()
                return False

            if "alloc_mem_area" in output:
                logging.error("Could not allocate hugepage memory; "
                              "qemu command:\n%s" % qemu_command)
                logging.error("Output:" + kvm_utils.format_str_for_message(
                              self.process.get_output()))
                self.destroy()
                return False

            logging.debug("VM appears to be alive with PID %s", self.get_pid())

            # Establish a session with the serial console -- requires a version
            # of netcat that supports -U
            self.serial_console = kvm_subprocess.ShellSession(
                "nc -U %s" % self.get_serial_console_filename(),
                auto_close=False,
                output_func=kvm_utils.log_line,
                output_params=("serial-%s.log" % name,))

            return True
Example #13
0
    def make_qemu_command(self, name=None, params=None, root_dir=None):
        """
        Generate a qemu command line. All parameters are optional. If a
        parameter is not supplied, the corresponding value stored in the
        class attributes is used.

        @param name: The name of the object
        @param params: A dict containing VM params
        @param root_dir: Base directory for relative filenames

        @note: The params dict should contain:
               mem -- memory size in MBs
               cdrom -- ISO filename to use with the qemu -cdrom parameter
               extra_params -- a string to append to the qemu command
               shell_port -- port of the remote shell daemon on the guest
               (SSH, Telnet or the home-made Remote Shell Server)
               shell_client -- client program to use for connecting to the
               remote shell daemon on the guest (ssh, telnet or nc)
               x11_display -- if specified, the DISPLAY environment variable
               will be be set to this value for the qemu process (useful for
               SDL rendering)
               images -- a list of image object names, separated by spaces
               nics -- a list of NIC object names, separated by spaces

               For each image in images:
               drive_format -- string to pass as 'if' parameter for this
               image (e.g. ide, scsi)
               image_snapshot -- if yes, pass 'snapshot=on' to qemu for
               this image
               image_boot -- if yes, pass 'boot=on' to qemu for this image
               In addition, all parameters required by get_image_filename.

               For each NIC in nics:
               nic_model -- string to pass as 'model' parameter for this
               NIC (e.g. e1000)
        """
        # Helper function for command line option wrappers
        def has_option(help, option):
            return bool(re.search(r"^-%s(\s|$)" % option, help, re.MULTILINE))

        # Wrappers for all supported qemu command line parameters.
        # This is meant to allow support for multiple qemu versions.
        # Each of these functions receives the output of 'qemu -help' as a
        # parameter, and should add the requested command line option
        # accordingly.

        def add_name(help, name):
            return " -name '%s'" % name

        def add_human_monitor(help, filename):
            return " -monitor unix:'%s',server,nowait" % filename

        def add_qmp_monitor(help, filename):
            return " -qmp unix:'%s',server,nowait" % filename

        def add_serial(help, filename):
            return " -serial unix:'%s',server,nowait" % filename

        def add_mem(help, mem):
            return " -m %s" % mem

        def add_smp(help, smp):
            return " -smp %s" % smp

        def add_cdrom(help, filename, index=None):
            if has_option(help, "drive"):
                cmd = " -drive file='%s',media=cdrom" % filename
                if index is not None: cmd += ",index=%s" % index
                return cmd
            else:
                return " -cdrom '%s'" % filename

        def add_drive(help, filename, index=None, format=None, cache=None,
                      werror=None, serial=None, snapshot=False, boot=False):
            cmd = " -drive file='%s'" % filename
            if index is not None: cmd += ",index=%s" % index
            if format: cmd += ",if=%s" % format
            if cache: cmd += ",cache=%s" % cache
            if werror: cmd += ",werror=%s" % werror
            if serial: cmd += ",serial='%s'" % serial
            if snapshot: cmd += ",snapshot=on"
            if boot: cmd += ",boot=on"
            return cmd

        def add_nic(help, vlan, model=None, mac=None, netdev_id=None,
                    nic_extra_params=None):
            if has_option(help, "netdev"):
                netdev_vlan_str = ",netdev=%s" % netdev_id
            else:
                netdev_vlan_str = ",vlan=%d" % vlan
            if has_option(help, "device"):
                if not model:
                    model = "rtl8139"
                elif model == "virtio":
                    model = "virtio-net-pci"
                cmd = " -device %s" % model + netdev_vlan_str
                if mac:
                    cmd += ",mac='%s'" % mac
                if nic_extra_params:
                    cmd += ",%s" % nic_extra_params
            else:
                cmd = " -net nic" + netdev_vlan_str
                if model:
                    cmd += ",model=%s" % model
                if mac:
                    cmd += ",macaddr='%s'" % mac
            return cmd

        def add_net(help, vlan, mode, ifname=None, script=None,
                    downscript=None, tftp=None, bootfile=None, hostfwd=[],
                    netdev_id=None, netdev_extra_params=None):
            if has_option(help, "netdev"):
                cmd = " -netdev %s,id=%s" % (mode, netdev_id)
                if netdev_extra_params:
                    cmd += ",%s" % netdev_extra_params
            else:
                cmd = " -net %s,vlan=%d" % (mode, vlan)
            if mode == "tap":
                if ifname: cmd += ",ifname='%s'" % ifname
                if script: cmd += ",script='%s'" % script
                cmd += ",downscript='%s'" % (downscript or "no")
            elif mode == "user":
                if tftp and "[,tftp=" in help:
                    cmd += ",tftp='%s'" % tftp
                if bootfile and "[,bootfile=" in help:
                    cmd += ",bootfile='%s'" % bootfile
                if "[,hostfwd=" in help:
                    for host_port, guest_port in hostfwd:
                        cmd += ",hostfwd=tcp::%s-:%s" % (host_port, guest_port)
            return cmd

        def add_floppy(help, filename):
            return " -fda '%s'" % filename

        def add_tftp(help, filename):
            # If the new syntax is supported, don't add -tftp
            if "[,tftp=" in help:
                return ""
            else:
                return " -tftp '%s'" % filename

        def add_bootp(help, filename):
            # If the new syntax is supported, don't add -bootp
            if "[,bootfile=" in help:
                return ""
            else:
                return " -bootp '%s'" % filename

        def add_tcp_redir(help, host_port, guest_port):
            # If the new syntax is supported, don't add -redir
            if "[,hostfwd=" in help:
                return ""
            else:
                return " -redir tcp:%s::%s" % (host_port, guest_port)

        def add_vnc(help, vnc_port):
            return " -vnc :%d" % (vnc_port - 5900)

        def add_sdl(help):
            if has_option(help, "sdl"):
                return " -sdl"
            else:
                return ""

        def add_nographic(help):
            return " -nographic"

        def add_uuid(help, uuid):
            return " -uuid '%s'" % uuid

        def add_pcidevice(help, host):
            return " -pcidevice host='%s'" % host

        def add_kernel(help, filename):
            return " -kernel '%s'" % filename

        def add_initrd(help, filename):
            return " -initrd '%s'" % filename

        def add_kernel_cmdline(help, cmdline):
            return " -append %s" % cmdline

        def add_testdev(help, filename):
            return (" -chardev file,id=testlog,path=%s"
                    " -device testdev,chardev=testlog" % filename)

        def add_no_hpet(help):
            if has_option(help, "no-hpet"):
                return " -no-hpet"
            else:
                return ""

        # End of command line option wrappers

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

        qemu_binary = kvm_utils.get_path(root_dir, params.get("qemu_binary",
                                                              "qemu"))
        # Get the output of 'qemu -help' (log a message in case this call never
        # returns or causes some other kind of trouble)
        logging.debug("Getting output of 'qemu -help'")
        help = commands.getoutput("%s -help" % qemu_binary)

        # Start constructing the qemu command
        qemu_cmd = ""
        # Set the X11 display parameter if requested
        if params.get("x11_display"):
            qemu_cmd += "DISPLAY=%s " % params.get("x11_display")
        # Add the qemu binary
        qemu_cmd += qemu_binary
        # Add the VM's name
        qemu_cmd += add_name(help, name)
        # Add monitors
        for monitor_name in kvm_utils.get_sub_dict_names(params, "monitors"):
            monitor_params = kvm_utils.get_sub_dict(params, monitor_name)
            monitor_filename = self.get_monitor_filename(monitor_name)
            if monitor_params.get("monitor_type") == "qmp":
                qemu_cmd += add_qmp_monitor(help, monitor_filename)
            else:
                qemu_cmd += add_human_monitor(help, monitor_filename)

        # Add serial console redirection
        qemu_cmd += add_serial(help, self.get_serial_console_filename())

        for image_name in kvm_utils.get_sub_dict_names(params, "images"):
            image_params = kvm_utils.get_sub_dict(params, image_name)
            if image_params.get("boot_drive") == "no":
                continue
            qemu_cmd += add_drive(help,
                                  get_image_filename(image_params, root_dir),
                                  image_params.get("drive_index"),
                                  image_params.get("drive_format"),
                                  image_params.get("drive_cache"),
                                  image_params.get("drive_werror"),
                                  image_params.get("drive_serial"),
                                  image_params.get("image_snapshot") == "yes",
                                  image_params.get("image_boot") == "yes")

        redirs = []
        for redir_name in kvm_utils.get_sub_dict_names(params, "redirs"):
            redir_params = kvm_utils.get_sub_dict(params, redir_name)
            guest_port = int(redir_params.get("guest_port"))
            host_port = self.redirs.get(guest_port)
            redirs += [(host_port, guest_port)]

        vlan = 0
        for nic_name in kvm_utils.get_sub_dict_names(params, "nics"):
            nic_params = kvm_utils.get_sub_dict(params, nic_name)
            # Handle the '-net nic' part
            mac = self.get_mac_address(vlan)
            qemu_cmd += add_nic(help, vlan, nic_params.get("nic_model"), mac,
                                self.netdev_id[vlan],
                                nic_params.get("nic_extra_params"))
            # Handle the '-net tap' or '-net user' part
            script = nic_params.get("nic_script")
            downscript = nic_params.get("nic_downscript")
            tftp = nic_params.get("tftp")
            if script:
                script = kvm_utils.get_path(root_dir, script)
            if downscript:
                downscript = kvm_utils.get_path(root_dir, downscript)
            if tftp:
                tftp = kvm_utils.get_path(root_dir, tftp)
            qemu_cmd += add_net(help, vlan, nic_params.get("nic_mode", "user"),
                                self.get_ifname(vlan),
                                script, downscript, tftp,
                                nic_params.get("bootp"), redirs,
                                self.netdev_id[vlan],
                                nic_params.get("netdev_extra_params"))
            # Proceed to next NIC
            vlan += 1

        mem = params.get("mem")
        if mem:
            qemu_cmd += add_mem(help, mem)

        smp = params.get("smp")
        if smp:
            qemu_cmd += add_smp(help, smp)

        cdroms = kvm_utils.get_sub_dict_names(params, "cdroms")
        for cdrom in cdroms:
            cdrom_params = kvm_utils.get_sub_dict(params, cdrom)
            iso = cdrom_params.get("cdrom")
            if iso:
                qemu_cmd += add_cdrom(help, kvm_utils.get_path(root_dir, iso),
                                      cdrom_params.get("drive_index"))

        # We may want to add {floppy_otps} parameter for -fda
        # {fat:floppy:}/path/. However vvfat is not usually recommended.
        floppy = params.get("floppy")
        if floppy:
            floppy = kvm_utils.get_path(root_dir, floppy)
            qemu_cmd += add_floppy(help, floppy)

        tftp = params.get("tftp")
        if tftp:
            tftp = kvm_utils.get_path(root_dir, tftp)
            qemu_cmd += add_tftp(help, tftp)

        bootp = params.get("bootp")
        if bootp:
            qemu_cmd += add_bootp(help, bootp)

        kernel = params.get("kernel")
        if kernel:
            kernel = kvm_utils.get_path(root_dir, kernel)
            qemu_cmd += add_kernel(help, kernel)

        kernel_cmdline = params.get("kernel_cmdline")
        if kernel_cmdline:
            qemu_cmd += add_kernel_cmdline(help, kernel_cmdline)

        initrd = params.get("initrd")
        if initrd:
            initrd = kvm_utils.get_path(root_dir, initrd)
            qemu_cmd += add_initrd(help, initrd)

        for host_port, guest_port in redirs:
            qemu_cmd += add_tcp_redir(help, host_port, guest_port)

        if params.get("display") == "vnc":
            qemu_cmd += add_vnc(help, self.vnc_port)
        elif params.get("display") == "sdl":
            qemu_cmd += add_sdl(help)
        elif params.get("display") == "nographic":
            qemu_cmd += add_nographic(help)

        if params.get("uuid") == "random":
            qemu_cmd += add_uuid(help, self.uuid)
        elif params.get("uuid"):
            qemu_cmd += add_uuid(help, params.get("uuid"))

        if params.get("testdev") == "yes":
            qemu_cmd += add_testdev(help, self.get_testlog_filename())

        if params.get("disable_hpet") == "yes":
            qemu_cmd += add_no_hpet(help)

        # If the PCI assignment step went OK, add each one of the PCI assigned
        # devices to the qemu command line.
        if self.pci_assignable:
            for pci_id in self.pa_pci_ids:
                qemu_cmd += add_pcidevice(help, pci_id)

        extra_params = params.get("extra_params")
        if extra_params:
            qemu_cmd += " %s" % extra_params

        return qemu_cmd
Example #14
0
    def make_qemu_command(self, name=None, params=None, qemu_path=None,
                          image_dir=None, iso_dir=None):
        """
        Generate a qemu command line. All parameters are optional. If a
        parameter is not supplied, the corresponding value stored in the
        class attributes is used.


        @param name: The name of the object
        @param params: A dict containing VM params
        @param qemu_path: The path of the qemu binary
        @param image_dir: The directory where images reside
        @param iso_dir: The directory where ISOs reside


        @note: The params dict should contain:
               mem -- memory size in MBs
               cdrom -- ISO filename to use with the qemu -cdrom parameter
               (iso_dir is pre-pended to the ISO filename)
               extra_params -- a string to append to the qemu command
               ssh_port -- should be 22 for SSH, 23 for Telnet
               x11_display -- if specified, the DISPLAY environment variable
               will be be set to this value for the qemu process (useful for
               SDL rendering)
               images -- a list of image object names, separated by spaces
               nics -- a list of NIC object names, separated by spaces

               For each image in images:
               drive_format -- string to pass as 'if' parameter for this
               image (e.g. ide, scsi)
               image_snapshot -- if yes, pass 'snapshot=on' to qemu for
               this image
               image_boot -- if yes, pass 'boot=on' to qemu for this image
               In addition, all parameters required by get_image_filename.

               For each NIC in nics:
               nic_model -- string to pass as 'model' parameter for this
               NIC (e.g. e1000)
        """
        if name == None:
            name = self.name
        if params == None:
            params = self.params
        if qemu_path == None:
            qemu_path = self.qemu_path
        if image_dir == None:
            image_dir = self.image_dir
        if iso_dir == None:
            iso_dir = self.iso_dir

        # Start constructing the qemu command
        qemu_cmd = ""
        # Set the X11 display parameter if requested
        if params.get("x11_display"):
            qemu_cmd += "DISPLAY=%s " % params.get("x11_display")
        # Add the qemu binary
        qemu_cmd += qemu_path
        # Add the VM's name
        qemu_cmd += " -name '%s'" % name
        # Add the monitor socket parameter
        qemu_cmd += " -monitor unix:%s,server,nowait" % self.monitor_file_name

        for image_name in kvm_utils.get_sub_dict_names(params, "images"):
            image_params = kvm_utils.get_sub_dict(params, image_name)
            qemu_cmd += " -drive file=%s" % get_image_filename(image_params,
                                                               image_dir)
            if image_params.get("drive_format"):
                qemu_cmd += ",if=%s" % image_params.get("drive_format")
            if image_params.get("drive_cache"):
                qemu_cmd += ",cache=%s" % image_params.get("drive_cache")
            if image_params.get("drive_serial"):
                qemu_cmd += ",serial=%s" % image_params.get("drive_serial")
            if image_params.get("image_snapshot") == "yes":
                qemu_cmd += ",snapshot=on"
            if image_params.get("image_boot") == "yes":
                qemu_cmd += ",boot=on"

        vlan = 0
        for nic_name in kvm_utils.get_sub_dict_names(params, "nics"):
            nic_params = kvm_utils.get_sub_dict(params, nic_name)
            qemu_cmd += " -net nic,vlan=%d" % vlan
            if nic_params.get("nic_model"):
                qemu_cmd += ",model=%s" % nic_params.get("nic_model")
            qemu_cmd += " -net user,vlan=%d" % vlan
            vlan += 1

        mem = params.get("mem")
        if mem:
            qemu_cmd += " -m %s" % mem

        iso = params.get("cdrom")
        if iso:
            iso = os.path.join(iso_dir, iso)
            qemu_cmd += " -cdrom %s" % iso

        extra_params = params.get("extra_params")
        if extra_params:
            qemu_cmd += " %s" % extra_params

        for redir_name in kvm_utils.get_sub_dict_names(params, "redirs"):
            redir_params = kvm_utils.get_sub_dict(params, redir_name)
            guest_port = int(redir_params.get("guest_port"))
            host_port = self.get_port(guest_port)
            qemu_cmd += " -redir tcp:%s::%s" % (host_port, guest_port)

        if params.get("display") == "vnc":
            qemu_cmd += " -vnc :%d" % (self.vnc_port - 5900)
        elif params.get("display") == "sdl":
            qemu_cmd += " -sdl"
        elif params.get("display") == "nographic":
            qemu_cmd += " -nographic"

        if params.get("uuid") == "random":
            qemu_cmd += " -uuid %s" % self.uuid
        elif params.get("uuid"):
            qemu_cmd += " -uuid %s" % params.get("uuid")

        return qemu_cmd