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

[Xen-changelog] Split the configuration file parsing and xc dominfo parsing aspects of



# HG changeset patch
# User emellor@ewan
# Node ID 9647be59212dbac04b4bade91195c161a967a9d1
# Parent  19572dec7d3c281a426fbb6fbe693a76ea260bf6
Split the configuration file parsing and xc dominfo parsing aspects of
XendDomainInfo out from the rest of the code, creating an intermediate
dictionary of common format.  This means that the rest of XendDomainInfo can
work whether creating a domain for the first time, or whether xend is
restarted but the domains still exist.  This means that xend is now robust in
the face of restarts.  The phase of validation of configuration details is
now more explicit, and stronger too.

Change the handling of memory sizes in XendDomainInfo's interface to use KiB
in setMemoryTarget and getMemoryTarget.  This gives reasonable granularity
whilst ensuring that we can handle values up to 2TiB without overflowing a
signed 32 bit value.  It is not clear that the xend code, especially the C /
Python interface, is either 64-bit clean or unsigned 32-bit clean, so this is
the safest choice for now.  The behaviour of Python's shift operator will
change in Python 2.4, so it is best to address this problem once we have moved
to that version.

Determine the backend flags on-the-fly, in getBackendFlags, rather than
computing them in advance in configureBackends and storing the value.  Change
addControllerClass so that backend flag information is in this table too,
rather than hard-coded elsewhere.

Improve the error reporting for name clashes.

Remove XendDomainInfo's dependence upon DBMap, and use xstransact directly
instead.  This changes the interface from XendDomain to XendDomainInfo, as
paths rather than DBMaps are passed in.

Remove the XendDomainInfo.recreate and restore flags.  Since the device and
domain handling is now stateless inside xend, much less work is necessary for
recreate and restore procedures, so we can do without these flags.

Remove XendDomainInfo's unused dependency upon SrvDaemon, and its unnecessary
dependence upon PrettyPrint.  Remove the unused show method.

Decouple image.py from XendDomainInfo.bootloader by passing a bootloading flag
into initDomain instead.  Decouple it from XendDomainInfo.config by passing
the semiparsed device configuration into create().  Move configuration in
VmxImageHandler so that rather than being scattered around the class it is in
or called from the configure method.  Device configuration is no longer
available anywhere else.

>From Dan Smith <danms@xxxxxxxxxx>:

      I could not find in the existing code the point at which
      a domain was added to the XendDomain list after restore.  Several
      attempts to restore would result in positive log messages, but the
      restored domain would not show up in "xm list".  This patch includes a
      call to _add_domain(), which results in restore working for me.

Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx>

diff -r 19572dec7d3c -r 9647be59212d tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Wed Sep 21 14:13:26 2005
+++ b/tools/python/xen/xend/XendDomain.py       Wed Sep 21 14:23:26 2005
@@ -14,17 +14,14 @@
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
 """Handler for domain operations.
  Nothing here is persistent (across reboots).
  Needs to be persistent for one uptime.
 """
-import errno
 import os
-import sys
-import time
-import traceback
 
 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
 
@@ -155,10 +152,8 @@
                 continue
             log.info("recreating domain %d, uuid %s" % (domid, uuid))
             dompath = "/".join(dompath.split("/")[0:-1])
-            db = self.dbmap.addChild("%s/xend" % uuid)
             try:
-                dominfo = XendDomainInfo.recreate(uuid, dompath, domid, db,
-                                                  dom)
+                dominfo = XendDomainInfo.recreate(uuid, dompath, domid, dom)
             except Exception, ex:
                 log.exception("Error recreating domain info: id=%d", domid)
                 continue
@@ -275,7 +270,7 @@
         @param config: configuration
         @return: domain
         """
-        dominfo = XendDomainInfo.create(self.dbmap, config)
+        dominfo = XendDomainInfo.create(self.dbmap.getPath(), config)
         self._add_domain(dominfo)
         return dominfo
 
@@ -310,8 +305,7 @@
         @param vmconfig: vm configuration
         """
         config = sxp.child_value(vmconfig, 'config')
-        dominfo = XendDomainInfo.restore(self.dbmap, config)
-        return dominfo
+        return XendDomainInfo.restore(self.dbmap.getPath(), config)
 
     def domain_restore(self, src, progress=False):
         """Restore a domain from file.
@@ -353,15 +347,15 @@
             dompath = self.domroot
         log.info("Creating entry for unknown xend domain: id=%d uuid=%s",
                  dom0, uuid)
-        db = self.dbmap.addChild("%s/xend" % uuid)
-        try:
-            dominfo = XendDomainInfo.recreate(uuid, dompath, dom0,
-                                              db, info)
-        except:
-            raise XendError("Error recreating xend domain info: id=%d" %
-                            dom0)
-        self._add_domain(dominfo)
-        return dominfo
+        try:
+            dominfo = XendDomainInfo.recreate(uuid, dompath, dom0, info)
+            self._add_domain(dominfo)
+            return dominfo
+        except Exception, exn:
+            log.exception(exn)
+            raise XendError("Error recreating xend domain info: id=%d: %s" %
+                            (dom0, str(exn)))
+
         
     def domain_lookup(self, id):
         return self.domains.get(id)
@@ -729,7 +723,7 @@
         @return: 0 on success, -1 on error
         """
         dominfo = self.domain_lookup(id)
-        return dominfo.setMemoryTarget(mem * (1 << 20))
+        return dominfo.setMemoryTarget(mem << 10)
 
     def domain_vcpu_hotplug(self, id, vcpu, state):
         """Enable or disable VCPU vcpu in DOM id
diff -r 19572dec7d3c -r 9647be59212d tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Wed Sep 21 14:13:26 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Wed Sep 21 14:23:26 2005
@@ -13,6 +13,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
 """Representation of a single domain.
@@ -31,18 +32,15 @@
 import xen.lowlevel.xc
 from xen.util.blkif import blkdev_uname_to_file
 
-from xen.xend.server import SrvDaemon
 from xen.xend.server.channel import EventChannel
 
 from xen.xend import sxp
-from xen.xend.PrettyPrint import prettyprintstring
 from xen.xend.XendBootloader import bootloader
 from xen.xend.XendLogging import log
 from xen.xend.XendError import XendError, VmError
 from xen.xend.XendRoot import get_component
 
 from xen.xend.uuid import getUuid
-from xen.xend.xenstore import DBVar
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.xenstore.xsutil import IntroduceDomain
 
@@ -94,9 +92,6 @@
 
 
 xc = xen.lowlevel.xc.new()
-
-
-xend = SrvDaemon.instance()
 
 
 def domain_exists(name):
@@ -136,142 +131,282 @@
     """
     MINIMUM_RESTART_TIME = 20
 
-    def create(cls, parentdb, config):
+
+    def create(cls, dompath, config):
         """Create a VM from a configuration.
 
-        @param parentdb:  parent db
+        @param dompath:   The path to all domain information
         @param config    configuration
         @raise: VmError for invalid configuration
         """
-        uuid = getUuid()
-        db = parentdb.addChild("%s/xend" % uuid)
-        path = parentdb.getPath()
-        vm = cls(uuid, path, db)
-        vm.construct(config)
-        vm.saveToDB(sync=True)
-
+
+        log.debug("XendDomainInfo.create(%s, ...)", dompath)
+        
+        vm = cls(getUuid(), dompath, cls.parseConfig(config))
+        vm.construct()
         return vm
 
     create = classmethod(create)
 
-    def recreate(cls, uuid, path, domid, db, info):
+
+    def recreate(cls, uuid, dompath, domid, info):
         """Create the VM object for an existing domain.
 
-        @param db:        domain db
+        @param dompath:   The path to all domain information
         @param info:      domain info from xc
         """
-        vm = cls(uuid, path, db)
-        vm.setDomid(domid)
-        vm.name, vm.start_time = vm.gatherVm(("name", str),
-                                             ("start-time", float))
-        try:
-            db.readDB()
-        except: pass
-        vm.importFromDB()
-        config = vm.config
-        log.debug('info=' + str(info))
-        log.debug('config=' + prettyprintstring(config))
-
-        vm.memory = info['mem_kb'] / 1024
-        vm.target = info['mem_kb'] * 1024
-
-        if config:
-            try:
-                vm.recreate = True
-                vm.construct(config)
-            finally:
-                vm.recreate = False
-        else:
-            vm.setName("Domain-%d" % domid)
-
-        vm.exportToDB(save=True)
-        return vm
+
+        log.debug("XendDomainInfo.recreate(%s, %s, %s, %s)", uuid, dompath,
+                  domid, info)
+
+        return cls(uuid, dompath, info, domid, True)
 
     recreate = classmethod(recreate)
 
-    def restore(cls, parentdb, config, uuid=None):
+
+    def restore(cls, dompath, config, uuid = None):
         """Create a domain and a VM object to do a restore.
 
-        @param parentdb:  parent db
+        @param dompath:   The path to all domain information
         @param config:    domain configuration
         @param uuid:      uuid to use
         """
+        
+        log.debug("XendDomainInfo.restore(%s, ..., %s)", dompath, uuid)
+
         if not uuid:
             uuid = getUuid()
-        db = parentdb.addChild("%s/xend" % uuid)
-        path = parentdb.getPath()
-        vm = cls(uuid, path, db)
-        ssidref = int(sxp.child_value(config, 'ssidref'))
-        log.debug('restoring with ssidref='+str(ssidref))
-        id = xc.domain_create(ssidref = ssidref)
-        vm.setDomid(id)
+
+        try:
+            ssidref = int(sxp.child_value(config, 'ssidref'))
+        except TypeError, exn:
+            raise VmError('Invalid ssidref in config: %s' % exn)
+
+        log.debug('restoring with ssidref = %d' % ssidref)
+
+        vm = cls(uuid, dompath, cls.parseConfig(config),
+                 xc.domain_create(ssidref = ssidref))
         vm.clear_shutdown()
+        return vm
+
+    restore = classmethod(restore)
+
+
+    def parseConfig(cls, config):
+        def get_cfg(name, conv = None):
+            val = sxp.child_value(config, name)
+
+            if conv and not val is None:
+                try:
+                    return conv(val)
+                except TypeError, exn:
+                    raise VmError(
+                        'Invalid setting %s = %s in configuration: %s' %
+                        (name, val, str(exn)))
+            else:
+                return val
+
+
+        log.debug("parseConfig: config is %s" % str(config))
+
+        result = {}
+        imagecfg = "()"
+
+        result['name']         = get_cfg('name')
+        result['ssidref']      = get_cfg('ssidref',    int)
+        result['memory']       = get_cfg('memory',     int)
+        result['mem_kb']       = get_cfg('mem_kb',     int)
+        result['maxmem']       = get_cfg('maxmem',     int)
+        result['maxmem_kb']    = get_cfg('maxmem_kb',  int)
+        result['cpu']          = get_cfg('cpu',        int)
+        result['cpu_weight']   = get_cfg('cpu_weight', float)
+        result['bootloader']   = get_cfg('bootloader')
+        result['restart_mode'] = get_cfg('restart')
+
         try:
-            vm.restore = True
-            vm.construct(config)
-        finally:
-            vm.restore = False
-        vm.exportToDB(save=True, sync=True)
-        return vm
-
-    restore = classmethod(restore)
-
-    __exports__ = [
-        DBVar('config',        ty='sxpr'),
-        DBVar('state',         ty='str'),
-        DBVar('restart_mode',  ty='str'),
-        DBVar('restart_state', ty='str'),
-        DBVar('restart_time',  ty='float'),
-        DBVar('restart_count', ty='int'),
-        ]
+            imagecfg = get_cfg('image')
+
+            if imagecfg:
+                result['image'] = imagecfg
+                result['vcpus'] = int(sxp.child_value(imagecfg, 'vcpus',
+                                                      1))
+            else:
+                result['vcpus'] = 1
+        except TypeError, exn:
+            raise VmError(
+                'Invalid configuration setting: vcpus = %s: %s' %
+                (sxp.child_value(imagecfg, 'vcpus', 1),
+                 str(exn)))
+
+        result['backend'] = []
+        for c in sxp.children(config, 'backend'):
+            result['backend'].append(sxp.name(sxp.child0(c)))
+
+        result['device'] = []
+        for d in sxp.children(config, 'device'):
+            c = sxp.child0(d)
+            result['device'].append((sxp.name(c), c))
+
+        log.debug("parseConfig: result is %s" % str(result))
+        return result
+
+
+    parseConfig = classmethod(parseConfig)
+
     
-    def __init__(self, uuid, path, db):
+    def __init__(self, uuid, parentpath, info, domid = None, augment = False):
+
         self.uuid = uuid
-        self.path = path + "/" + uuid
-
-        self.db = db
-
-        self.recreate = 0
-        self.restore = 0
-        
-        self.config = None
-        self.domid = None
-        self.cpu_weight = 1
-        self.start_time = None
-        self.name = None
-        self.memory = None
-        self.ssidref = None
+        self.info = info
+
+        self.path = parentpath + "/" + uuid
+
+        if domid:
+            self.domid = domid
+        elif 'dom' in info:
+            self.domid = int(info['dom'])
+        else:
+            self.domid = None
+
+        if augment:
+            self.augmentInfo()
+
+        self.validateInfo()
+
         self.image = None
-
-        self.target = None
 
         self.store_channel = None
         self.store_mfn = None
         self.console_channel = None
         self.console_mfn = None
         
-        self.info = None
-        self.backend_flags = 0
-        
         #todo: state: running, suspended
         self.state = STATE_VM_OK
         self.state_updated = threading.Condition()
         self.shutdown_pending = None
 
-        #todo: set to migrate info if migrating
-        self.migrate = None
-        
-        self.restart_mode = RESTART_ONREBOOT
         self.restart_state = None
         self.restart_time = None
         self.restart_count = 0
         
-        self.vcpus = 1
-        self.bootloader = None
-
         self.writeVm("uuid", self.uuid)
         self.storeDom("vm", self.path)
 
+
+    def augmentInfo(self):
+        def useIfNeeded(name, val):
+            if not self.infoIsSet(name) and val is not None:
+                self.info[name] = val
+
+        params = (("name", str),
+                  ("start-time", float))
+
+        from_store = self.gatherVm(*params)
+
+        map(lambda x, y: useIfNeeded(x[0], y), params, from_store)
+
+
+    def validateInfo(self):
+        """Validate and normalise the info block.  This has either been parsed
+        by parseConfig, or received from xc through recreate.
+        """
+        def defaultInfo(name, val):
+            if not self.infoIsSet(name):
+                self.info[name] = val()
+
+        try:
+            defaultInfo('name',         lambda: "Domain-%d" % self.domid)
+            defaultInfo('restart_mode', lambda: RESTART_ONREBOOT)
+            defaultInfo('cpu_weight',   lambda: 1.0)
+            defaultInfo('bootloader',   lambda: None)
+            defaultInfo('backend',      lambda: [])
+            defaultInfo('device',       lambda: [])
+
+            self.check_name(self.info['name'])
+
+            # Internally, we keep only maxmem_KiB, and not maxmem or maxmem_kb
+            # (which come from outside, and are in MiB and KiB respectively).
+            # This means that any maxmem or maxmem_kb settings here have come
+            # from outside, and maxmem_KiB must be updated to reflect them.
+            # If we have both maxmem and maxmem_kb and these are not
+            # consistent, then this is an error, as we've no way to tell which
+            # one takes precedence.
+
+            # Exactly the same thing applies to memory_KiB, memory, and
+            # mem_kb.
+
+            def discard_negatives(name):
+                if self.infoIsSet(name) and self.info[name] <= 0:
+                    del self.info[name]
+
+            def valid_KiB_(mb_name, kb_name):
+                discard_negatives(kb_name)
+                discard_negatives(mb_name)
+                
+                if self.infoIsSet(kb_name):
+                    if self.infoIsSet(mb_name):
+                        mb = self.info[mb_name]
+                        kb = self.info[kb_name]
+                        if mb * 1024 == kb:
+                            return kb
+                        else:
+                            raise VmError(
+                                'Inconsistent %s / %s settings: %s / %s' %
+                                (mb_name, kb_name, mb, kb))
+                    else:
+                        return self.info[kb_name]
+                elif self.infoIsSet(mb_name):
+                    return self.info[mb_name] * 1024
+                else:
+                    return None
+
+            def valid_KiB(mb_name, kb_name):
+                result = valid_KiB_(mb_name, kb_name)
+                if result <= 0:
+                    raise VmError('Invalid %s / %s: %s' %
+                                  (mb_name, kb_name, result))
+                else:
+                    return result
+
+            def delIf(name):
+                if name in self.info:
+                    del self.info[name]
+
+            self.info['memory_KiB'] = valid_KiB('memory', 'mem_kb')
+            delIf('memory')
+            delIf('mem_kb')
+            self.info['maxmem_KiB'] = valid_KiB_('maxmem', 'maxmem_kb')
+            delIf('maxmem')
+            delIf('maxmem_kb')
+
+            if not self.info['maxmem_KiB']:
+                self.info['maxmem_KiB'] = 1 << 30
+
+            # Validate the given backend names.
+            for s in self.info['backend']:
+                if s not in backendFlags:
+                    raise VmError('Invalid backend type: %s' % s)
+
+            for (n, c) in self.info['device']:
+                if not n or not c or n not in controllerClasses:
+                    raise VmError('invalid device (%s, %s)' %
+                                  (str(n), str(c)))
+
+            if self.info['restart_mode'] not in restart_modes:
+                raise VmError('invalid restart mode: ' +
+                              str(self.info['restart_mode']))
+
+            if 'cpumap' not in self.info:
+                if [self.info['vcpus'] == 1]:
+                    self.info['cpumap'] = [1];
+                else:
+                    raise VmError('Cannot create CPU map')
+
+        except KeyError, exn:
+            log.exception(exn)
+            raise VmError('Unspecified domain detail: %s' % str(exn))
+
+
     def readVm(self, *args):
         return xstransact.Read(self.path, *args)
 
@@ -302,18 +437,28 @@
     def storeDom(self, *args):
         return xstransact.Store(self.path, *args)
 
-    def setDB(self, db):
-        self.db = db
-
-    def saveToDB(self, save=False, sync=False):
-        self.db.saveDB(save=save, sync=sync)
-
-    def exportToDB(self, save=False, sync=False):
-        self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
-
-    def importFromDB(self):
-        self.db.importFromDB(self, fields=self.__exports__)
-        self.store_channel = self.eventChannel("store/port")
+
+    def exportToDB(self, save=False):
+        to_store = {
+            'domid':              str(self.domid),
+            'uuid':               self.uuid,
+
+            'restart_time':       str(self.restart_time),
+
+            'xend/state':         self.state,
+            'xend/restart_count': str(self.restart_count),
+            'xend/restart_mode':  str(self.info['restart_mode']),
+
+            'memory/target':      str(self.info['memory_KiB'])
+            }
+
+        for (k, v) in self.info.items():
+            to_store[k] = str(v)
+
+        log.debug("Storing %s" % str(to_store))
+
+        self.writeVm(to_store)
+
 
     def setDomid(self, domid):
         """Set the domain id.
@@ -327,11 +472,12 @@
         return self.domid
 
     def setName(self, name):
-        self.name = name
+        self.check_name(name)
+        self.info['name'] = name
         self.storeVm("name", name)
 
     def getName(self):
-        return self.name
+        return self.info['name']
 
     def getPath(self):
         return self.path
@@ -340,14 +486,14 @@
         return self.uuid
 
     def getVCpuCount(self):
-        return self.vcpus
+        return self.info['vcpus']
 
     def getSsidref(self):
-        return self.ssidref
+        return self.info['ssidref']
 
     def getMemoryTarget(self):
-        """Get this domain's target memory size, in MiB."""
-        return self.memory
+        """Get this domain's target memory size, in KiB."""
+        return self.info['memory_KiB']
 
     def setStoreRef(self, ref):
         self.store_mfn = ref
@@ -355,7 +501,8 @@
 
 
     def getBackendFlags(self):
-        return self.backend_flags
+        return reduce(lambda x, y: x | backendFlags[y],
+                      self.info['backend'], 0)
 
 
     def closeStoreChannel(self):
@@ -376,21 +523,32 @@
         self.console_mfn = ref
         self.storeDom("console/ring-ref", ref)
 
+
     def setMemoryTarget(self, target):
+        """Set the memory target of this domain.
+        @param target In KiB.
+        """
+        self.info['memory_KiB'] = target
         self.storeDom("memory/target", target)
 
-    def update(self, info=None):
-        """Update with  info from xc.domain_getinfo().
-        """
-        if info:
-            self.info = info
-        else:
-            di = dom_get(self.domid)
-            if not di:
+
+    def update(self, info = None):
+        """Update with info from xc.domain_getinfo().
+        """
+
+        log.debug("XendDomainInfo.update(%s) on domain %d", info, self.domid)
+
+        if not info:
+            info = dom_get(self.domid)
+            if not info:
                 return
-            self.info = di 
-        self.memory = self.info['mem_kb'] / 1024
-        self.ssidref = self.info['ssidref']
+            
+        self.info.update(info)
+        self.validateInfo()
+
+        log.debug("XendDomainInfo.update done on domain %d: %s", self.domid,
+                  self.info)
+
 
     def state_set(self, state):
         self.state_updated.acquire()
@@ -398,7 +556,7 @@
             self.state = state
             self.state_updated.notifyAll()
         self.state_updated.release()
-        self.saveToDB()
+        self.exportToDB()
 
     def state_wait(self, state):
         self.state_updated.acquire()
@@ -409,9 +567,9 @@
     def __str__(self):
         s = "<domain"
         s += " id=" + str(self.domid)
-        s += " name=" + self.name
-        s += " memory=" + str(self.memory)
-        s += " ssidref=" + str(self.ssidref)
+        s += " name=" + self.info['name']
+        s += " memory=" + str(self.info['memory_KiB'] / 1024)
+        s += " ssidref=" + str(self.info['ssidref'])
         s += ">"
         return s
 
@@ -441,37 +599,47 @@
     def sxpr(self):
         sxpr = ['domain',
                 ['domid', self.domid],
-                ['name', self.name],
-                ['memory', self.memory],
-                ['ssidref', self.ssidref],
-                ['target', self.target] ]
+                ['name', self.info['name']],
+                ['memory', self.info['memory_KiB'] / 1024],
+                ['ssidref', self.info['ssidref']]]
         if self.uuid:
             sxpr.append(['uuid', self.uuid])
         if self.info:
-            sxpr.append(['maxmem', self.info['maxmem_kb']/1024 ])
-            run   = (self.info['running']  and 'r') or '-'
-            block = (self.info['blocked']  and 'b') or '-'
-            pause = (self.info['paused']   and 'p') or '-'
-            shut  = (self.info['shutdown'] and 's') or '-'
-            crash = (self.info['crashed']  and 'c') or '-'
-            state = run + block + pause + shut + crash
+            sxpr.append(['maxmem', self.info['maxmem_KiB'] / 1024])
+
+            def stateChar(name):
+                if name in self.info:
+                    if self.info[name]:
+                        return name[0]
+                    else:
+                        return '-'
+                else:
+                    return '?'
+
+            state = reduce(
+                lambda x, y: x + y,
+                map(stateChar,
+                    ['running', 'blocked', 'paused', 'shutdown', 'crashed']))
+
             sxpr.append(['state', state])
-            if self.info['shutdown']:
+            if self.infoIsSet('shutdown'):
                 reason = shutdown_reason(self.info['shutdown_reason'])
                 sxpr.append(['shutdown_reason', reason])
-            sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]])
-            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])    
+            if self.infoIsSet('cpu_time'):
+                sxpr.append(['cpu_time', self.info['cpu_time']/1e9])    
             sxpr.append(['vcpus', self.info['vcpus']])
             sxpr.append(['cpumap', self.info['cpumap']])
-            # build a string, using '|' to seperate items, show only up
-            # to number of vcpus in domain, and trim the trailing '|'
-            sxpr.append(['vcpu_to_cpu', ''.join(map(lambda x: str(x)+'|',
-                        self.info['vcpu_to_cpu'][0:self.info['vcpus']]))[:-1]])
+            if self.infoIsSet('vcpu_to_cpu'):
+                sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]])
+                # build a string, using '|' to separate items, show only up
+                # to number of vcpus in domain, and trim the trailing '|'
+                sxpr.append(['vcpu_to_cpu', ''.join(map(lambda x: str(x)+'|',
+                            
self.info['vcpu_to_cpu'][0:self.info['vcpus']]))[:-1]])
             
-        if self.start_time:
-            up_time =  time.time() - self.start_time  
+        if self.infoIsSet('start_time'):
+            up_time =  time.time() - self.info['start_time']
             sxpr.append(['up_time', str(up_time) ])
-            sxpr.append(['start_time', str(self.start_time) ])
+            sxpr.append(['start_time', str(self.info['start_time']) ])
 
         if self.store_channel:
             sxpr.append(self.store_channel.sxpr())
@@ -481,19 +649,12 @@
             sxpr.append(['console_channel', self.console_channel.sxpr()])
         if self.console_mfn:
             sxpr.append(['console_mfn', self.console_mfn])
-# already in (devices)
-#        console = self.getConsole()
-#        if console:
-#            sxpr.append(console.sxpr())
-
         if self.restart_count:
             sxpr.append(['restart_count', self.restart_count])
         if self.restart_state:
             sxpr.append(['restart_state', self.restart_state])
         if self.restart_time:
             sxpr.append(['restart_time', str(self.restart_time)])
-        if self.config:
-            sxpr.append(['config', self.config])
         return sxpr
 
     def check_name(self, name):
@@ -502,9 +663,8 @@
         The same name cannot be used for more than one vm at the same time.
 
         @param name: name
-        @raise: VMerror if invalid
-        """
-        if self.recreate: return
+        @raise: VmError if invalid
+        """
         if name is None or name == '':
             raise VmError('missing vm name')
         for c in name:
@@ -520,28 +680,50 @@
             return
         if dominfo.is_terminated():
             return
-        if not self.domid or (dominfo.domid != self.domid):
-            raise VmError('vm name clash: ' + name)
-        
-    def construct(self, config):
+        if self.domid is None:
+            raise VmError("VM name '%s' already in use by domain %d" %
+                          (name, dominfo.domid))
+        if dominfo.domid != self.domid:
+            raise VmError("VM name '%s' is used in both domains %d and %d" %
+                          (name, self.domid, dominfo.domid))
+
+
+    def construct(self):
         """Construct the vm instance from its configuration.
 
         @param config: configuration
         @raise: VmError on error
         """
         # todo - add support for scheduling params?
-        self.config = config
         try:
             # Initial domain create.
-            self.setName(sxp.child_value(config, 'name'))
-            self.check_name(self.name)
-            self.init_image()
-            self.configure_cpus(config)
-            self.init_domain()
+            if 'image' not in self.info:
+                raise VmError('Missing image in configuration')
+
+            self.image = ImageHandler.create(self, self.info['image'],
+                                             self.info['device'])
+
+            log.debug('XendDomainInfo.construct: '
+                      'calling initDomain(%s %s %s %s %s)',
+                      str(self.domid),
+                      str(self.info['memory_KiB']),
+                      str(self.info['ssidref']),
+                      str(self.info['cpu']),
+                      str(self.info['cpu_weight']))
+
+            self.setDomid(self.image.initDomain(self.domid,
+                                                self.info['memory_KiB'],
+                                                self.info['ssidref'],
+                                                self.info['cpu'],
+                                                self.info['cpu_weight'],
+                                                self.info['bootloader']))
+            
+            self.info['start_time'] = time.time()
+
+            log.debug('init_domain> Created domain=%d name=%s memory=%d',
+                      self.domid, self.info['name'], self.info['memory_KiB'])
 
             # Create domain devices.
-            self.configure_backends()
-            self.configure_restart()
             self.construct_image()
             self.configure()
             self.exportToDB(save=True)
@@ -553,40 +735,11 @@
             self.destroy()
             raise
 
-    def configure_cpus(self, config):
-        try:
-            self.cpu_weight = float(sxp.child_value(config, 'cpu_weight', '1'))
-        except:
-            raise VmError('invalid cpu weight')
-        self.memory = int(sxp.child_value(config, 'memory'))
-        if self.memory is None:
-            raise VmError('missing memory size')
-        self.setMemoryTarget(self.memory * (1 << 20))
-        self.ssidref = int(sxp.child_value(config, 'ssidref'))
-        cpu = sxp.child_value(config, 'cpu')
-        if self.recreate and self.domid and cpu is not None and int(cpu) >= 0:
-            xc.domain_pincpu(self.domid, 0, 1<<int(cpu))
-        try:
-            image = sxp.child_value(self.config, 'image')
-            vcpus = sxp.child_value(image, 'vcpus')
-            if vcpus:
-                self.vcpus = int(vcpus)
-        except:
-            raise VmError('invalid vcpus value')
-
     def configure_vcpus(self, vcpus):
         d = {}
         for v in range(0, vcpus):
             d["cpu/%d/availability" % v] = "online"
         self.writeVm(d)
-
-    def init_image(self):
-        """Create boot image handler for the domain.
-        """
-        image = sxp.child_value(self.config, 'image')
-        if image is None:
-            raise VmError('missing image')
-        self.image = ImageHandler.create(self, image)
 
     def construct_image(self):
         """Construct the boot image for the domain.
@@ -598,21 +751,17 @@
             IntroduceDomain(self.domid, self.store_mfn,
                             self.store_channel.port1, self.path)
         # get the configured value of vcpus and update store
-        self.configure_vcpus(self.vcpus)
+        self.configure_vcpus(self.info['vcpus'])
+
 
     def delete(self):
         """Delete the vm's db.
         """
-        self.domid = None
-        self.saveToDB(sync=True)
         try:
-            # Todo: eventually will have to wait for devices to signal
-            # destruction before can delete the db.
-            if self.db:
-                self.db.delete()
+            xstransact.Remove(self.path, 'domid')
         except Exception, ex:
             log.warning("error in domain db delete: %s", ex)
-            pass
+
 
     def destroy_domain(self):
         """Destroy the vm's domain.
@@ -624,7 +773,7 @@
         try:
             xc.domain_destroy(dom=self.domid)
         except Exception, err:
-            log.exception("Domain destroy failed: %s", self.name)
+            log.exception("Domain destroy failed: %s", self.info['name'])
 
     def cleanup(self):
         """Cleanup vm resources: release devices.
@@ -647,11 +796,14 @@
                 pass
 
     def destroy(self):
-        """Clenup vm and destroy domain.
-        """
+        """Cleanup vm and destroy domain.
+        """
+
+        log.debug("XendDomainInfo.destroy")
+
         self.destroy_domain()
         self.cleanup()
-        self.saveToDB()
+        self.exportToDB()
         return 0
 
     def is_terminated(self):
@@ -664,6 +816,7 @@
         """
 
         t = xstransact("%s/device" % self.path)
+
         for n in controllerClasses.keys():
             for d in t.list(n):
                 try:
@@ -676,31 +829,6 @@
                         (self.info['name'], n, d, str(ex)))
         t.commit()
 
-
-    def show(self):
-        """Print virtual machine info.
-        """
-        print "[VM dom=%d name=%s memory=%d ssidref=%d" % (self.domid, 
self.name, self.memory, self.ssidref)
-        print "image:"
-        sxp.show(self.image)
-        print "]"
-
-    def init_domain(self):
-        """Initialize the domain memory.
-        """
-        if self.recreate:
-            return
-        if self.start_time is None:
-            self.start_time = time.time()
-            self.storeVm(("start-time", self.start_time))
-        try:
-            cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
-        except:
-            raise VmError('invalid cpu')
-        id = self.image.initDomain(self.domid, self.memory, self.ssidref, cpu, 
self.cpu_weight)
-        log.debug('init_domain> Created domain=%d name=%s memory=%d',
-                  id, self.name, self.memory)
-        self.setDomid(id)
 
     def eventChannel(self, path=None):
         """Create an event channel to the domain.
@@ -725,14 +853,8 @@
         self.console_channel = self.eventChannel("console/port")
 
     def create_configured_devices(self):
-        devices = sxp.children(self.config, 'device')
-        for d in devices:
-            dev_config = sxp.child0(d)
-            if dev_config is None:
-                raise VmError('invalid device')
-            dev_type = sxp.name(dev_config)
-
-            self.createDevice(dev_type, dev_config)
+        for (n, c) in self.info['device']:
+            self.createDevice(n, c)
 
 
     def create_devices(self):
@@ -740,8 +862,6 @@
 
         @raise: VmError for invalid devices
         """
-        if self.recreate:
-            return
         if not self.rebooting():
             self.create_configured_devices()
         self.image.createDeviceModel()
@@ -766,14 +886,6 @@
         self.configureDevice(deviceClass, devid, dev_config)
 
 
-    def configure_restart(self):
-        """Configure the vm restart mode.
-        """
-        r = sxp.child_value(self.config, 'restart', RESTART_ONREBOOT)
-        if r not in restart_modes:
-            raise VmError('invalid restart mode: ' + str(r))
-        self.restart_mode = r;
-
     def restart_needed(self, reason):
         """Determine if the vm needs to be restarted when shutdown
         for the given reason.
@@ -781,11 +893,11 @@
         @param reason: shutdown reason
         @return True if needs restart, False otherwise
         """
-        if self.restart_mode == RESTART_NEVER:
+        if self.info['restart_mode'] == RESTART_NEVER:
             return False
-        if self.restart_mode == RESTART_ALWAYS:
+        if self.info['restart_mode'] == RESTART_ALWAYS:
             return True
-        if self.restart_mode == RESTART_ONREBOOT:
+        if self.info['restart_mode'] == RESTART_ONREBOOT:
             return reason == 'reboot'
         return False
 
@@ -817,7 +929,7 @@
             tdelta = tnow - self.restart_time
             if tdelta < self.MINIMUM_RESTART_TIME:
                 self.restart_cancel()
-                msg = 'VM %s restarting too fast' % self.name
+                msg = 'VM %s restarting too fast' % self.info['name']
                 log.error(msg)
                 raise VmError(msg)
         self.restart_time = tnow
@@ -836,14 +948,13 @@
             self.exportToDB()
             self.restart_state = STATE_RESTART_BOOTING
             self.configure_bootloader()
-            self.construct(self.config)
-            self.saveToDB()
+            self.construct()
+            self.exportToDB()
         finally:
             self.restart_state = None
 
     def configure_bootloader(self):
-        self.bootloader = sxp.child_value(self.config, "bootloader")
-        if not self.bootloader:
+        if not self.info['bootloader']:
             return
         # if we're restarting with a bootloader, we need to run it
         # FIXME: this assumes the disk is the first device and
@@ -854,30 +965,13 @@
         if dev:
             disk = sxp.child_value(dev, "uname")
             fn = blkdev_uname_to_file(disk)
-            blcfg = bootloader(self.bootloader, fn, 1, self.vcpus)
+            blcfg = bootloader(self.info['bootloader'], fn, 1, 
self.info['vcpus'])
         if blcfg is None:
             msg = "Had a bootloader specified, but can't find disk"
             log.error(msg)
             raise VmError(msg)
         self.config = sxp.merge(['vm', ['image', blcfg]], self.config)
 
-    def configure_backends(self):
-        """Set configuration flags if the vm is a backend for netif or blkif.
-        Configure the backends to use for vbd and vif if specified.
-        """
-        for c in sxp.children(self.config, 'backend'):
-            v = sxp.child0(c)
-            name = sxp.name(v)
-            if name == 'blkif':
-                self.backend_flags |= SIF_BLK_BE_DOMAIN
-            elif name == 'netif':
-                self.backend_flags |= SIF_NET_BE_DOMAIN
-            elif name == 'usbif':
-                pass
-            elif name == 'tpmif':
-                self.backend_flags |= SIF_TPM_BE_DOMAIN
-            else:
-                raise VmError('invalid backend type:' + str(name))
 
     def configure(self):
         """Configure a vm.
@@ -895,19 +989,15 @@
         """
         return
 
+
     def configure_maxmem(self):
-        try:
-            maxmem = int(sxp.child_value(self.config, 'maxmem', self.memory))
-            xc.domain_setmaxmem(self.domid, maxmem_kb = maxmem * 1024)
-        except:
-            raise VmError("invalid maxmem: " +
-                          sxp.child_value(self.config, 'maxmem'))
+        xc.domain_setmaxmem(self.domid, maxmem_kb = self.info['maxmem_KiB'])
 
 
     def vcpu_hotplug(self, vcpu, state):
         """Disable or enable VCPU in domain.
         """
-        if vcpu > self.vcpus:
+        if vcpu > self.info['vcpus']:
             log.error("Invalid VCPU %d" % vcpu)
             return
         if int(state) == 0:
@@ -974,6 +1064,9 @@
                 self.vcpu_hotplug(vcpu, 0)
 
 
+    def infoIsSet(self, name):
+        return name in self.info and self.info[name] is not None
+
 
 #============================================================================
 # Register image handlers.
@@ -996,16 +1089,24 @@
 controllerClasses = {}
 
 
-def addControllerClass(device_class, cls):
+"""A map of backend names and the corresponding flag."""
+backendFlags = {}
+
+
+def addControllerClass(device_class, backend_name, backend_flag, cls):
     """Register a subclass of DevController to handle the named device-class.
+
+    @param backend_flag One of the SIF_XYZ_BE_DOMAIN constants, or None if
+    no flag is to be set.
     """
     cls.deviceClass = device_class
+    backendFlags[backend_name] = backend_flag
     controllerClasses[device_class] = cls
 
 
 from xen.xend.server import blkif, netif, tpmif, pciif, usbif
-addControllerClass('vbd',  blkif.BlkifController)
-addControllerClass('vif',  netif.NetifController)
-addControllerClass('vtpm', tpmif.TPMifController)
-addControllerClass('pci',  pciif.PciController)
-addControllerClass('usb',  usbif.UsbifController)
+addControllerClass('vbd',  'blkif', SIF_BLK_BE_DOMAIN, blkif.BlkifController)
+addControllerClass('vif',  'netif', SIF_NET_BE_DOMAIN, netif.NetifController)
+addControllerClass('vtpm', 'tpmif', SIF_TPM_BE_DOMAIN, tpmif.TPMifController)
+addControllerClass('pci',  'pciif', None,              pciif.PciController)
+addControllerClass('usb',  'usbif', None,              usbif.UsbifController)
diff -r 19572dec7d3c -r 9647be59212d tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Wed Sep 21 14:13:26 2005
+++ b/tools/python/xen/xend/image.py    Wed Sep 21 14:23:26 2005
@@ -13,7 +13,9 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
+
 
 import os, string
 import re
@@ -22,8 +24,6 @@
 from xen.xend import sxp
 from xen.xend.XendError import VmError
 from xen.xend.XendLogging import log
-from xen.xend.xenstore import DBVar
-from xen.xend.xenstore.xstransact import xstransact
 
 from xen.xend.server import channel
 
@@ -86,15 +86,13 @@
 
     findImageHandlerClass = classmethod(findImageHandlerClass)
 
-    def create(cls, vm, image):
+    def create(cls, vm, imageConfig, deviceConfig):
         """Create an image handler for a vm.
 
-        @param vm vm
-        @param image image config
         @return ImageHandler instance
         """
-        imageClass = cls.findImageHandlerClass(image)
-        return imageClass(vm, image)
+        imageClass = cls.findImageHandlerClass(imageConfig)
+        return imageClass(vm, imageConfig, deviceConfig)
 
     create = classmethod(create)
 
@@ -109,29 +107,25 @@
 
     flags = 0
 
-    def __init__(self, vm, config=None):
+    def __init__(self, vm, imageConfig, deviceConfig):
         self.vm = vm
-        self.configure(config)
-
-    def configure(self, config):
+        self.configure(imageConfig, deviceConfig)
+
+    def configure(self, imageConfig, _):
         """Config actions common to all unix-like domains."""
-        if not config:
-            self.kernel, self.cmdline, self.ramdisk = self.vm.gatherVm(
-                ("image/kernel"), ("image/cmdline"), ("image/ramdisk"))
-            return
-        
-        self.kernel = sxp.child_value(config, "kernel")
+
+        self.kernel = sxp.child_value(imageConfig, "kernel")
         self.cmdline = ""
-        ip = sxp.child_value(config, "ip", None)
+        ip = sxp.child_value(imageConfig, "ip", None)
         if ip:
             self.cmdline += " ip=" + ip
-        root = sxp.child_value(config, "root")
+        root = sxp.child_value(imageConfig, "root")
         if root:
             self.cmdline += " root=" + root
-        args = sxp.child_value(config, "args")
+        args = sxp.child_value(imageConfig, "args")
         if args:
             self.cmdline += " " + args
-        self.ramdisk = sxp.child_value(config, "ramdisk", '')
+        self.ramdisk = sxp.child_value(imageConfig, "ramdisk", '')
         
         self.vm.storeVm(("image/ostype", self.ostype),
                         ("image/kernel", self.kernel),
@@ -145,22 +139,22 @@
         except OSError, ex:
             log.warning("error removing bootloader file '%s': %s", f, ex)
 
-    def initDomain(self, dom, memory, ssidref, cpu, cpu_weight):
+    def initDomain(self, dom, memory, ssidref, cpu, cpu_weight, bootloading):
         """Initial domain create.
 
+        @param memory In KiB
         @return domain id
         """
 
         mem_kb = self.getDomainMemory(memory)
-        if not self.vm.restore:
-            dom = xc.domain_create(dom = dom or 0, ssidref = ssidref)
-            # if bootloader, unlink here. But should go after buildDomain() ?
-            if self.vm.bootloader:
-                self.unlink(self.kernel)
-                self.unlink(self.ramdisk)
-            if dom <= 0:
-                raise VmError('Creating domain failed: name=%s' %
-                              self.vm.getName())
+        dom = xc.domain_create(dom = dom or 0, ssidref = ssidref)
+        # if bootloader, unlink here. But should go after buildDomain() ?
+        if bootloading:
+            self.unlink(self.kernel)
+            self.unlink(self.ramdisk)
+        if dom <= 0:
+            raise VmError('Creating domain failed: name=%s' %
+                          self.vm.getName())
         log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, 
mem_kb, ssidref, dom)
         xc.domain_setcpuweight(dom, cpu_weight)
         xc.domain_setmaxmem(dom, mem_kb)
@@ -184,9 +178,6 @@
     def createDomain(self):
         """Build the domain boot image.
         """
-        if self.vm.recreate or self.vm.restore:
-            return
-
         # Set params and call buildDomain().
         self.flags = self.vm.getBackendFlags()
 
@@ -205,9 +196,11 @@
             raise VmError('Building domain failed: ostype=%s dom=%d err=%d'
                           % (self.ostype, self.vm.getDomain(), err))
 
-    def getDomainMemory(self, mem_mb):
-        """Memory (in KB) the domain will need for mem_mb (in MB)."""
-        return mem_mb * 1024
+    def getDomainMemory(self, mem):
+        """@return The memory required, in KiB, by the domain to store the
+        given amount, also in KiB.  This is normally just mem, but VMX domains
+        have overheads to account for."""
+        return mem
 
     def buildDomain(self):
         """Build the domain. Define in subclass."""
@@ -269,38 +262,33 @@
 
     ostype = "vmx"
 
-    memmap = None
-    memmap_value = []
-    device_channel = None
-    pid = 0
-
-    def configure(self, config):
-        ImageHandler.configure(self, config)
-        if not config:
-            self.memmap, dmargs, self.device_model, self.display = 
self.vm.gatherVm(
-                ("image/memmap"), ("image/dmargs"), ("image/device-model"),
-                ("image/display"))
-            self.dmargs = dmargs.split(' ')
-            return
+    def configure(self, imageConfig, deviceConfig):
+        ImageHandler.configure(self, imageConfig, deviceConfig)
         
-        self.memmap = sxp.child_value(config, 'memmap')
-        self.dmargs = self.parseDeviceModelArgs(config)
-        self.device_model = sxp.child_value(config, 'device_model')
+        self.memmap = sxp.child_value(imageConfig, 'memmap')
+        self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
+        self.device_model = sxp.child_value(imageConfig, 'device_model')
         if not self.device_model:
             raise VmError("vmx: missing device model")
-        self.display = sxp.child_value(config, 'display')
+        self.display = sxp.child_value(imageConfig, 'display')
 
         self.vm.storeVm(("image/memmap", self.memmap),
                         ("image/dmargs", " ".join(self.dmargs)),
                         ("image/device-model", self.device_model),
                         ("image/display", self.display))
 
+        self.device_channel = None
+        self.pid = 0
+        self.memmap_value = []
+
+        self.dmargs += self.configVNC(imageConfig)
+
+
     def createImage(self):
         """Create a VM for the VMX environment.
         """
         self.parseMemmap()
         self.createDomain()
-        self.dmargs += self.configVNC(sxp.child_value(self.vm.config, 'image'))
 
     def buildDomain(self):
         # Create an event channel
@@ -314,7 +302,7 @@
                            image          = self.kernel,
                            control_evtchn = self.device_channel.port2,
                            store_evtchn   = store_evtchn,
-                           memsize        = self.vm.getMemoryTarget(),
+                           memsize        = self.vm.getMemoryTarget() / 1024,
                            memmap         = self.memmap_value,
                            cmdline        = self.cmdline,
                            ramdisk        = self.ramdisk,
@@ -334,12 +322,12 @@
         
     # Return a list of cmd line args to the device models based on the
     # xm config file
-    def parseDeviceModelArgs(self, config):
+    def parseDeviceModelArgs(self, imageConfig, deviceConfig):
         dmargs = [ 'cdrom', 'boot', 'fda', 'fdb',
                    'localtime', 'serial', 'stdvga', 'isa' ] 
         ret = []
         for a in dmargs:
-            v = sxp.child_value(config, a)
+            v = sxp.child_value(imageConfig, a)
 
             # python doesn't allow '-' in variable names
             if a == 'stdvga': a = 'std-vga'
@@ -354,14 +342,11 @@
                 ret.append("%s" % v)
 
         # Handle disk/network related options
-        devices = sxp.children(self.vm.config, 'device')
-        for device in devices:
-            name = sxp.name(sxp.child0(device))
+        for (name, info) in deviceConfig:
             if name == 'vbd':
-               vbdinfo = sxp.child(device, 'vbd')
-               uname = sxp.child_value(vbdinfo, 'uname')
-               typedev = sxp.child_value(vbdinfo, 'dev')
-               (vbdtype, vbdparam) = string.split(uname, ':', 1)
+               uname = sxp.child_value(info, 'uname')
+               typedev = sxp.child_value(info, 'dev')
+               (_, vbdparam) = string.split(uname, ':', 1)
                if re.match('^ioemu:', typedev):
                   (emtype, vbddev) = string.split(typedev, ':', 1)
                else:
@@ -375,13 +360,11 @@
                ret.append("-%s" % vbddev)
                ret.append("%s" % vbdparam)
             if name == 'vif':
-               vifinfo = sxp.child(device, 'vif')
-               mac = sxp.child_value(vifinfo, 'mac')
+               mac = sxp.child_value(info, 'mac')
                ret.append("-macaddr")
                ret.append("%s" % mac)
             if name == 'vtpm':
-               vtpminfo = sxp.child(device, 'vtpm')
-               instance = sxp.child_value(vtpminfo, 'instance')
+               instance = sxp.child_value(info, 'instance')
                ret.append("-instance")
                ret.append("%s" % instance)
         return ret
@@ -417,7 +400,7 @@
             args = args + vnc
         args = args + ([ "-d",  "%d" % self.vm.getDomain(),
                   "-p", "%d" % self.device_channel.port1,
-                  "-m", "%s" % self.vm.getMemoryTarget() ])
+                  "-m", "%s" % self.vm.getMemoryTarget() / 1024 ])
         args = args + self.dmargs
         env = dict(os.environ)
         env['DISPLAY'] = self.display
@@ -445,13 +428,14 @@
         if not self.pid:
             return
         os.kill(self.pid, signal.SIGKILL)
-        (pid, status) = os.waitpid(self.pid, 0)
+        os.waitpid(self.pid, 0)
         self.pid = 0
 
-    def getDomainMemory(self, mem_mb):
+    def getDomainMemory(self, mem):
+        """@see ImageHandler.getDomainMemory"""
         # for ioreq_t and xenstore
         static_pages = 2
-        return (mem_mb * 1024) + self.getPageTableSize(mem_mb) + 4 * 
static_pages
+        return mem + self.getPageTableSize(mem * 1024) + 4 * static_pages
             
     def getPageTableSize(self, mem_mb):
         """Return the size of memory needed for 1:1 page tables for physical

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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