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

Reply via email to