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

Reply via email to