Onkar, Thanks! Taking a look now.
On 06/26/2012 01:11 PM, Onkar N Mahajan wrote: > Hello Chris, > 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 - > > From 5cff67ca3f004381ddcbe862ce20ae6894bb742e Mon Sep 17 00:00:00 2001 > From: Onkar N Mahajan<onkar.n.maha...@linux.vnet.ibm.com> > Date: Tue, 26 Jun 2012 22:31:11 +0530 > Subject: [PATCH] Libvirt-Autotest: Support for running multiple guest > (Improved) Signed-off-by: Onkar N Mahajan > <onkar.n.maha...@linux.vnet.ibm.com> > > --- > client/tests/libvirt/tests-shared.cfg.sample | 12 +- > client/virt/libvirt_vm.py | 159 > +++++++++++++++++++++++++- > client/virt/virt_utils.py | 38 +++++-- > client/virt/virt_vm.py | 54 +++++++++- > 4 files changed, 246 insertions(+), 17 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 d97ac0c..df9fd9b 100644 > --- a/client/virt/libvirt_vm.py > +++ b/client/virt/libvirt_vm.py > @@ -461,6 +461,156 @@ def virsh_detach_device(name, xml_file, extra="", > uri=""): > logging.error("Detaching device from VM %s failed." % name) > return False > > +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 > + > > class VM(virt_vm.BaseVM): > """ > @@ -485,6 +635,7 @@ class VM(virt_vm.BaseVM): > self.process = None > self.serial_console = None > self.redirs = {} > + self.displaytype= None > self.vnc_port = 5900 > self.vnclisten = "0.0.0.0" > self.pci_assignable = None > @@ -934,6 +1085,7 @@ class VM(virt_vm.BaseVM): > virt_install_cmd += add_location(help, location) > > if params.get("display") == "vnc": > + self.displaytype = "vnc" > if params.get("vnc_port"): > vm.vnc_port = int(params.get("vnc_port")) > virt_install_cmd += add_vnc(help, vm.vnc_port) > @@ -941,8 +1093,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") > @@ -1188,7 +1342,10 @@ class VM(virt_vm.BaseVM): > > # Find available VNC port, if needed > if params.get("display") == "vnc": > - self.vnc_port = virt_utils.find_free_port(5900, 6100) > + self.displaytype = "vnc" > + port = get_free_port(self.name, self.connect_uri, > self.displaytype, > + 5900, 6100) > + self.vnc_port = port > > # Find available spice port, if needed > if params.get("spice"): > diff --git a/client/virt/virt_utils.py b/client/virt/virt_utils.py > index 1c4d90d..5079cbb 100644 > --- a/client/virt/virt_utils.py > +++ b/client/virt/virt_utils.py > @@ -3889,14 +3889,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 534f8e3..201992d 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 BaseVM(object): > """ -- Chris Evich, RHCA, RHCE, RHCDS, RHCSS Quality Assurance Engineer e-mail: cevich + `@' + redhat.com o: 1-888-RED-HAT1 x44214 _______________________________________________ Autotest mailing list Autotest@test.kernel.org http://test.kernel.org/cgi-bin/mailman/listinfo/autotest