[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] [Xm-Test] XenManagedDomain and initial test case for vTPM management using xen-api



This patch provides XmTestManagedDomain and XenManagedDomain classes
similar to the XmTestDomain and XenDomain classes. I have wrapped the
xen-api for VM configuration creation, starting and stopping of VMs and
destruction of the VM configuration in the XenManagedDomain class's
methods. No device-related functions are provided through the class.

The managed domains' UUIDs are tracked and all created VMs are destroyed
upon failure or skipping of the test or by calling
xapi.vm_destroy_all().

I am adding a new grouptest 'xapi' for running xen-api tests.

Only caveat: I am using an empty username and password
(XmTestList/xapi.py) with Xend's authentication deactivated to run these
tests.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>

Index: root/xen-unstable.hg/tools/xm-test/grouptest/xapi
===================================================================
--- /dev/null
+++ root/xen-unstable.hg/tools/xm-test/grouptest/xapi
@@ -0,0 +1 @@
+vtpm 09_vtpm-xapi.test
Index: root/xen-unstable.hg/tools/xm-test/tests/vtpm/09_vtpm-xapi.py
===================================================================
--- /dev/null
+++ root/xen-unstable.hg/tools/xm-test/tests/vtpm/09_vtpm-xapi.py
@@ -0,0 +1,76 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@xxxxxxxxxx>
+
+# Test to test the vtpm class through the Xen-API
+
+from XmTestLib import xapi
+from XmTestLib.XenManagedDomain import XmTestManagedDomain
+from XmTestLib import *
+from vtpm_utils import *
+import commands
+import os
+
+def do_test():
+    domain = XmTestManagedDomain()
+    vm_uuid = domain.get_uuid()
+
+    vtpmcfg = {}
+    vtpmcfg['type'] = "paravirtualised"
+    vtpmcfg['backend'] = "Domain-0"
+    vtpmcfg['instance'] = 1
+    vtpmcfg['VM'] = vm_uuid
+
+    server, session = xapi._connect()
+
+    vtpm_uuid = xapi.execute(server.VTPM.create, session, vtpmcfg)
+
+    vtpm_id = xapi.execute(server.VTPM.get_instance, session, vtpm_uuid)
+    vtpm_be = xapi.execute(server.VTPM.get_backend , session, vtpm_uuid)
+    if vtpm_be != vtpmcfg['backend']:
+        FAIL("vTPM's backend is in '%s', expected: '%s'" %
+             (vtpm_be, vtpmcfg['backend']))
+
+    driver = xapi.execute(server.VTPM.get_driver, session, vtpm_uuid)
+    if driver != vtpmcfg['type']:
+        FAIL("vTPM has driver type '%s', expected: '%s'" %
+             (driver, vtpmcfg['type']))
+
+    vtpm_rec = xapi.execute(server.VTPM.get_record, session, vtpm_uuid)
+
+    if vtpm_rec['driver']  != vtpmcfg['type']:
+        FAIL("vTPM record shows driver type '%s', expected: '%s'" %
+             (vtpm_rec['driver'], vtpmcfg['type']))
+    if vtpm_rec['uuid']  != vtpm_uuid:
+        FAIL("vTPM record shows vtpm uuid '%s', expected: '%s'" %
+             (vtpm_rec['uuid'], vtpm_uuid))
+    if vtpm_rec['VM']  != vm_uuid:
+        FAIL("vTPM record shows VM uuid '%s', expected: '%s'" %
+             (vtpm_rec['VM'], vm_uuid))
+
+    success = domain.start()
+
+    console = domain.getConsole()
+
+    try:
+        run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
+    except ConsoleError, e:
+        saveLog(console.getHistory())
+        vtpm_cleanup(domName)
+        FAIL("No result from dumping the PCRs")
+
+    if re.search("No such file",run["output"]):
+        vtpm_cleanup(domName)
+        FAIL("TPM frontend support not compiled into (domU?) kernel")
+
+    domain.stop()
+    domain.destroy()
+
+
+
+try:
+    do_test()
+finally:
+    #Make sure all domains are gone that were created in this test case
+    xapi.vm_destroy_all()
Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/xapi.py
===================================================================
--- /dev/null
+++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/xapi.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (C) 2006 XenSource Ltd.
+# Copyright (C) 2006 IBM Corporation
+#============================================================================
+
+import os
+import sys
+from XmTestLib import *
+from xen.util.xmlrpclib2 import ServerProxy
+from types import DictType
+
+
+XAPI_DEFAULT_LOGIN = " "
+XAPI_DEFAULT_PASSWORD = " "
+
+class XenAPIError(Exception):
+    pass
+
+
+#A list of VMs' UUIDs that were created using vm_create
+_VMuuids = []
+
+#Terminate previously created managed(!) VMs and destroy their configs
+def vm_destroy_all():
+    server, session = _connect()
+    for uuid in _VMuuids:
+        execute(server.VM.hard_shutdown, session, uuid)
+        execute(server.VM.destroy      , session, uuid)
+
+
+def execute(fn, *args):
+    result = fn(*args)
+    if type(result) != DictType:
+        raise TypeError("Function returned object of type: %s" %
+                        str(type(result)))
+    if 'Value' not in result:
+        raise XenAPIError(*result['ErrorDescription'])
+    return result['Value']
+
+_initialised = False
+_server = None
+_session = None
+def _connect(*args):
+    global _server, _session, _initialised
+    if not _initialised:
+        _server = ServerProxy('httpu:///var/run/xend/xmlrpc.sock')
+        login = XAPI_DEFAULT_LOGIN
+        password = XAPI_DEFAULT_PASSWORD
+        creds = (login, password)
+        _session = execute(_server.session.login_with_password, *creds)
+        _initialised = True
+    return (_server, _session)
Index: root/xen-unstable.hg/tools/xm-test/tests/vtpm/Makefile.am
===================================================================
--- root.orig/xen-unstable.hg/tools/xm-test/tests/vtpm/Makefile.am
+++ root/xen-unstable.hg/tools/xm-test/tests/vtpm/Makefile.am
@@ -7,7 +7,8 @@ TESTS = 01_vtpm-list_pos.test \
         05_vtpm-loc_migr.test \
         06_vtpm-susp_res_pcrs.test \
         07_vtpm-mig_pcrs.test \
-        08_vtpm-mig_pcrs.test
+        08_vtpm-mig_pcrs.test \
+        09_vtpm-xapi.test
 
 XFAIL_TESTS =
 
Index: root/xen-unstable.hg/tools/python/scripts/xapi.py
===================================================================
--- root.orig/xen-unstable.hg/tools/python/scripts/xapi.py
+++ root/xen-unstable.hg/tools/python/scripts/xapi.py
@@ -412,17 +412,6 @@ def xapi_vtpm_create(*args):
     print "Creating vTPM with cfg = %s" % cfg
     vtpm_uuid = execute(server.VTPM.create, session, cfg)
     print "Done. (%s)" % vtpm_uuid
-    vtpm_id = execute(server.VTPM.get_instance, session, vtpm_uuid)
-    print "Has instance number '%s'" % vtpm_id
-    vtpm_be = execute(server.VTPM.get_backend, session, vtpm_uuid)
-    print "Has backend in '%s'" % vtpm_be
-    driver = execute(server.VTPM.get_driver, session, vtpm_uuid)
-    print "Has driver type '%s'" % driver
-    vtpm_rec = execute(server.VTPM.get_record, session, vtpm_uuid)
-    print "Has vtpm record '%s'" % vtpm_rec
-    vm = execute(server.VTPM.get_VM, session, vtpm_uuid)
-    print "Has VM '%s'" % vm
-
 
 #
 # Command Line Utils
Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/Test.py
===================================================================
--- root.orig/xen-unstable.hg/tools/xm-test/lib/XmTestLib/Test.py
+++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/Test.py
@@ -33,6 +33,7 @@ import select
 import signal
 import re
 import glob
+import xapi
 
 TEST_PASS = 0
 TEST_FAIL = 255
@@ -133,10 +134,12 @@ def becomeNonRoot():
 
 def FAIL(format, *args):
     print "\nREASON:", (format % args)
+    xapi.vm_destroy_all()
     sys.exit(TEST_FAIL)
 
 def SKIP(format, *args):
     print "\nREASON:", (format % args)
+    xapi.vm_destroy_all()
     sys.exit(TEST_SKIP)
 
 def saveLog(logText, filename=None):
Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenManagedDomain.py
===================================================================
--- /dev/null
+++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenManagedDomain.py
@@ -0,0 +1,176 @@
+#!/usr/bin/python
+"""
+ Copyright (C) International Business Machines Corp., 2005
+ Author: Stefan Berger <stefanb@xxxxxxxxxx>
+
+ Based on XenDomain.py by Dan Smith <danms@xxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; under version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+import os
+import sys
+from XmTestLib import *
+from xen.util.xmlrpclib2 import ServerProxy
+from types import DictType
+
+
+class XenManagedConfig:
+    """An object to help create a VM configuration usable via Xen-API"""
+    def __init__(self):
+        self.opts = {}
+        #Array to translate old option to new ones
+        self.opttrlate = { 'name' : 'name_label' ,
+                           'memory' : [ 'memory_static_max' ,
+                                        'memory_static_min' ,
+                                        'memory_dynamic_min',
+                                        'memory_dynamic_max' ],
+                           'kernel' : 'kernel_kernel',
+                           'ramdisk': 'kernel_initrd',
+                           'root'   : 'kernel_args'}
+
+    def setOpt(self, name, value):
+        """Set an option in the config"""
+        if name in self.opttrlate.keys():
+            _name = self.opttrlate[name]
+        else:
+            _name = name
+
+        if isinstance(_name, list):
+            for _n in _name:
+                self.opts[_n] = value
+        else:
+            self.opts[_name] = value
+
+    def getOpt(self, name):
+        """Return the value of a config option"""
+        if name in self.opts.keys():
+            return self.opts[name]
+        else:
+            return None
+
+    def setOpts(self, opts):
+        """Batch-set options from a dictionary"""
+        for k, v in opts.items():
+            self.setOpt(k, v)
+
+    def getOpts(self):
+        return self.opts
+
+
+class XenManagedDomain(XenDomain):
+
+    def __init__(self, name=None, config=None):
+        if name:
+            self.name = name
+        else:
+            self.name = getUniqueName()
+
+        self.config = config
+        self.console = None
+        self.netEnv = "bridge"
+
+        self.server, self.session = xapi._connect()
+        server = self.server
+        try:
+            self.vm_uuid = xapi.execute(server.VM.create, self.session,
+                                        self.config.getOpts())
+            xapi._VMuuids.append(self.vm_uuid)
+        except:
+            raise DomainError("Could not create VM config file for "
+                              "managed domain.")
+
+        #Only support PV for now.
+        self.type = "PV"
+
+    def start(self, noConsole=False):
+        #start the VM
+        server = self.server
+        if self.vm_uuid:
+            try:
+                xapi.execute(server.VM.start, self.session, self.vm_uuid)
+            except:
+                raise DomainError("Could not start domain")
+        else:
+            raise DomainError("VM has not UUID - VM config does not exist?")
+
+        if self.getDomainType() == "HVM":
+           waitForBoot()
+
+        if self.console and noConsole == True:
+            self.closeConsole()
+
+        elif self.console and noConsole == False:
+            return self.console
+
+        elif not self.console and noConsole == False:
+            return self.getConsole()
+
+    def stop(self):
+        if self.vm_uuid:
+            server = self.server
+            xapi.execute(server.VM.hard_shutdown, self.session, self.vm_uuid)
+        else:
+            raise DomainError("VM has not UUID - VM config does not exist?")
+
+    def destroy(self):
+        #Stop VM first.
+        self.stop()
+        if self.vm_uuid:
+            server = self.server
+            xapi.execute(server.VM.destroy, self.session, self.vm_uuid)
+            xapi._VMuuids.remove(self.vm_uuid)
+        else:
+            raise DomainError("VM has not UUID - VM config does not exist?")
+
+    def get_uuid(self):
+        return self.vm_uuid
+
+    def newDevice(self, Device, *args):
+        raise DomainError("No support for newDevice().")
+
+    def removeDevice(self, id):
+        raise DomainError("No support for removeDevice().")
+
+    def removeAllDevices(self, id):
+        raise DomainError("No support for removeAllDevices().")
+
+    def isRunning(self):
+        return isDomainRunning(self.name)
+
+    def getDevice(self, id):
+        raise DomainError("No support for getDevice().")
+
+
+class XmTestManagedDomain(XenManagedDomain):
+
+    """Create a new managed xm-test domain
+    @param name: The requested domain name
+    @param extraConfig: Additional configuration options
+    @param baseConfig: The initial configuration defaults to use
+    """
+    def __init__(self, name=None, extraConfig=None,
+                 baseConfig=arch.configDefaults):
+        config = XenManagedConfig()
+        config.setOpts(baseConfig)
+        if extraConfig:
+            config.setOpts(extraConfig)
+
+        if name:
+            config.setOpt("name_label", name)
+        elif not config.getOpt("name_label"):
+            config.setOpt("name_label", getUniqueName())
+
+        XenManagedDomain.__init__(self, config.getOpt("name_label"),
+                                  config=config)
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.