From: Onkar Mahajan <[email protected]> Please find the improved patch for adding to libvirt - support for running tests with multiple VMs without interfering with other VM resources. Please let me know if there are any issues- my security patches are based on this.
Signed-off-by: Onkar Mahajan <[email protected]> --- client/tests/libvirt/tests-shared.cfg.sample | 12 +- client/virt/libvirt_vm.py | 152 ++++++++++++++++++++++++++ client/virt/virt_utils.py | 38 +++++-- client/virt/virt_vm.py | 54 ++++++++- 4 files changed, 240 insertions(+), 16 deletions(-) diff --git a/client/tests/libvirt/tests-shared.cfg.sample b/client/tests/libvirt/tests-shared.cfg.sample index 1fe0894..64cf516 100644 --- a/client/tests/libvirt/tests-shared.cfg.sample +++ b/client/tests/libvirt/tests-shared.cfg.sample @@ -28,13 +28,13 @@ include virtio-win.cfg # * The parameters cdrom_unattended, floppy, kernel and initrd are generated # by LIBVIRT autotest, so remember to put them under a writable location # (for example, the cdrom share can be read only) -image_name(_.*)? ?<= /tmp/libvirt_autotest_root/images/ -cdrom(_.*)? ?<= /tmp/libvirt_autotest_root/ -floppy ?<= /tmp/libvirt_autotest_root/ -image_dir = /tmp/libvirt_autotest_root/ +image_name(_.*)? ?<= /tmp/libvirt_autotest_root/$main_vm/ +cdrom(_.*)? ?<= /tmp/libvirt_autotest_root/$main_vm/ +floppy ?<= /tmp/libvirt_autotest_root/$main_vm/ +image_dir = /tmp/libvirt_autotest_root/$main_vm/ Linux..unattended_install: - kernel ?<= /tmp/libvirt_autotest_root/ - initrd ?<= /tmp/libvirt_autotest_root/ + kernel ?<= /tmp/libvirt_autotest_root/$main_vm/ + initrd ?<= /tmp/libvirt_autotest_root/$main_vm/ # Uncomment the following lines to enable abort-on-error mode: #abort_on_error = yes diff --git a/client/virt/libvirt_vm.py b/client/virt/libvirt_vm.py index 25a403b..63ea20f 100644 --- a/client/virt/libvirt_vm.py +++ b/client/virt/libvirt_vm.py @@ -465,6 +465,156 @@ def virsh_migrate(name="", dest_uri="", option="", extra="", uri="", return virsh_cmd(cmd, uri, ignore_status, print_info) +def virsh_vncdisplay(name, uri=""): + """ + Returns the VNC display information for the domain + Returns : [ <IP>, <port> ] + """ + + cmd = "vncdisplay %s" % name + try: + cmdresult = virsh_cmd(cmd, uri).stdout.strip() + # Match IP|'':<port> + m = re.search('^((?:25[0-]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){3}' + '(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))?\:(\d+)', + cmdresult) + ip = m.group(1) + if ip == None: + ip = "0.0.0.0" + vncinfo = [ ip, m.group(2)] + return vncinfo + except error.CmdError, details: + out = str(details) + if out.strip() == "": + domxml = virsh_dumpxml(self.name, self.connect_uri) + dom = minidom.parseString(domxml) + if dom.getElementsByTagName('graphics'): + display = node.childNodes[0] + ap = display.attributes["autoport"] + if ap.value =="yes": + # VNC display configured with autoport='yes' + return ["0.0.0.0", -1] + else: + raise virt_vm.UnsupportedDisplayError(self.name, "vnc") + raise virt_vm.LibvirtVirshCmdError(name, cmd, uri, details) + + +def virsh_list(option="--all", uri = ""): + """ + - list domains - + @param option: Can take various values see 'virsh help list' + for more details. + @param uri : connect uri + + Returns a list : + Returns dictionary with each entry + as : <'dom-name'>: [ <dom-id> , <dom-status> ] + + """ + cmd = "list %s" % option + try: + cmd_res = virsh_cmd(cmd, uri).stdout.strip() + d = {} + for line in cmd_res.split("\n"): + l = [] + m = re.search('^\s([0-9]*\-?)\s+([0-9a-zA-Z\.-_]+)\s+(.*)', line) + if m: + l.append(m.group(1)) + l.append(m.group(3)) + d[m.group(2)] = l + return d + except error.CmdError, details: + raise virt_vm.LibvirtVirshCmdError(virsh_cmd=cmd, connuri=uri, + details=details) + + +def list_all_domains(uri, option="--all"): + """ + Returns list of domains for the uri + """ + try: + val = virsh_list(option, uri) + return val + except virt_vm.LibvirtVirshCmdError: + raise virt_vm.LibvirtFailedGettingInfoError(connuri=uri) + + +def get_graphics_info(name, uri, displaytype): + """ + Returns Graphics display Information configured for a given + domain. + ** Currently supports only VNC display ** + """ + if displaytype == "vnc": + try: + """ + Add virsh functions to get graphics information + here. + """ + vncinfo = virsh_vncdisplay(name, uri) + if vncinfo: + ip = vncinfo[0] + port = vncinfo[1] + return [ip, port] + except virt_vm.UnsupportedDisplayError: + raise NotImplementedError("Only VMs with VNC" + "displays are supported") + except virt_vm.LibvirtVirshCmdError: + raise virt_vm.LibvirtFailedGettingInfoError(name, uri) + + +def get_free_port(name, uri, type, startport, endport): + """ + Get first free port available for a given application. + ** Currently supports only VNC ** + Returns : port (>0) : success + -1 : Failure + """ + if type == "vnc": + val={} + assigned_ports=[] + maxport = 0 + port = 0 + try: + val = list_all_domains(uri) + except virt_vm.LibvirtFailedGettingInfoError: + logging.error("Failed to get domains information for " + "%s" % (self.connect_uri)) + return -1 + for key in val.keys(): + try: + vncinfo = get_graphics_info(key, uri, type) + p = int(vncinfo[1]) + if p >= startport: + p = p-int(startport) + if p >= maxport: + maxport = p + assigned_ports.append(p) + except (virt_vm.LibvirtFailedGettingInfoError, + NotImplementedError): + logging.error("Failed to get information for VM %s " + "at URI %s" % (name, uri)) + return -1 + cmd = "vncserver -list | grep ^:[0-9]* | cut -c1-4" + cmd_result = str(utils.run(cmd)) + for line in cmd_result.split("\n"): + m = re.search('^:(\d)\s*$', line) + if m: + vncsp = m.group(1) + vncserverport = int(vncsp) + if vncserverport >= maxport: + maxport = vncserverport + assigned_ports.append(vncserverport) + for p in range(0,endport-startport): + if not p in assigned_ports: + port = p + if virt_utils.find_free_port(port,port+1): + break + else: + continue + port += startport + return port + def virsh_attach_device(name, xml_file, extra="", uri=""): """ @@ -1061,8 +1211,10 @@ class VM(virt_vm.BaseVM): vm.vnclisten = params.get("vnclisten") virt_install_cmd += add_vnclisten(help, vm.vnclisten) elif params.get("display") == "sdl": + self.displaytype = "sdl" virt_install_cmd += add_sdl(help) elif params.get("display") == "nographic": + self.displaytype = "nographic" virt_install_cmd += add_nographic(help) video_device = params.get("video_device") diff --git a/client/virt/virt_utils.py b/client/virt/virt_utils.py index 5ce4f5c..809b38b 100644 --- a/client/virt/virt_utils.py +++ b/client/virt/virt_utils.py @@ -3956,14 +3956,36 @@ def virt_test_assistant(test_name, test_dir, base_dir, default_userspace_paths, logging.info("%d - Verifying directories (check if the directory structure " "expected by the default test config is there)", step) sub_dir_list = ["images", "isos", "steps_data"] - for sub_dir in sub_dir_list: - sub_dir_path = os.path.join(base_dir, sub_dir) - if not os.path.isdir(sub_dir_path): - logging.debug("Creating %s", sub_dir_path) - os.makedirs(sub_dir_path) - else: - logging.debug("Dir %s exists, not creating" % - sub_dir_path) + + if test_name == 'libvirt': + base_fl = "%s/%s" % (test_dir, "base.cfg") + if not os.path.isfile(base_fl): + base_fl = "%s/%s" % (common_dir, "base.cfg.sample") + cmd = "cat %s | grep \"^main_vm\s=\s.*\" | cut -d \"=\" -f 2|sed 's/[^\w]//'" % base_fl + try: + vmdir = utils.run("%s" % cmd).stdout + except error.CmdError, detail: + logging.error("Failed to fetch 'main_vm' parameter from base.cfg :%s", detail) + sys.exit(1) + base_dir = "%s/%s" % (base_dir, vmdir.strip()) + for sub_dir in sub_dir_list: + sub_dir_path = os.path.join(base_dir, sub_dir) + if not os.path.isdir(sub_dir_path): + logging.debug("Creating %s", sub_dir_path) + os.makedirs(sub_dir_path) + else: + logging.debug("Dir %s exists, not creating" % + sub_dir_path) + else: + for sub_dir in sub_dir_list: + sub_dir_path = os.path.join(base_dir, sub_dir) + if not os.path.isdir(sub_dir_path): + logging.debug("Creating %s", sub_dir_path) + os.makedirs(sub_dir_path) + else: + logging.debug("Dir %s exists, not creating" % + sub_dir_path) + logging.info("") step += 1 logging.info("%d - Creating config files from samples (copy the default " diff --git a/client/virt/virt_vm.py b/client/virt/virt_vm.py index ba0cc40..dfea79e 100644 --- a/client/virt/virt_vm.py +++ b/client/virt/virt_vm.py @@ -1,8 +1,8 @@ -import logging, time, glob, re +import os, logging, time, glob, re, shutil, string from autotest.client.shared import error +from autotest.client import utils import virt_utils, virt_remote - class VMError(Exception): pass @@ -312,6 +312,56 @@ class VMUSBControllerPortFullError(VMUSBControllerError): def __str__(self): return ("No available USB Controller port left for VM %s." % self.name) +class VMDisplayError(VMError): + pass + +class UnsupportedDisplayError(VMDisplayError): + def __init__(self, name, display): + VMDisplayError.__init__(self, name, displaytype) + self.name = name + self.display = displaytype + + def __str__(self): + return ("%s display not supported for this VM '%s' on this host." % + (string.upper(self.display), self.name)) + +""" +Libvirt error handling starts below. +""" + +class LibvirtError(Exception): + pass + +class LibvirtFailedGettingInfoError(LibvirtError): + def __init__(self, name, connuri): + LibvirtError.__init__(self, name, connuri) + self.name = name + self.uri = connuri + + def __str__(self, name=None, uri =""): + if self.name: + return ("Libvirt failed to get information for VM '%s' at" + " connection URI '%s'" % (self.name, self.uri)) + else: + return ("Libvirt failed to get information for " + "connection '%s' : %s" % (self.uri)) + +class LibvirtVirshCmdError(LibvirtError): + def __init__(self, name, virsh_cmd, connuri, details=""): + LibvirtError.__init__(self, name, virsh_cmd, connuri, details) + self.virshcmd = virsh_cmd + self.name = name + self.uri = connuri + self.details = details + + def __str__(self): + if self.name : + return ("Error executing command '%s' for VM '%s' at" + " connection URI '%s' : " + "%s" % (self.virshcmd, self.name, self.uri, self.details)) + else: + return ("Error in executing commmand '%s' for connect URI" + " %s : %s" % (self.virshcmd, self.uri, self.details)) class CpuInfo(object): """ -- 1.7.10.4 _______________________________________________ Autotest-kernel mailing list [email protected] https://www.redhat.com/mailman/listinfo/autotest-kernel
