Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/xapi.py =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/lib/XmTestLib/xapi.py +++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/xapi.py @@ -17,50 +17,49 @@ # Copyright (C) 2006 IBM Corporation #============================================================================ +import atexit import os import sys from XmTestLib import * -from xen.util.xmlrpclib2 import ServerProxy +from xen.xm import main as xmmain +from xen.xm import XenAPI +from xen.xm.opts import OptionError from types import DictType +import xml.dom.minidom - -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/xen-api.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) +def get_login_pwd(): + if xmmain.serverType == xmmain.SERVER_XEN_API: + try: + login, password = xmmain.parseAuthentication() + return (login, password) + except: + raise OptionError("Configuration for login/pwd not found. " + "Need to run xapi-setup.py?") + raise OptionError("Xm configuration file not using Xen-API for " + "communication with xend.") + +sessions=[] + +def connect(*args): + try: + creds = get_login_pwd() + except Exception, e: + FAIL("%s" % str(e)) + try: + session = XenAPI.Session(xmmain.serverURI) + except: + raise OptionError("Could not create XenAPI session with Xend." \ + "URI=%s" % xmmain.serverURI) + try: + session.login_with_password(*creds) + except: + raise OptionError("Could not login to Xend. URI=%s" % xmmain.serverURI) + def logout(): + try: + for s in sessions: + s.xenapi.session.logout() + except: + pass + sessions.append(session) + atexit.register(logout) + return session Index: root/xen-unstable.hg/tools/xm-test/tests/vtpm/09_vtpm-xapi.py =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/tests/vtpm/09_vtpm-xapi.py +++ root/xen-unstable.hg/tools/xm-test/tests/vtpm/09_vtpm-xapi.py @@ -6,71 +6,66 @@ # Test to test the vtpm class through the Xen-API from XmTestLib import xapi -from XmTestLib.XenManagedDomain import XmTestManagedDomain +from XmTestLib.XenAPIDomain import XmTestAPIDomain 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: + # XmTestAPIDomain tries to establish a connection to XenD + domain = XmTestAPIDomain() +except Exception, e: + SKIP("Skipping test. Error: %s" % str(e)) +vm_uuid = domain.get_uuid() + +vtpmcfg = {} +vtpmcfg['type'] = "paravirtualised" +vtpmcfg['backend'] = "Domain-0" +vtpmcfg['instance'] = 1 +vtpmcfg['VM'] = vm_uuid + +session = xapi.connect() + +vtpm_uuid = session.xenapi.VTPM.create(vtpmcfg) + +vtpm_id = session.xenapi.VTPM.get_instance(vtpm_uuid) +vtpm_be = session.xenapi.VTPM.get_backend(vtpm_uuid) +if vtpm_be != vtpmcfg['backend']: + FAIL("vTPM's backend is in '%s', expected: '%s'" % + (vtpm_be, vtpmcfg['backend'])) + +driver = session.xenapi.VTPM.get_driver(vtpm_uuid) +if driver != vtpmcfg['type']: + FAIL("vTPM has driver type '%s', expected: '%s'" % + (driver, vtpmcfg['type'])) + +vtpm_rec = session.xenapi.VTPM.get_record(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: - do_test() -finally: - #Make sure all domains are gone that were created in this test case - xapi.vm_destroy_all() + 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() Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenManagedDomain.py =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenManagedDomain.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/python -""" - Copyright (C) International Business Machines Corp., 2005 - Author: Stefan Berger - - Based on XenDomain.py by Dan Smith - - 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, startpaused=False): - #start the VM - server = self.server - if self.vm_uuid: - try: - xapi.execute(server.VM.start, self.session, self.vm_uuid, - startpaused) - 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) Index: root/xen-unstable.hg/tools/xm-test/configure.ac =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/configure.ac +++ root/xen-unstable.hg/tools/xm-test/configure.ac @@ -150,6 +150,7 @@ AC_CONFIG_FILES([ tests/vcpu-pin/Makefile tests/vcpu-disable/Makefile tests/vtpm/Makefile + tests/xapi/Makefile tests/enforce_dom0_cpus/Makefile lib/XmTestReport/xmtest.py lib/XmTestLib/config.py Index: root/xen-unstable.hg/tools/xm-test/grouptest/xapi =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/grouptest/xapi +++ root/xen-unstable.hg/tools/xm-test/grouptest/xapi @@ -1 +1,2 @@ +xapi vtpm 09_vtpm-xapi.test Index: root/xen-unstable.hg/tools/xm-test/tests/xapi/01_xapi-vm_basic.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/xapi/01_xapi-vm_basic.py @@ -0,0 +1,61 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger + +# Basic VM creation test + +from XmTestLib import xapi +from XmTestLib.XenAPIDomain import XmTestAPIDomain +from XmTestLib import * +from xen.xend import XendAPIConstants +import commands +import os + +try: + # XmTestAPIDomain tries to establish a connection to XenD + domain = XmTestAPIDomain() +except Exception, e: + SKIP("Skipping test. Error: %s" % str(e)) +vm_uuid = domain.get_uuid() + +session = xapi.connect() + +domain.start(startpaused=True) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]: + FAIL("VM was not started in 'paused' state") + +res = session.xenapi.VM.unpause(vm_uuid) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]: + FAIL("VM could not be put into 'running' state") + +console = domain.getConsole() + +try: + run = console.runCmd("cat /proc/interrupts") +except ConsoleError, e: + saveLog(console.getHistory()) + FAIL("Could not access proc-filesystem") + +res = session.xenapi.VM.pause(vm_uuid) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]: + FAIL("VM could not be put into 'paused' state") + +res = session.xenapi.VM.unpause(vm_uuid) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]: + FAIL("VM could not be 'unpaused'") + +domain.stop() +domain.destroy() Index: root/xen-unstable.hg/tools/xm-test/tests/xapi/Makefile.am =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/tests/xapi/Makefile.am @@ -0,0 +1,19 @@ +SUBDIRS = + +TESTS = 01_xapi-vm_basic.test + +XFAIL_TESTS = + +EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) xapi_utils.py +TESTS_ENVIRONMENT=@TENV@ + +%.test: %.py + cp $< $@ + chmod +x $@ + +clean-local: am_config_clean-local + +am_config_clean-local: + rm -f *test + rm -f *log + rm -f *~ Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenAPIDomain.py =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/XenAPIDomain.py @@ -0,0 +1,176 @@ +#!/usr/bin/python +""" + Copyright (C) International Business Machines Corp., 2005 + Author: Stefan Berger + + Based on XenDomain.py by Dan Smith + + 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 XenAPIConfig: + """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' : 'PV_kernel', + 'ramdisk': 'PV_ramdisk', + 'root' : 'PV_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 XenAPIDomain(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.session = xapi.connect() + session = self.session + try: + self.vm_uuid = session.xenapi.VM.create(self.config.getOpts()) + addXAPIDomain(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, startpaused=False): + #start the VM + session = self.session + if self.vm_uuid: + try: + session.xenapi.VM.start(self.vm_uuid, startpaused) + except: + raise DomainError("Could not start domain") + else: + raise DomainError("VM has no UUID - does VM config exist?") + + if startpaused: + return + + 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: + self.session.xenapi.VM.hard_shutdown(self.vm_uuid) + else: + raise DomainError("VM has no UUID - does VM config exist?") + + def destroy(self): + #Stop VM first. + self.stop() + if self.vm_uuid: + self.session.xenapi.VM.destroy(self.vm_uuid) + delXAPIDomain(self.vm_uuid) + else: + raise DomainError("VM has no UUID - does VM config 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 XmTestAPIDomain(XenAPIDomain): + + """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 = XenAPIConfig() + 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()) + + XenAPIDomain.__init__(self, config.getOpt("name_label"), + config=config) Index: root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/DomainTracking.py =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/lib/XmTestLib/DomainTracking.py +++ root/xen-unstable.hg/tools/xm-test/lib/XmTestLib/DomainTracking.py @@ -20,9 +20,11 @@ import atexit import Test +import xapi # Tracking of managed domains _managedDomains = [] +_VMuuids = [] registered = 0 def addManagedDomain(name): @@ -36,8 +38,24 @@ def delManagedDomain(name): if name in _managedDomains: del _managedDomains[_managedDomains.index(name)] +def addXAPIDomain(uuid): + global registered + _VMuuids.append(uuid) + if not registered: + atexit.register(destroyManagedDomains) + registered = 1 + +def delXAPIDomain(uuid): + _VMuuids.remove(uuid) + def destroyManagedDomains(): if len(_managedDomains) > 0: for m in _managedDomains: Test.traceCommand("xm destroy %s" % m) Test.traceCommand("xm delete %s" % m) + if len(_VMuuids) > 0: + for uuid in _VMuuids: + Test.traceCommand("xm destroy %s" % uuid) + Test.traceCommand("xm delete %s" % uuid) + + Index: root/xen-unstable.hg/tools/xm-test/README =================================================================== --- root.orig/xen-unstable.hg/tools/xm-test/README +++ root/xen-unstable.hg/tools/xm-test/README @@ -207,6 +207,49 @@ dedicated machine. As such, the library running DomUs on the system to provide each test with a "clean slate". +Testing the XML-RPC and Xen-API interfaces of xend +================================================== + +The xm-test suite can be used to test xm's interface with xend using +either XML-RPC or the Xen-API. In order to use either one of these modes, +xm needs to be configured using its configuration file +'/etc/xen/xm-config.xml'. +Note: The current default configuration after a fresh install of the xen +sources currently is to use the XML-RPC interface for communication with xend. + +Example content for the xm-config.xml for using the Xen-API looks as +follows: + + + + + +This configuration makes xm talk to xend using port 9363. For this to +work, also xend needs to be configured to listen to port 9363. Therefore +The following line must be in /etc/xen/xend-config.sxp. + +(xen-api-server (( 127.0.0.1:9363 none ))) + +To communicate via the legacy XML-RPC interface, the file +'/etc/xen/xm-config.xml' may simply have the following content or +may be complete remove from the /etc/xen directory. + + + + +A few tests have been written for the xm-test suite that test the +Xen-API interface directly without relying on 'xm'. These tests can be +found in the grouptest 'xapi' and for them to work properly, xm must have +been configured to use the Xen-API following the instructions above. To +run these test, the following command line can be invoked: + + # ./runtest.sh -g xapi + + + Extending =========