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

[Xen-changelog] [xen-unstable] [XEND] Remove SXP from most parts of Xend.



# HG changeset patch
# User Alastair Tse <atse@xxxxxxxxxxxxx>
# Node ID 5bed7bc05c8a0de90f2047a98b24e5347d6d9dda
# Parent  e7cb5813e2a7e5d95c22855e1d63cba8147c5422
[XEND] Remove SXP from most parts of Xend.

Attempt to get rid of most SXP dependency in Xend except in
configuration parsing and certain places where it is
required.

XendConfig now stores configuration options similar to Xen API VM
and devices attributes but exports an SXP version to certain things
like xm and XendCheckpoint. All access to VM and device attributes
should now use Python dictionaries rather than the SXP parser.

Signed-off-by: Alastair Tse <atse@xxxxxxxxxxxxx>
---
 tools/python/xen/xend/XendAPI.py                       |   12 
 tools/python/xen/xend/XendCheckpoint.py                |    4 
 tools/python/xen/xend/XendConfig.py                    | 1229 +++++++++--------
 tools/python/xen/xend/XendDomain.py                    |   11 
 tools/python/xen/xend/XendDomainInfo.py                |  328 ++--
 tools/python/xen/xend/image.py                         |  138 -
 tools/python/xen/xend/server/DevController.py          |    7 
 tools/python/xen/xend/server/blkif.py                  |   21 
 tools/python/xen/xend/server/iopif.py                  |    4 
 tools/python/xen/xend/server/irqif.py                  |    2 
 tools/python/xen/xend/server/netif.py                  |   24 
 tools/python/xen/xend/server/pciif.py                  |   69 
 tools/python/xen/xend/server/pciquirk.py               |   43 
 tools/python/xen/xend/server/tests/test_controllers.py |    6 
 tools/python/xen/xend/server/tpmif.py                  |   12 
 tools/python/xen/xm/main.py                            |    4 
 16 files changed, 1008 insertions(+), 906 deletions(-)

diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/XendAPI.py  Thu Nov 30 14:44:58 2006 +0000
@@ -730,11 +730,11 @@ class XendAPI:
     
     def vm_get_memory_dynamic_max(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_todo()
+        return xen_api_success(dom.get_memory_dynamic_max())
 
     def vm_get_memory_dynamic_min(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_todo()    
+        return xen_api_success(dom.get_memory_dynamic_min())        
     
     def vm_get_VCPUs_policy(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
@@ -798,11 +798,11 @@ class XendAPI:
     
     def vm_get_builder(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_todo()
+        return xen_api_success(dom.get_builder())
     
     def vm_get_boot_method(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_success('')
+        return xen_api_success(dom.get_boot_method())
     
     def vm_get_kernel_kernel(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
@@ -969,8 +969,8 @@ class XendAPI:
             'resident_on': XendNode.instance().uuid,
             'memory_static_min': xeninfo.get_memory_static_min(),
             'memory_static_max': xeninfo.get_memory_static_max(),
-            'memory_dynamic_min': xeninfo.get_memory_static_min(),
-            'memory_dynamic_max': xeninfo.get_memory_static_max(),
+            'memory_dynamic_min': xeninfo.get_memory_dynamic_min(),
+            'memory_dynamic_max': xeninfo.get_memory_dynamic_max(),
             'memory_actual': xeninfo.get_memory_static_min(),
             'vcpus_policy': xeninfo.get_vcpus_policy(),
             'vcpus_params': xeninfo.get_vcpus_params(),
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/XendCheckpoint.py   Thu Nov 30 14:44:58 2006 +0000
@@ -18,8 +18,8 @@ from xen.xend import balloon, sxp
 from xen.xend import balloon, sxp
 from xen.xend.XendError import XendError, VmError
 from xen.xend.XendLogging import log
+from xen.xend.XendConfig import XendConfig
 from xen.xend.XendConstants import *
-from xen.xend.XendConfig import XendConfig
 
 SIGNATURE = "LinuxGuestRecord"
 XC_SAVE = "xc_save"
@@ -137,7 +137,7 @@ def restore(xd, fd, dominfo = None, paus
     vmconfig = p.get_val()
 
     if dominfo:
-        dominfo.update(XendConfig(sxp = vmconfig), refresh = False)
+        dominfo.update(XendConfig(sxp_obj = vmconfig), refresh = False)
         dominfo.resume()
     else:
         dominfo = xd.restore_(vmconfig)
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/XendConfig.py       Thu Nov 30 14:44:58 2006 +0000
@@ -31,31 +31,34 @@ XendConfig API
 XendConfig API
 
   XendConfig will try to mirror as closely the Xen API VM Struct
-  providing a backwards compatibility mode for SXP dumping, loading.
+  with extra parameters for those options that are not supported.
 
 """
 
-
-LEGACY_CFG_TO_XENAPI_CFG = {
+def reverse_dict(adict):
+    """Return the reverse mapping of a dictionary."""
+    return dict([(v, k) for k, v in adict.items()])
+
+# Mapping from XendConfig configuration keys to the old
+# legacy configuration keys that map directly.
+
+XENAPI_CFG_TO_LEGACY_CFG = {
     'uuid': 'uuid',
-    'vcpus': 'vcpus_number',
-    'maxmem': 'memory_static_max',
-    'memory': 'memory_static_min',
-    'name': 'name_label',
-    'on_poweroff': 'actions_after_shutdown',            
-    'on_reboot': 'actions_after_reboot',
-    'on_crash': 'actions_after_crash',
-    'bootloader': 'boot_method',
-    'kernel_kernel': 'kernel_kernel',
-    'kernel_initrd': 'kernel_initrd',
-    'kernel_args': 'kernel_args',
-    }
-
-XENAPI_CFG_CUSTOM_TRANSLATE = [
-    'vifs',
-    'vbds',
-    ]
-
+    'vcpus_number': 'vcpus',
+    'memory_static_min': 'memory',
+    'memory_static_max': 'maxmem',
+    'name_label': 'name',
+    'actions_after_shutdown': 'on_poweroff',
+    'actions_after_reboot': 'on_reboot',
+    'actions_after_crash': 'on_crash', 
+    'platform_localtime': 'localtime',
+}
+
+LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG)
+
+# Mapping from XendConfig configuration keys to the old
+# legacy configuration keys that are found in the 'image'
+# SXP object.
 XENAPI_HVM_CFG = {
     'platform_std_vga': 'std-vga',
     'platform_serial' : 'serial',
@@ -64,7 +67,10 @@ XENAPI_HVM_CFG = {
     'platform_keymap' : 'keymap',
 }    
 
-XENAPI_UNSUPPORTED_IN_LEGACY_CFG = [
+# List of XendConfig configuration keys that have no equivalent
+# in the old world.
+
+XENAPI_UNSUPPORTED_BY_LEGACY_CFG = [
     'name_description',
     'user_version',
     'is_a_template',
@@ -85,11 +91,116 @@ XENAPI_UNSUPPORTED_IN_LEGACY_CFG = [
     'platform_clock_offset',
     'platform_enable_audio',
     'platform_keymap',
+    'boot_method',
     'builder',
     'grub_cmdline',
     'pci_bus',
     'otherconfig'
-    ]
+]
+
+# List of legacy configuration keys that have no equivalent in the
+# Xen API, but are still stored in XendConfig.
+
+LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [
+    # roundtripped (dynamic, unmodified)
+    'shadow_memory',
+    'security',
+    'vcpu_avail',
+    'cpu_weight',
+    'cpu_cap',
+    'bootloader',
+    'bootloader_args',
+    'features',
+    # read/write
+    'on_xend_start',
+    'on_xend_stop',
+    # read-only
+    'domid',
+    'start_time',
+    'cpu_time',
+    'online_vcpus',
+    # write-once
+    'cpu',
+    'cpus',
+]
+
+LEGACY_CFG_TYPES = {
+    'uuid':          str,
+    'name':          str,
+    'vcpus':         int,
+    'vcpu_avail':    int,
+    'memory':        int,
+    'shadow_memory': int,
+    'maxmem':        int,
+    'start_time':    float,
+    'cpu_cap':         int,
+    'cpu_weight':      int,
+    'cpu_time':      float,
+    'bootloader':      str,
+    'bootloader_args': str,
+    'features':        str,
+    'localtime':       int,
+    'name':        str,
+    'on_poweroff': str,
+    'on_reboot':   str,
+    'on_crash':    str,
+    'on_xend_stop': str,
+    'on_xend_start': str,
+}
+
+# Values that should be stored in xenstore's /vm/<uuid> that is used
+# by Xend. Used in XendDomainInfo to restore running VM state from
+# xenstore.
+LEGACY_XENSTORE_VM_PARAMS = [
+    'uuid',
+    'name',
+    'vcpus',
+    'vcpu_avail',
+    'memory',
+    'shadow_memory',
+    'maxmem',
+    'start_time',
+    'name',
+    'on_poweroff',
+    'on_crash',
+    'on_reboot',
+    'on_xend_start',
+    'on_xend_stop',
+]
+
+LEGACY_IMAGE_CFG = [
+    ('root', str),
+    ('ip', str),
+    ('nographic', int),
+    ('vnc', int),
+    ('sdl', int),
+    ('vncdisplay', int),
+    ('vncunused', int),
+]
+
+LEGACY_IMAGE_HVM_CFG = [
+    ('device_model', str),
+    ('display', str),
+    ('xauthority', str),
+    ('vncconsole', int),
+    ('pae', int),
+    ('apic', int),
+    ('acpi', int),
+    ('serial', str),
+]
+
+LEGACY_IMAGE_HVM_DEVICES_CFG = [
+    ('boot', str),
+    ('fda', str),
+    ('fdb', str),
+    ('soundhw', str),
+    ('isa', str),
+    ('vcpus', int),
+    ('acpi', int),
+    ('usb', str),
+    ('usbdevice', str),
+]
+
 
 
 # configuration params that need to be converted to ints
@@ -102,75 +213,12 @@ XENAPI_INT_CFG = [
     'memory_static_max',
     'memory_dynamic_min',
     'memory_dynamic_max',
+    'memory_actual',
     'tpm_instance',
     'tpm_backend',
 ]    
 
 ##
-## Xend Configuration Parameters
-##
-
-
-# All parameters of VMs that may be configured on-the-fly, or at start-up.
-VM_CONFIG_ENTRIES = [
-    ('name',        str),
-    ('on_crash',    str),
-    ('on_poweroff', str),
-    ('on_reboot',   str),
-    ('on_xend_start', str),
-    ('on_xend_stop', str),        
-]
-
-# All entries written to the store.  This is VM_CONFIG_ENTRIES, plus those
-# entries written to the store that cannot be reconfigured on-the-fly.
-VM_STORE_ENTRIES = [
-    ('uuid',       str),
-    ('vcpus',      int),
-    ('vcpu_avail', int),
-    ('memory',     int),
-    ('maxmem',     int),
-    ('start_time', float),
-]
-
-VM_STORED_ENTRIES = VM_CONFIG_ENTRIES + VM_STORE_ENTRIES
-
-# Configuration entries that we expect to round-trip -- be read from the
-# config file or xc, written to save-files (i.e. through sxpr), and reused as
-# config on restart or restore, all without munging.  Some configuration
-# entries are munged for backwards compatibility reasons, or because they
-# don't come out of xc in the same form as they are specified in the config
-# file, so those are handled separately.
-
-ROUNDTRIPPING_CONFIG_ENTRIES = [
-    ('uuid',       str),
-    ('vcpus',      int),
-    ('vcpu_avail', int),
-    ('cpu_cap',    int),
-    ('cpu_weight', int),
-    ('memory',     int),
-    ('shadow_memory', int),
-    ('maxmem',     int),
-    ('bootloader', str),
-    ('bootloader_args', str),
-    ('features', str),
-    ('localtime', int),
-]
-ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_ENTRIES
-
-## Static Configuration
-
-STATIC_CONFIG_ENTRIES = [
-    ('cpu',      int),
-    ('cpus',     str),
-    ('image',    list),
-    ('security', list), # TODO: what if null?
-]
-
-DEPRECATED_ENTRIES = [
-    ('restart', str),
-]
-
-##
 ## Config Choices
 ##
 
@@ -178,245 +226,152 @@ CONFIG_OLD_DOM_STATES = ('running', 'blo
 CONFIG_OLD_DOM_STATES = ('running', 'blocked', 'paused', 'shutdown',
                          'crashed', 'dying')
 
-##
-## Defaults
-##
-
-def DEFAULT_VCPUS(info):
-    if 'max_vcpu_id' in info: return int(info['max_vcpu_id']) + 1
-    else: return 1
-
-DEFAULT_CONFIGURATION = (
-    ('uuid',         lambda info: uuid.createString()),
-    ('name',         lambda info: 'Domain-' + info['uuid']),
-
-    ('on_poweroff',  lambda info: 'destroy'),
-    ('on_reboot',    lambda info: 'restart'),
-    ('on_crash',     lambda info: 'restart'),
-    ('features',     lambda info: ''),
-
-    
-    ('memory',       lambda info: 0),
-    ('shadow_memory',lambda info: 0),
-    ('maxmem',       lambda info: 0),
-    ('bootloader',   lambda info: None),
-    ('bootloader_args', lambda info: None),            
-    ('backend',      lambda info: []),
-    ('device',       lambda info: {}),
-    ('image',        lambda info: None),
-    ('security',     lambda info: []),
-    ('on_xend_start', lambda info: 'ignore'),    
-    ('on_xend_stop', lambda info: 'ignore'),
-
-    ('cpus',         lambda info: []),
-    ('cpu_cap',      lambda info: 0),
-    ('cpu_weight',   lambda info: 256),
-    ('vcpus',        lambda info: DEFAULT_VCPUS(info)),
-    ('online_vcpus', lambda info: info['vcpus']),
-    ('max_vcpu_id',  lambda info: info['vcpus']-1),
-    ('vcpu_avail',   lambda info: (1<<info['vcpus'])-1),
-
-    # New for Xen API
-    ('kernel_kernel', lambda info: ''),
-    ('kernel_initrd', lambda info: ''),
-    ('kernel_args',   lambda info: ''),
-    
-)
-    
 class XendConfigError(VmError):
     def __str__(self):
         return 'Invalid Configuration: %s' % str(self.value)
 
 ##
-## XendConfig SXP Config Compat
-##
-
-class XendSXPConfig:
-    def get_domid(self):
-        pass
-    def get_handle(self):
-        return self['uuid']
-        
-
-##
 ## XendConfig Class (an extended dictionary)
 ##
 
 class XendConfig(dict):
-    """ Generic Configuration Parser accepting SXP, Python or XML.
-    This is a dictionary-like object that is populated.
-
-    @ivar legacy: dictionary holding legacy xen domain info
-    @ivar xenapi: dictionary holding xen api config info
+    """ The new Xend VM Configuration.
+
+    Stores the configuration in xenapi compatible format but retains
+    import and export functions for SXP.
     """
-
-    def __init__(self, filename = None, fd = None,
-                 sxp = None, xml = None, pycfg = None, xenapi_vm = None,
-                 cfg = {}):
-        """Constructor. Provide either the filename, fd or sxp.
-
-        @keyword filename: filename of an SXP file
-        @keyword fd: file descriptor of an SXP file
-        @keyword sxp: a list of list of a parsed SXP
-        @keyword xml: an XML tree object
-        @keyword xenapi_vm: a struct passed from an XMLRPC call (Xen API)
-        @keyword cfg: a dictionary of configuration (eg. from xc)
-        """
-        format = 'unknown'
-
-        self.xenapi = {}
-
-        if filename and not fd:
-            fd = open(filename, 'r')
-
-        if fd:
-            format = self._detect_format(fd)
-        
-        if fd:
-            if format == 'sxp':
-                sxp = self._read_sxp(fd)
-            elif format == 'python' and filename != None:
-                pycfg = self._read_python(filename)
-            elif format == 'python' and filename == None:
-                raise XendConfigError("Python files must be passed as a "
-                                      "filename rather than file descriptor.")
-            elif format == 'xml':
-                xml = self._read_xml(fd)
-            else:
-                raise XendConfigError("Unable to determine format of file")
-                
-        if sxp:
-            cfg = self._populate_from_sxp(sxp)
-        if xml:
-            cfg = self._populate_from_xml(xml)
-        if pycfg:
-            cfg = self._populate_from_python_config(pycfg)
-        if xenapi_vm:
-            cfg = self._populate_from_xenapi_vm(xenapi_vm)
+    def __init__(self, filename = None, sxp_obj = None,
+                 xapi = None, dominfo = None):
+        
+        dict.__init__(self)
+        self.update(self._defaults())
+
+        if filename:
+            try:
+                sxp_obj = sxp.parse(open(filename,'r'))
+                sxp_obj = sxp_obj[0]
+            except IOError, e:
+                raise XendConfigError("Unable to read file: %s" % filename)
+        
+        if sxp_obj:
+            self._sxp_to_xapi(sxp_obj)
+            self._sxp_to_xapi_unsupported(sxp_obj)
+        elif xapi:
+            self.update(xapi)
+            self._add_xapi_unsupported()
+        elif dominfo:
+            # output from xc.domain_getinfo
+            self._dominfo_to_xapi(dominfo)
+
+        log.debug('XendConfig.init: %s' % self)
+
+        # validators go here
+        self.validate()
+
+    def _defaults(self):
+        defaults = {
+            'uuid': uuid.createString(),
+            'name_label': 'Domain-Unnamed',
+            'actions_after_shutdown': 'destroy',
+            'actions_after_reboot': 'restart',
+            'actions_after_crash': 'restart',
+            'actions_after_suspend': '',
+            'features': '',
+            'builder': 'linux',
+            'memory_static_min': 0,
+            'memory_dynamic_min': 0,
+            'shadow_memory': 0,
+            'memory_static_max': 0,
+            'memory_dynamic_max': 0,
+            'memory_actual': 0,
+            'boot_method': None,
+            'bootloader': None,
+            'bootloader_args': None,
+            'devices': {},
+            'image': {},
+            'security': None,
+            'on_xend_start': 'ignore',
+            'on_xend_stop': 'ignore',
+            'cpus': [],
+            'cpu_weight': 256,
+            'cpu_cap': 0,
+            'vcpus_number': 1,
+            'online_vcpus': 1,
+            'max_vcpu_id': 0,
+            'vcpu_avail': 1,
+            'vif_refs': [],
+            'vbd_refs': [],
+            'vtpm_refs': [],
+        }
+        
+        defaults['name_label'] = 'Domain-' + defaults['uuid']
+        return defaults
+
+    def _memory_sanity_check(self):
+        if self['memory_static_min'] == 0:
+            self['memory_static_min'] = self['memory_dynamic_min']
+
+        # If the static max is not set, let's set it to dynamic max.
+        # If the static max is smaller than static min, then fix it!
+        self['memory_static_max'] = max(self['memory_static_max'],
+                                        self['memory_dynamic_max'],
+                                        self['memory_static_min'])
+
+        for mem_type in ('memory_static_min', 'memory_static_max'):
+            if self[mem_type] <= 0:
+                raise XendConfigError('Memory value too low for %s: %d' %
+                                      (mem_type, self[mem_type]))
+
+    def _actions_sanity_check(self):
+        for event in ['shutdown', 'reboot', 'crash']:
+            if self['actions_after_' + event] not in CONFIG_RESTART_MODES:
+                raise XendConfigError('Invalid event handling mode: ' +
+                                      event)
+
+    def validate(self):
+        self._memory_sanity_check()
+        self._actions_sanity_check()
+
+    def _dominfo_to_xapi(self, dominfo):
+        self['domid'] = dominfo['domid']
+        self['online_vcpus'] = dominfo['online_vcpus']
+        self['max_vcpu_id'] = dominfo['max_vcpu_id']
+        self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
+        self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
+        self['cpu_time'] = dominfo['cpu_time']/1e9
+        # TODO: i don't know what the security stuff expects here
+        if dominfo.get('ssidref'):
+            self['security'] = [['ssidref', dominfo['ssidref']]]
+        self['shutdown_reason'] = dominfo['shutdown_reason']
+
+        # parse state into Xen API states
+        self['running'] = dominfo['running']
+        self['crashed'] = dominfo['crashed']
+        self['dying'] = dominfo['dying']
+        self['shutdown'] = dominfo['shutdown']
+        self['paused'] = dominfo['paused']
+        self['blocked'] = dominfo['blocked']
+
+        if 'name' in dominfo:
+            self['name_label'] = dominfo['name']
+
+        if 'handle' in dominfo:
+            self['uuid'] = uuid.toString(dominfo['handle'])
             
-        if cfg:
-            self.update(cfg)
-            
-        if xenapi_vm:
-            self.xenapi.update(xenapi_vm)
-
-        log.debug('XendConfig: %s' % str(self))
-        self.validate()
-
-    #
-    # Xen API Attribute Access
-    #
-
-    def __getattr__(self, name):
-        try:
-            return dict.__getattr__(self, name)
-        except AttributeError:
-            try:
-                return  self.__dict__['xenapi'][name]
-            except KeyError:
-                raise AttributeError("XendConfig Xen API has no attribute "
-                                     "'%s'" % name)
-            
-
-    def __setattr__(self, name, value):
-        try:
-            return dict.__setattr__(self, name, value)
-        except AttributeError:
-            self.xenapi[name] = value
-            #self.set_legacy_api_with_xen_api_value(name, value)
-
-    def __delattr__(self, name):
-        try:
-            dict.__delattr__(self, name)
-        except AttributeError:
-            del self.xenapi[name]
-        #self.del_legacy_api_with_xen_api_key(name)
-
-
-    """
-    #
-    # Legacy API Attribute Access
-    #
-
-    def __getitem__(self, key):
-        try:
-            return self.legacy[key]
-        except KeyError:
-            raise AttributeError, "XendConfig Legacy has no attribute '%s'"\
-                  % key
-
-    def __setitem__(self, key, value):
-        self.legacy[key] = value
-        self.set_xen_api_with_legacy_api_value(key, value)
-
-    def __delitem__(self, key):
-        del self.legacy[key]
-        self.del_xen_api_with_legacy_api_key(key)
-    """
-    
-
-    def _detect_format(self, fd):
-        """Detect the format of the configuration passed.
-
-        @param fd: file descriptor of contents to detect
-        @rtype: string, 'sxp', 'xml', 'python' or 'unknown'
-        """
-        format = 'unknown'
-        
-        fd.seek(0)
-        for line in fd:
-            stripped = line.strip()
-            if stripped:
-                if re.search(r'^\(', stripped): 
-                    format = 'sxp'
-                elif re.search(r'^\<?xml', stripped):
-                    format = 'xml'
-                else:
-                    format = 'python'
-                break
-
-        fd.seek(0)
-        return format
-
-    def _read_sxp(self, fd):
-        """ Read and parse SXP (from SXP to list of lists)
-
-        @rtype: list of lists.
-        """
-        try:
-            parsed = sxp.parse(fd)[0]
-            return parsed
-        except:
-            raise
-            return None
-
-    def _read_xml(self, fd):
-        """TODO: Read and parse XML (from XML to dict)
-
-        @rtype: dict
-        """
-        raise NotImplementedError
-
-    def _read_python(self, filename):
-        """Read and parse python module that represents the config.
-
-        @rtype: dict
-        """
-        cfg_globals = {}
-        execfile(filename, cfg_globals, {})
-        return cfg_globals
-
-    def _populate_from_sxp(self, parsed):
+    def _parse_sxp(self, sxp_cfg):
         """ Populate this XendConfig using the parsed SXP.
 
+        @param sxp_cfg: Parsed SXP Configuration
+        @type sxp_cfg: list of lists
         @rtype: dictionary
+        @return: A dictionary containing the parsed options of the SXP.
         """
         cfg = {}
 
         # First step is to convert deprecated options to
         # current equivalents.
         
-        restart = sxp.child_value(parsed, 'restart')
+        restart = sxp.child_value(sxp_cfg, 'restart')
         if restart:
             if restart == 'onreboot':
                 cfg['on_poweroff'] = 'destroy'
@@ -433,23 +388,19 @@ class XendConfig(dict):
                          'restart = \'%s\'', restart)
 
         # Only extract options we know about.
-        all_params = VM_CONFIG_ENTRIES + ROUNDTRIPPING_CONFIG_ENTRIES + \
-                     STATIC_CONFIG_ENTRIES
-                     
-        for key, typeconv in all_params:
-            val = sxp.child_value(parsed, key)
+        extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
+        extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
+        
+        for key in extract_keys:
+            val = sxp.child_value(sxp_cfg, key)
             if val:
                 try:
-                    cfg[key] = typeconv(val)
+                    try:
+                        cfg[key] = LEGACY_CFG_TYPES[key](val)
+                    except KeyError:
+                        cfg[key] = val
                 except ValueError:
                     pass
-
-        # Manually extract other complex configuration
-        # options.
-
-        cfg['backend'] = []
-        for c in sxp.children(parsed, 'backend'):
-            cfg['backend'].append(sxp.name(sxp.child0(c)))
 
         # Parsing the device SXP's. In most cases, the SXP looks
         # like this:
@@ -472,65 +423,52 @@ class XendConfig(dict):
         # Hence we deal with pci device configurations outside of
         # the regular device parsing.
         
-        cfg['device'] = {}
-        for dev in sxp.children(parsed, 'device'):
+        cfg['devices'] = {}
+        for dev in sxp.children(sxp_cfg, 'device'):
             config = sxp.child0(dev)
             dev_type = sxp.name(config)
             dev_info = {}
             
             if dev_type == 'pci':
-                continue 
-            
-            for opt, val in config[1:]:
-                dev_info[opt] = val
-            log.debug("XendConfig: reading device: %s" % dev_info)
-            # create uuid if it doesn't
-            dev_uuid = dev_info.get('uuid', uuid.createString())
-            dev_info['uuid'] = dev_uuid
-            cfg['device'][dev_uuid] = (dev_type, dev_info)
-
-        # deal with PCI device configurations if they exist
-        for dev in sxp.children(parsed, 'device'):
-            config = sxp.child0(dev)
-            dev_type = sxp.name(config)
-
-            if dev_type != 'pci':
-                continue
-            
-            dev_attr = sxp.child_value(config, 'dev')
-            if isinstance(dev_attr, (types.ListType, types.TupleType)):
+                pci_devs_uuid = sxp.child_value(config, 'uuid',
+                                                uuid.createString())
+                pci_devs = []
                 for pci_dev in sxp.children(config, 'dev'):
-                    dev_info = {}
+                    pci_dev_info = {}
                     for opt, val in pci_dev[1:]:
-                        dev_info[opt] = val
-                    log.debug("XendConfig: reading device: %s" % dev_info)
-                    dev_uuid = dev_info.get('uuid', uuid.createString())
-                    dev_info['uuid'] = dev_uuid
-                    cfg['device'][dev_uuid] = (dev_type, dev_info)
-                    
-            else: # Xen 2.0 PCI device configuration
+                        pci_dev_info[opt] = val
+                    pci_devs.append(pci_dev_info)
+                
+                cfg['devices'][pci_devs_uuid] = (dev_type,
+                                                 {'devs': pci_devs,
+                                                  'uuid': pci_devs_uuid})
+                
+                log.debug("XendConfig: reading device: %s" % pci_devs)
+            else:
                 for opt, val in config[1:]:
                     dev_info[opt] = val
                 log.debug("XendConfig: reading device: %s" % dev_info)
                 # create uuid if it doesn't
                 dev_uuid = dev_info.get('uuid', uuid.createString())
                 dev_info['uuid'] = dev_uuid
-                cfg['device'][dev_uuid] = (dev_type, dev_info)
+                cfg['devices'][dev_uuid] = (dev_type, dev_info)
+
 
         # Extract missing data from configuration entries
-        if 'image' in cfg:
-            image_vcpus = sxp.child_value(cfg['image'], 'vcpus')
+        image_sxp = sxp.child_value(sxp_cfg, 'image', [])
+        if image_sxp:
+            image_vcpus = sxp.child_value(image_sxp, 'vcpus')
             if image_vcpus is not None:
                 try:
-                    if 'vcpus' not in cfg:
-                        cfg['vcpus'] = int(image_vcpus)
-                    elif cfg['vcpus'] != int(image_vcpus):
-                        cfg['vcpus'] = int(image_vcpus)
+                    if 'vcpus_number' not in cfg:
+                        cfg['vcpus_number'] = int(image_vcpus)
+                    elif cfg['vcpus_number'] != int(image_vcpus):
+                        cfg['vcpus_number'] = int(image_vcpus)
                         log.warn('Overriding vcpus from %d to %d using image'
-                                 'vcpus value.', cfg['vcpus'])
+                                 'vcpus value.', cfg['vcpus_number'])
                 except ValueError, e:
                     raise XendConfigError('integer expeceted: %s: %s' %
-                                        str(cfg['image']), e)
+                                          image_sxp, e)
 
         # Deprecated cpu configuration
         if 'cpu' in cfg:
@@ -564,101 +502,176 @@ class XendConfig(dict):
         except ValueError, e:
             raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
 
-        # Parse image SXP outside of image.py
-        # - used to be only done in image.py
-        if 'image' in cfg:
-            cfg['kernel_kernel'] = sxp.child_value(cfg['image'], 'kernel','')
-            cfg['kernel_initrd'] = sxp.child_value(cfg['image'], 'ramdisk','')
-            kernel_args = sxp.child_value(cfg['image'], 'args', '')
-
-            # attempt to extract extra arguments from SXP config
-            arg_ip = sxp.child_value(cfg['image'], 'ip')
-            if arg_ip: kernel_args += ' ip=%s' % arg_ip
-            arg_root = sxp.child_value(cfg['image'], 'root')
-            if arg_root: kernel_args += ' root=%s' % arg_root
-            
-            cfg['kernel_args'] = kernel_args
+        if 'security' in cfg and isinstance(cfg['security'], str):
+            cfg['security'] = sxp.from_string(cfg['security'])
 
         # TODO: get states
-        old_state = sxp.child_value(parsed, 'state')
+        old_state = sxp.child_value(sxp_cfg, 'state')
         if old_state:
             for i in range(len(CONFIG_OLD_DOM_STATES)):
                 cfg[CONFIG_OLD_DOM_STATES[i]] = int(old_state[i] != '-')
 
-        # Xen API extra cfgs
-        # ------------------
-        cfg['vif_refs'] = []
-        cfg['vbd_refs'] = []
-        cfg['vtpm_refs'] = []
-        for dev_uuid, (dev_type, dev_info) in cfg['device'].items():
-            if dev_type == 'vif':
-                cfg['vif_refs'].append(dev_uuid)
-            elif dev_type in ('vbd','tap'):
-                cfg['vbd_refs'].append(dev_uuid)
-            elif dev_type == 'vtpm':
-                cfg['vtpm_refs'].append(dev_uuid)
-                
         return cfg
-
-
-    def _populate_from_xenapi_vm(self, xenapi_vm):
-        cfg = {}
-
-        for cfgkey, apikey in LEGACY_CFG_TO_XENAPI_CFG.items():
+    
+
+    def _sxp_to_xapi(self, sxp_cfg):
+        """Read in an SXP Configuration object and
+        populate at much of the Xen API with valid values.
+        """
+        cfg = self._parse_sxp(sxp_cfg)
+
+        # Convert parameters that can be directly mapped from
+        # the Legacy Config to Xen API Config
+        
+        for apikey, cfgkey in XENAPI_CFG_TO_LEGACY_CFG.items():
             try:
-                if apikey in XENAPI_INT_CFG:
-                    cfg[cfgkey] = int(xenapi_vm[apikey])
-                else:
-                    cfg[cfgkey] = xenapi_vm[apikey]                    
+                self[apikey] = LEGACY_CFG_TYPES[cfgkey](cfg[cfgkey])
             except KeyError:
                 pass
 
-        # Reconstruct image SXP 
-        # TODO: get rid of SXP altogether from here
-        sxp_image = ['linux']
-        if xenapi_vm['kernel_kernel']:
-            sxp_image.append(['kernel', xenapi_vm['kernel_kernel']])
-        if xenapi_vm['kernel_initrd']:
-            sxp_image.append(['ramdisk', xenapi_vm['kernel_initrd']])
-        if xenapi_vm['kernel_args']:
-            sxp_image.append(['args', xenapi_vm['kernel_args']])
-
-        cfg['image'] = prettyprintstring(sxp_image)
-
-        # make sure device structures are there.
-        if 'device' not in cfg:
-            cfg['device'] = {}
-        if 'vif_refs' not in cfg:
-            cfg['vif_refs'] = []
-        if 'vbd_refs' not in cfg:
-            cfg['vbd_refs'] = []
-        if 'vtpm_refs' not in cfg:
-            cfg['vtpm_refs'] = []
-
-        return cfg
-
-
-    def _sync_xen_api_from_legacy_api(self):
-        """ Sync all the attributes that is supported by the Xen API
-        from the legacy API configuration.
+        # Convert Legacy "image" config to Xen API kernel_*
+        # configuration
+        image_sxp = sxp.child_value(sxp_cfg, 'image', [])
+        if image_sxp:
+            self['kernel_kernel'] = sxp.child_value(image_sxp, 'kernel','')
+            self['kernel_initrd'] = sxp.child_value(image_sxp, 'ramdisk','')
+            kernel_args = sxp.child_value(image_sxp, 'args', '')
+
+            # attempt to extract extra arguments from SXP config
+            arg_ip = sxp.child_value(image_sxp, 'ip')
+            if arg_ip and not re.search(r'ip=[0-9\.]+', kernel_args):
+                kernel_args += ' ip=%s' % arg_ip
+            arg_root = sxp.child_value(image_sxp, 'root')
+            if arg_root and not re.search(r'root=[^ ]+', kernel_args):
+                kernel_args += ' root=%s' % arg_root
+            
+            self['kernel_args'] = kernel_args
+
+        # Convert Legacy HVM parameters to Xen API configuration
+        self['platform_std_vga'] = cfg.get('std-vga', 0)
+        self['platform_serial'] = cfg.get('serial', '')
+        self['platform_localtime'] = cfg.get('localtime', 0)
+        self['platform_enable_audio'] = cfg.get('soundhw', 0)
+
+        # Convert path to bootloader to boot_method
+        if not cfg.get('bootloader'):
+            if self.get('kernel_kernel','').endswith('hvmloader'):
+                self['boot_method'] = 'bios'
+            else:
+                self['boot_method'] = 'kernel_external'
+        else:
+            self['boot_method'] = 'grub'
+
+        # make sure a sane maximum is set
+        if self['memory_static_max'] <= 0:
+            self['memory_static_max'] = self['memory_static_min']
+            
+        self['memory_dynamic_max'] = self['memory_static_max']
+        self['memory_dynamic_min'] = self['memory_static_min']
+
+        # set device references in the configuration
+        self['devices'] = cfg.get('devices', {})
+        
+        self['vif_refs'] = []
+        self['vbd_refs'] = []
+        self['vtpm_refs'] = []
+        for dev_uuid, (dev_type, dev_info) in self['devices'].items():
+            if dev_type == 'vif':
+                self['vif_refs'].append(dev_uuid)
+            elif dev_type in ('vbd','tap'):
+                self['vbd_refs'].append(dev_uuid)
+            elif dev_type in ('vtpm',):
+                self['vtpm_refs'].append(dev_uuid)
+        
+
+    def _sxp_to_xapi_unsupported(self, sxp_cfg):
+        """Read in an SXP configuration object and populate
+        values are that not related directly supported in
+        the Xen API.
         """
-        for cfgkey, apikey in LEGACY_CFG_TO_XENAPI_CFG.items():        
-            if cfgkey in self:
-                self.xenapi[apikey] = self[cfgkey]
-
-    def _sync_legacy_api_from_xen_api(self):
-        for cfgkey, apikey in LEGACY_CFG_TO_XENAPI_CFG.items():
-            if apikey in self.xenapi:
-                self[cfgkey] = self.xenapi[apikey]
-
-
-    def _populate_from_xml(self, parsed_xml):
-        raise NotImplementedError
-
-    def _populate_from_python_config(self, parsed_py):
-        raise NotImplementedError
+
+        # Parse and convert parameters used to configure
+        # the image (as well as HVM images)
+        image_sxp = sxp.child_value(sxp_cfg, 'image', [])
+        if image_sxp:
+            image = {}
+            image['type'] = sxp.name(image_sxp)
+            for arg, conv in LEGACY_IMAGE_CFG:
+                val = sxp.child_value(image_sxp, arg, None)
+                if val != None:
+                    image[arg] = conv(val)
+
+            image_hvm = {}
+            for arg, conv in LEGACY_IMAGE_HVM_CFG:
+                val = sxp.child_value(image_sxp, arg, None)
+                if val != None:
+                    image_hvm[arg] = conv(val)
+                    
+            image_hvm_devices = {}
+            for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
+                val = sxp.child_value(image_sxp, arg, None)
+                if val != None:
+                    image_hvm_devices[arg] = conv(val)
+
+            if image_hvm or image_hvm_devices:
+                image['hvm'] = image_hvm
+                image['hvm']['devices'] = image_hvm_devices
+
+            self['image'] = image
+
+            for apikey, imgkey in XENAPI_HVM_CFG.items():
+                val = sxp.child(image_sxp, imgkey, None)
+                if val != None:
+                    self[apikey] = val
+
+        # extract backend value
+                    
+        backend = []
+        for c in sxp.children(sxp_cfg, 'backend'):
+            backend.append(sxp.name(sxp.child0(c)))
+        if backend:
+            self['backend'] = backend
+
+        if self['image'].has_key('hvm'):
+            self['builder'] = 'hvm'
+            
+        # Parse and convert other Non Xen API parameters.
+        def _set_cfg_if_exists(sxp_arg):
+            val = sxp.child_value(sxp_cfg, sxp_arg)
+            if val != None:
+                if LEGACY_CFG_TYPES.get(sxp_arg):
+                    self[sxp_arg] = LEGACY_CFG_TYPES[sxp_arg](val)
+                else:
+                    self[sxp_arg] = val
+
+        _set_cfg_if_exists('shadow_memory')
+        _set_cfg_if_exists('security')
+        _set_cfg_if_exists('features')
+        _set_cfg_if_exists('on_xend_stop')
+        _set_cfg_if_exists('on_xend_start')
+        _set_cfg_if_exists('vcpu_avail')
+        _set_cfg_if_exists('max_vcpu_id') # TODO, deprecated?
+        
+        # Parse and store runtime configuration 
+        _set_cfg_if_exists('start_time')
+        _set_cfg_if_exists('online_vcpus')
+        _set_cfg_if_exists('cpu_time')
+        _set_cfg_if_exists('shutdown_reason')
+        _set_cfg_if_exists('up_time')
+        _set_cfg_if_exists('status') # TODO, deprecated  
+
+    def _add_xapi_unsupported(self):
+        """Updates the configuration object with entries that are not
+        officially supported by the Xen API but is required for
+        the rest of Xend to function.
+        """
+        pass
 
     def _get_old_state_string(self):
+        """Returns the old xm state string.
+        @rtype: string
+        @return: old state string
+        """
         state_string = ''
         for state_name in CONFIG_OLD_DOM_STATES:
             on_off = self.get(state_name, 0)
@@ -669,8 +682,24 @@ class XendConfig(dict):
 
         return state_string
 
-    def get_sxp(self, domain = None, ignore_devices = False, ignore = []):
+
+    def update_config(self, dominfo):
+        """Update configuration with the output from xc.domain_getinfo().
+
+        @param dominfo: Domain information via xc.domain_getinfo()
+        @type dominfo: dict
+        """
+        self._dominfo_to_xapi(dominfo)
+        self.validate()
+
+    def to_xml(self):
+        """Return an XML string representing the configuration."""
+        pass
+
+    def to_sxp(self, domain = None, ignore_devices = False, ignore = []):
         """ Get SXP representation of this config object.
+
+        Incompat: removed store_mfn, console_mfn
 
         @keyword domain: (optional) XendDomainInfo to get extra information
                          from such as domid and running devices.
@@ -688,44 +717,32 @@ class XendConfig(dict):
         if domain.getDomid() is not None:
             sxpr.append(['domid', domain.getDomid()])
 
-        for cfg, typefunc in ROUNDTRIPPING_CONFIG_ENTRIES:
-            if cfg in self:
-                if self[cfg] is not None:
-                    sxpr.append([cfg, self[cfg]])
-
-        if 'image' in self and self['image'] is not None:
-            sxpr.append(['image', self['image']])
-        if 'security' in self and self['security']:
-            sxpr.append(['security', self['security']])
-        if 'shutdown_reason' in self:
-            sxpr.append(['shutdown_reason', self['shutdown_reason']])
-        if 'cpu_time' in self:
-            sxpr.append(['cpu_time', self['cpu_time']/1e9])
-
-        sxpr.append(['online_vcpus', self['online_vcpus']])
-
-        if 'start_time' in self:
-            uptime = time.time() - self['start_time']
-            sxpr.append(['up_time', str(uptime)])
-            sxpr.append(['start_time', str(self['start_time'])])
-
-        if domain:
-            sxpr.append(['status', str(domain.state)])
-        else:
-            sxpr.append(['status', str(DOM_STATE_HALTED)])
+        for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items():
+            if self.has_key(xenapi) and self[xenapi] not in (None, []):
+                sxpr.append([legacy, self[xenapi]])
+
+        for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
+            if legacy in ('domid', 'uuid'): # skip these
+                continue
+            if self.has_key(legacy) and self[legacy] not in (None, []):
+                sxpr.append([legacy, self[legacy]])
+
+        if 'image' in self and self['image']:
+            sxpr.append(['image', self.image_sxpr()])
+
+        sxpr.append(['status', domain.state])
+        sxpr.append(['memory_dynamic_min',  self.get('memory_dynamic_min')])
+        sxpr.append(['memory_dynamic_max',  self.get('memory_dynamic_max')])
 
         if domain.getDomid() is not None:
             sxpr.append(['state', self._get_old_state_string()])
 
-        sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max',
-                                                    self['memory'])])
-
-        # For save/restore migration
         if domain:
             if domain.store_mfn:
                 sxpr.append(['store_mfn', domain.store_mfn])
             if domain.console_mfn:
                 sxpr.append(['console_mfn', domain.console_mfn])
+
 
         # Marshall devices (running or from configuration)
         if not ignore_devices:
@@ -743,7 +760,7 @@ class XendConfig(dict):
                     except:
                         log.exception("dumping sxp from device controllers")
                         pass
-                        
+                    
                 # if we didn't find that device, check the existing config
                 # for a device in the same class
                 if not found:
@@ -751,58 +768,28 @@ class XendConfig(dict):
                         if dev_type == cls:
                             sxpr.append(['device', dev_info])
 
-        return sxpr
-
-    def validate(self):
-        """ Validate the configuration and fill in missing configuration
-        with defaults.
+        return sxpr    
+    
+    def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None):
+        """Add a device configuration in SXP format or XenAPI struct format.
+
+        For SXP, it could be either:
+
+        [device, [vbd, [uname ...]]
+
+        or:
+
+        [vbd, [uname ..]]
+
+        @type cfg_sxp: list of lists (parsed sxp object)
+        @param cfg_sxp: SXP configuration object
+        @type cfg_xenapi: dict
+        @param cfg_xenapi: A device configuration from Xen API (eg. vbd,vif)
+        @rtype: string
+        @return: Assigned UUID of the device.
         """
-
-        # Fill in default values
-        for key, default_func in DEFAULT_CONFIGURATION:
-            if key not in self or self[key] == None:
-                self[key] = default_func(self)
-
-        # Basic sanity checks
-        if 'image' in self and isinstance(self['image'], str):
-            self['image'] = sxp.from_string(self['image'])
-        if 'security' in self and isinstance(self['security'], str):
-            self['security'] = sxp.from_string(self['security'])
-        if self['memory'] == 0 and 'mem_kb' in self:
-            self['memory'] = (self['mem_kb'] + 1023)/1024
-        if self['memory'] <= 0:
-            raise XendConfigError('Invalid memory size: %s' %
-                                  str(self['memory']))
-
-        self['maxmem'] = max(self['memory'], self['maxmem'])
-
-        # convert mem_kb from domain_getinfo to something more descriptive
-        if 'mem_kb' in self:
-            self['memory_dynamic_max'] = (self['mem_kb'] + 1023)/1024
-
-        # Verify devices
-        for d_uuid, (d_type, d_info) in self['device'].items():
-            if d_type not in XendDevices.valid_devices() and \
-               d_type not in XendDevices.pseudo_devices():
-                raise XendConfigError('Invalid device (%s)' % d_type)
-
-        # Verify restart modes
-        for event in ('on_poweroff', 'on_reboot', 'on_crash'):
-            if self[event] not in CONFIG_RESTART_MODES:
-                raise XendConfigError('Invalid restart event: %s = %s' % \
-                                      (event, str(self[event])))
-
-        # Verify that {vif,vbd}_refs are here too
-        if 'vif_refs' not in self:
-            self['vif_refs'] = []
-        if 'vbd_refs' not in self:
-            self['vbd_refs'] = []
-        if 'vtpm_refs' not in self:
-            self['vtpm_refs'] = []
-
-    def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None):
         if dev_type not in XendDevices.valid_devices() and \
-           dev_type not in XendDevices.pseudo_devices():
+           dev_type not in XendDevices.pseudo_devices():        
             raise XendConfigError("XendConfig: %s not a valid device type" %
                             dev_type)
 
@@ -816,22 +803,48 @@ class XendConfig(dict):
             log.debug("XendConfig.device_add: %s" % str(cfg_xenapi))
 
         if cfg_sxp:
+            if sxp.child0(cfg_sxp) == 'device':
+                config = sxp.child0(cfg_sxp)
+            else:
+                config = cfg_sxp
+
+            dev_type = sxp.name(config)
             dev_info = {}
 
             try:
-                for opt, val in cfg_sxp[1:]:
+                for opt, val in config[1:]:
                     dev_info[opt] = val
             except ValueError:
                 pass # SXP has no options for this device
 
+            
+            def _get_config_ipaddr(config):
+                val = []
+                for ipaddr in sxp.children(config, elt='ip'):
+                    val.append(sxp.child0(ipaddr))
+                return val
+
+            if dev_type == 'vif' and 'ip' in dev_info:
+                dev_info['ip'] = _get_config_ipaddr(config)
+
+            if dev_type == 'vbd':
+                if dev_info.get('dev', '').startswith('ioemu:'):
+                    dev_info['driver'] = 'ioemu'
+                else:
+                    dev_info['driver'] = 'paravirtualised'
+                    
+
             # create uuid if it doesn't exist
             dev_uuid = dev_info.get('uuid', uuid.createString())
             dev_info['uuid'] = dev_uuid
-            self['device'][dev_uuid] = (dev_type, dev_info)
-            if dev_type in ('vif', 'vbd'):
+
+            # store dev references by uuid for certain device types
+            self['devices'][dev_uuid] = (dev_type, dev_info)
+            if dev_type in ('vif', 'vbd', 'vtpm'):
                 self['%s_refs' % dev_type].append(dev_uuid)
             elif dev_type in ('tap',):
                 self['vbd_refs'].append(dev_uuid)
+
             return dev_uuid
 
         if cfg_xenapi:
@@ -849,13 +862,20 @@ class XendConfig(dict):
                 
                 dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
                 dev_info['uuid'] = dev_uuid
-                self['device'][dev_uuid] = (dev_type, dev_info)
+                self['devices'][dev_uuid] = (dev_type, dev_info)
                 self['vif_refs'].append(dev_uuid)
                 return dev_uuid
             
-            elif dev_type == 'vbd':
-                dev_info['uname'] = cfg_xenapi.get('image', None)
-                dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device')
+            elif dev_type in ('vbd', 'tap'):
+                if dev_type == 'vbd':
+                    dev_info['uname'] = cfg_xenapi.get('image', None)
+                    dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device')
+                elif dev_type == 'tap':
+                    dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image')
+                    dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device')
+                    
+                dev_info['driver'] = cfg_xenapi.get('driver')
+                    
                 if cfg_xenapi.get('mode') == 'RW':
                     dev_info['mode'] = 'w'
                 else:
@@ -863,35 +883,33 @@ class XendConfig(dict):
 
                 dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
                 dev_info['uuid'] = dev_uuid
-                self['device'][dev_uuid] = (dev_type, dev_info)
+                self['devices'][dev_uuid] = (dev_type, dev_info)
                 self['vbd_refs'].append(dev_uuid)                
                 return dev_uuid
-
-            elif dev_type == 'vtpm':
-                if cfg_xenapi.get('type'):
-                    dev_info['type'] = cfg_xenapi.get('type')
-                dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
-                dev_info['uuid'] = dev_uuid
-                self['device'][dev_uuid] = (dev_type, dev_info)
-                self['vtpm_refs'].append(dev_uuid)
-                return dev_uuid
-
-            elif dev_type == 'tap':
-                dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image')
-                dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device')
-                
-                if cfg_xenapi.get('mode') == 'RW':
-                    dev_info['mode'] = 'w'
-                else:
-                    dev_info['mode'] = 'r'
-
-                dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
-                dev_info['uuid'] = dev_uuid
-                self['device'][dev_uuid] = (dev_type, dev_info)
-                self['vbd_refs'].append(dev_uuid)                
-                return dev_uuid                
-                
+            
         return ''
+
+    def device_update(self, dev_uuid, cfg_sxp):
+        """Update an existing device with the new configuration.
+
+        @rtype: boolean
+        @return: Returns True if succesfully found and updated a device conf
+        """
+        if dev_uuid in self['devices']:
+            config = sxp.child0(cfg_sxp)
+            dev_type = sxp.name(config)
+            dev_info = {}
+
+            try:
+                for opt, val in config[1:]:
+                    self['devices'][opt] = val
+            except ValueError:
+                pass # SXP has no options for this device
+            
+            return True
+
+        return False
+
 
     def device_sxpr(self, dev_uuid = None, dev_type = None, dev_info = None):
         """Get Device SXPR by either giving the device UUID or (type, config).
@@ -900,8 +918,8 @@ class XendConfig(dict):
         @return: device config sxpr
         """
         sxpr = []
-        if dev_uuid != None and dev_uuid in self['device']:
-            dev_type, dev_info = self['device'][dev_uuid]
+        if dev_uuid != None and dev_uuid in self['devices']:
+            dev_type, dev_info = self['devices'][dev_uuid]
 
         if dev_type == None or dev_info == None:
             raise XendConfigError("Required either UUID or device type and "
@@ -917,27 +935,102 @@ class XendConfig(dict):
         """Returns the SXPR for all devices in the current configuration."""
         sxprs = []
         pci_devs = []
-        for dev_type, dev_info in self['device'].values():
+
+        if 'devices' in self:
+            return sxprs
+        
+        for dev_type, dev_info in self['devices'].values():
             if dev_type == 'pci': # special case for pci devices
-                pci_devs.append(dev_info)
+                sxpr = [['uuid', dev_info['uuid']]]
+                for pci_dev_info in dev_info['devs']:
+                    pci_dev_sxpr = ['dev']
+                    for opt, val in pci_dev_info.items():
+                        pci_dev_sxpr.append([opt, val])
+                    sxpr.append(pci_dev_sxpr)
+                sxprs.append((dev_type, sxpr))
             else:
                 sxpr = self.device_sxpr(dev_type = dev_type,
                                         dev_info = dev_info)
                 sxprs.append((dev_type, sxpr))
 
-        # if we have any pci_devs, we parse them differently into
-        # one single pci SXP entry.
-        if pci_devs:
-            sxpr = ['pci',]
-            for dev_info in pci_devs:
-                dev_sxpr = self.device_sxpr(dev_type = 'dev',
-                                            dev_info = dev_info)
-                sxpr.append(dev_sxpr)
-            sxprs.append(('pci', sxpr))
-            
         return sxprs
 
-                     
+    def image_sxpr(self):
+        """Returns a backwards compatible image SXP expression that is
+        used in xenstore's /vm/<uuid>/image value and xm list."""
+        image = [self['image'].get('type', 'linux')]
+        if self.has_key('kernel_kernel'):
+            image.append(['kernel', self['kernel_kernel']])
+        if self.has_key('kernel_initrd') and self['kernel_initrd']:
+            image.append(['ramdisk', self['kernel_initrd']])
+        if self.has_key('kernel_args') and self['kernel_args']:
+            image.append(['args', self['kernel_args']])
+
+        for arg, conv in LEGACY_IMAGE_CFG:
+            if self['image'].has_key(arg):
+                image.append([arg, self['image'][arg]])
+
+        if 'hvm' in self['image']:
+            for arg, conv in LEGACY_IMAGE_HVM_CFG:
+                if self['image']['hvm'].has_key(arg):
+                    image.append([arg, self['image']['hvm'][arg]])
+
+        if 'hvm' in self['image'] and 'devices' in self['image']['hvm']:
+            for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
+                if self['image']['hvm']['devices'].has_key(arg):
+                    image.append([arg,
+                                  self['image']['hvm']['devices'][arg]])
+
+        return image
+
+    def update_with_image_sxp(self, image_sxp):
+        # Convert Legacy "image" config to Xen API kernel_*
+        # configuration
+        self['kernel_kernel'] = sxp.child_value(image_sxp, 'kernel','')
+        self['kernel_initrd'] = sxp.child_value(image_sxp, 'ramdisk','')
+        kernel_args = sxp.child_value(image_sxp, 'args', '')
+        
+        # attempt to extract extra arguments from SXP config
+        arg_ip = sxp.child_value(image_sxp, 'ip')
+        if arg_ip and not re.search(r'ip=[0-9\.]', kernel_args):
+            kernel_args += ' ip=%s' % arg_ip
+        arg_root = sxp.child_value(image_sxp, 'root')
+        if arg_root and not re.search(r'root=', kernel_args):
+            kernel_args += ' root=%s' % arg_root
+        self['kernel_args'] = kernel_args
+
+        # Store image SXP in python dictionary format
+        image = {}
+        image['type'] = sxp.name(image_sxp)
+        for arg, conv in LEGACY_IMAGE_CFG:
+            val = sxp.child_value(image_sxp, arg, None)
+            if val != None:
+                image[arg] = conv(val)
+
+        image_hvm = {}
+        for arg, conv in LEGACY_IMAGE_HVM_CFG:
+            val = sxp.child_value(image_sxp, arg, None)
+            if val != None:
+                image_hvm[arg] = conv(val)
+                    
+        image_hvm_devices = {}
+        for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
+            val = sxp.child_value(image_sxp, arg, None)
+            if val != None:
+                image_hvm_devices[arg] = conv(val)
+
+        if image_hvm or image_hvm_devices:
+            image['hvm'] = image_hvm
+            image['hvm']['devices'] = image_hvm_devices
+
+        self['image'] = image
+
+        for apikey, imgkey in XENAPI_HVM_CFG.items():
+            val = sxp.child(image_sxp, imgkey, None)
+            if val != None:
+                self[apikey] = val        
+
+        
 #
 # debugging 
 #
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/XendDomain.py       Thu Nov 30 14:44:58 2006 +0000
@@ -433,6 +433,11 @@ class XendDomain:
         """
         log.debug("Adding Domain: %s" % info.getDomid())
         self.domains[info.getDomid()] = info
+        
+        # update the managed domains with a new XendDomainInfo object
+        # if we are keeping track of it.
+        if info.get_uuid() in self.managed_domains:
+            self._managed_domain_register(info)
 
     def _remove_domain(self, info, domid = None):
         """Remove the domain from the list of running domains
@@ -669,7 +674,7 @@ class XendDomain:
         self.domains_lock.acquire()
         try:
             try:
-                xeninfo = XendConfig(xenapi_vm = xenapi_vm)
+                xeninfo = XendConfig(xapi = xenapi_vm)
                 dominfo = XendDomainInfo.createDormant(xeninfo)
                 log.debug("Creating new managed domain: %s: %s" %
                           (dominfo.getName(), dominfo.get_uuid()))
@@ -873,8 +878,8 @@ class XendDomain:
         self.domains_lock.acquire()
         try:
             try:
-                xeninfo = XendConfig(sxp = config)
-                dominfo = XendDomainInfo.createDormant(xeninfo)
+                domconfig = XendConfig(sxp_obj = config)
+                dominfo = XendDomainInfo.createDormant(domconfig)
                 log.debug("Creating new managed domain: %s" %
                           dominfo.getName())
                 self._managed_domain_register(dominfo)
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Nov 30 14:44:58 2006 +0000
@@ -38,10 +38,9 @@ from xen.util import security
 from xen.util import security
 
 from xen.xend import balloon, sxp, uuid, image, arch
-from xen.xend import XendRoot, XendNode
+from xen.xend import XendRoot, XendNode, XendConfig
 
 from xen.xend.XendBootloader import bootloader
-from xen.xend.XendConfig import XendConfig
 from xen.xend.XendError import XendError, VmError
 from xen.xend.XendDevices import XendDevices
 from xen.xend.xenstore.xstransact import xstransact, complete
@@ -145,7 +144,7 @@ def create(config):
     """
 
     log.debug("XendDomainInfo.create(%s)", config)
-    vm = XendDomainInfo(XendConfig(sxp = config))
+    vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config))
     try:
         vm.start()
     except:
@@ -175,10 +174,9 @@ def recreate(info, priv):
 
     assert not info['dying']
 
-    xeninfo = XendConfig(cfg = info)
+    xeninfo = XendConfig.XendConfig(dominfo = info)
     domid = xeninfo['domid']
-    uuid1 = xeninfo['handle']
-    xeninfo['uuid'] = uuid.toString(uuid1)
+    uuid1 = uuid.fromString(xeninfo['uuid'])
     needs_reinitialising = False
     
     dompath = GetDomainPath(domid)
@@ -236,7 +234,7 @@ def restore(config):
 def restore(config):
     """Create a domain and a VM object to do a restore.
 
-    @param config: Domain configuration object
+    @param config: Domain SXP configuration
     @type  config: list of lists. (see C{create})
 
     @rtype:  XendDomainInfo
@@ -246,7 +244,8 @@ def restore(config):
     """
 
     log.debug("XendDomainInfo.restore(%s)", config)
-    vm = XendDomainInfo(XendConfig(sxp = config), resume = True)
+    vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config),
+                        resume = True)
     try:
         vm.resume()
         return vm
@@ -254,24 +253,24 @@ def restore(config):
         vm.destroy()
         raise
 
-def createDormant(xeninfo):
+def createDormant(domconfig):
     """Create a dormant/inactive XenDomainInfo without creating VM.
     This is for creating instances of persistent domains that are not
     yet start.
 
-    @param xeninfo: Parsed configuration
-    @type  xeninfo: dictionary
+    @param domconfig: Parsed configuration
+    @type  domconfig: XendConfig object
     
     @rtype:  XendDomainInfo
     @return: A up and running XendDomainInfo instance
     @raise XendError: Errors with configuration.    
     """
     
-    log.debug("XendDomainInfo.createDormant(%s)", xeninfo)
+    log.debug("XendDomainInfo.createDormant(%s)", domconfig)
     
     # domid does not make sense for non-running domains.
-    xeninfo.pop('domid', None)
-    vm = XendDomainInfo(XendConfig(cfg = xeninfo))
+    domconfig.pop('domid', None)
+    vm = XendDomainInfo(domconfig)
     return vm    
 
 def domain_by_name(name):
@@ -383,14 +382,6 @@ class XendDomainInfo:
         #if not self._infoIsSet('uuid'):
         #    self.info['uuid'] = uuid.toString(uuid.create())
 
-        #REMOVE: domid logic can be shortened 
-        #if domid is not None:
-        #    self.domid = domid
-        #elif info.has_key('dom'):
-        #    self.domid = int(info['dom'])
-        #else:
-        #    self.domid = None
-
         self.vmpath  = XS_VMROOT + self.info['uuid']
         self.dompath = dompath
 
@@ -403,6 +394,7 @@ class XendDomainInfo:
         self.vmWatch = None
         self.shutdownWatch = None
         self.shutdownStartTime = None
+        self._resume = resume
 
         self.state = DOM_STATE_HALTED
         self.state_updated = threading.Condition()
@@ -416,8 +408,7 @@ class XendDomainInfo:
         if augment:
             self._augmentInfo(priv)
 
-        self._checkName(self.info['name'])
-        self.setResume(resume)
+        self._checkName(self.info['name_label'])
             
 
     #
@@ -477,7 +468,7 @@ class XendDomainInfo:
         if self.domid == 0:
             raise XendError('Domain 0 cannot be shutdown')
         
-        if not reason in DOMAIN_SHUTDOWN_REASONS.values():
+        if reason not in DOMAIN_SHUTDOWN_REASONS.values():
             raise XendError('Invalid reason: %s' % reason)
         self._storeDom("control/shutdown", reason)
                 
@@ -512,12 +503,14 @@ class XendDomainInfo:
         """Create a new device.
 
         @param dev_config: device configuration
-        @type  dev_config: dictionary (parsed config)
+        @type  dev_config: SXP object (parsed config)
         """
         log.debug("XendDomainInfo.device_create: %s" % dev_config)
         dev_type = sxp.name(dev_config)
-        devid = self._createDevice(dev_type, dev_config)
-        self.info.device_add(dev_type, cfg_sxp = dev_config)        
+        dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config)
+        dev_config_dict = self.info['devices'][dev_uuid][1]
+        log.debug("XendDomainInfo.device_create: %s" % dev_config_dict)
+        devid = self._createDevice(dev_type, dev_config_dict)
         self._waitForDevice(dev_type, devid)
         return self.getDeviceController(dev_type).sxpr(devid)
 
@@ -525,12 +518,26 @@ class XendDomainInfo:
         """Configure an existing device.
         
         @param dev_config: device configuration
-        @type  dev_config: dictionary (parsed config)
+        @type  dev_config: SXP object (parsed config)
         @param devid:      device id
         @type  devid:      int
+        @return: Returns True if successfully updated device
+        @rtype: boolean
         """
         deviceClass = sxp.name(dev_config)
-        self._reconfigureDevice(deviceClass, devid, dev_config)
+        
+        # look up uuid of the device
+        dev_control =  self.getDeviceController(deviceClass)
+        dev_sxpr = dev_control.sxpr(devid)
+        dev_uuid = sxp.child_value(sxpr, 'uuid')
+        if not dev_uuid:
+            return False
+
+        self.info.device_update(dev_uuid, dev_config)
+        dev_config_dict = self.info['devices'].get(dev_uuid)
+        if dev_config_dict:
+            dev_control.reconfigureDevice(devid, dev_config_dict[1])
+        return True
 
     def waitForDevices(self):
         """Wait for this domain's configured devices to connect.
@@ -567,12 +574,12 @@ class XendDomainInfo:
         @param target: In MiB.
         """
         log.debug("Setting memory target of domain %s (%d) to %d MiB.",
-                  self.info['name'], self.domid, target)
+                  self.info['name_label'], self.domid, target)
         
         if target <= 0:
             raise XendError('Invalid memory size')
         
-        self.info['memory'] = target
+        self.info['memory_static_min'] = target
         self.storeVm("memory", target)
         self._storeDom("memory/target", target << 10)
 
@@ -581,8 +588,8 @@ class XendDomainInfo:
             # We include the domain name and ID, to help xm.
             sxpr = ['domain',
                     ['domid',      self.domid],
-                    ['name',       self.info['name']],
-                    ['vcpu_count', self.info['online_vcpus']]]
+                    ['name',       self.info['name_label']],
+                    ['vcpu_count', self.info['vcpus_number']]]
 
             for i in range(0, self.info['max_vcpu_id']+1):
                 info = xc.vcpu_getinfo(self.domid, i)
@@ -610,30 +617,40 @@ class XendDomainInfo:
         values taken from the store.  This recovers those values known
         to xend but not to the hypervisor.
         """
-        def useIfNeeded(name, val):
-            if not self._infoIsSet(name) and val is not None:
-                self.info[name] = val
-
+        augment_entries = XendConfig.LEGACY_XENSTORE_VM_PARAMS[:]
         if priv:
-            entries = VM_STORE_ENTRIES[:]
-            entries.remove(('memory', int))
-            entries.remove(('maxmem', int))
-        else:
-            entries = VM_STORE_ENTRIES
-        entries.append(('image', str))
-        entries.append(('security', str))
-
-        map(lambda x, y: useIfNeeded(x[0], y), entries,
-            self._readVMDetails(entries))
-
+            augment_entries.remove('memory')
+            augment_entries.remove('maxmem')
+
+        vm_config = self._readVMDetails([(k, XendConfig.LEGACY_CFG_TYPES[k])
+                                         for k in augment_entries])
+        
+        # make returned lists into a dictionary
+        vm_config = dict(zip(augment_entries, vm_config))
+        
+        for arg in augment_entries:
+            xapicfg = arg
+            val = vm_config[arg]
+            if val != None:
+                if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
+                    xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
+                    self.info[xapiarg] = val
+                else:
+                    self.info[arg] = val
+
+        # read image value
+        image_sxp = self._readVm('image')
+        if image_sxp:
+            self.info.update_with_image_sxp(sxp.from_string(image_sxp))
+
+        # read devices
         devices = []
-
         for devclass in XendDevices.valid_devices():
             devconfig = self.getDeviceController(devclass).configurations()
             if devconfig:
                 devices.extend(map(lambda conf: (devclass, conf), devconfig))
 
-        if not self.info['device'] and devices is not None:
+        if not self.info['devices'] and devices is not None:
             for device in devices:
                 self.info.device_add(device[0], cfg_sxp = device)
 
@@ -678,16 +695,16 @@ class XendDomainInfo:
     def _recreateDomFunc(self, t):
         t.remove()
         t.mkdir()
-        t.set_permissions({ 'dom' : self.domid })
+        t.set_permissions({'dom' : self.domid})
         t.write('vm', self.vmpath)
 
     def _storeDomDetails(self):
         to_store = {
             'domid':              str(self.domid),
             'vm':                 self.vmpath,
-            'name':               self.info['name'],
+            'name':               self.info['name_label'],
             'console/limit':      str(xroot.get_console_limit() * 1024),
-            'memory/target':      str(self.info['memory'] * 1024)
+            'memory/target':      str(self.info['memory_static_min'] * 1024)
             }
 
         def f(n, v):
@@ -713,7 +730,7 @@ class XendDomainInfo:
                 return 'offline'
 
         result = {}
-        for v in range(0, self.info['vcpus']):
+        for v in range(0, self.info['vcpus_number']):
             result["cpu/%d/availability" % v] = availability(v)
         return result
 
@@ -735,19 +752,29 @@ class XendDomainInfo:
         log.trace("XendDomainInfo.storeChanged");
 
         changed = False
-        
-        def f(x, y):
-            if y is not None and self.info[x[0]] != y:
-                self.info[x[0]] = y
-                changed = True
-
-        map(f, VM_CONFIG_PARAMS, self._readVMDetails(VM_CONFIG_PARAMS))
-
-        im = self._readVm('image')
-        current_im = self.info['image']
-        if (im is not None and
-            (current_im is None or sxp.to_string(current_im) != im)):
-            self.info['image'] = sxp.from_string(im)
+
+        # Check whether values in the configuration have
+        # changed in Xenstore.
+        
+        cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash']
+        
+        vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k])
+                                           for k in cfg_vm])
+
+        # convert two lists into a python dictionary
+        vm_details = dict(zip(cfg_vm, vm_details))
+        
+        for arg, val in vm_details.items():
+            if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
+                xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
+                if val != None and val != self.info[xapiarg]:
+                    self.info[xapiarg] = val
+                    changed= True
+
+        # Check whether image definition has been updated
+        image_sxp = self._readVm('image')
+        if image_sxp and image_sxp != self.info.image_sxpr():
+            self.info.update_with_image_sxp(sxp.from_string(image_sxp))
             changed = True
 
         if changed:
@@ -791,11 +818,11 @@ class XendDomainInfo:
 
     def setName(self, name):
         self._checkName(name)
-        self.info['name'] = name
+        self.info['name_label'] = name
         self.storeVm("name", name)
 
     def getName(self):
-        return self.info['name']
+        return self.info['name_label']
 
     def getDomainPath(self):
         return self.dompath
@@ -816,7 +843,7 @@ class XendDomainInfo:
         return self.info['features']
 
     def getVCpuCount(self):
-        return self.info['vcpus']
+        return self.info['vcpus_number']
 
     def setVCpuCount(self, vcpus):
         self.info['vcpu_avail'] = (1 << vcpus) - 1
@@ -828,19 +855,19 @@ class XendDomainInfo:
 
     def getMemoryTarget(self):
         """Get this domain's target memory size, in KB."""
-        return self.info['memory'] * 1024
+        return self.info['memory_static_min'] * 1024
 
     def getResume(self):
-        return "%s" % self.info['resume']
+        return str(self._resume)
 
     def getCap(self):
-        return self.info['cpu_cap']
+        return self.info.get('cpu_cap', 0)
 
     def getWeight(self):
         return self.info['cpu_weight']
 
     def setResume(self, state):
-        self.info['resume'] = state
+        self._resume = state
 
     def getRestartCount(self):
         return self._readVm('xend/restart_count')
@@ -891,7 +918,7 @@ class XendDomainInfo:
                     return
 
                 log.warn('Domain has crashed: name=%s id=%d.',
-                         self.info['name'], self.domid)
+                         self.info['name_label'], self.domid)
 
                 if xroot.get_enable_dump():
                     self.dumpCore()
@@ -910,7 +937,7 @@ class XendDomainInfo:
                     reason = shutdown_reason(xeninfo['shutdown_reason'])
 
                     log.info('Domain has shutdown: name=%s id=%d reason=%s.',
-                             self.info['name'], self.domid, reason)
+                             self.info['name_label'], self.domid, reason)
 
                     self._clearRestart()
 
@@ -945,7 +972,7 @@ class XendDomainInfo:
                     if timeout < 0:
                         log.info(
                             "Domain shutdown timeout expired: name=%s id=%s",
-                            self.info['name'], self.domid)
+                            self.info['name_label'], self.domid)
                         self.destroy()
         finally:
             self.refresh_shutdown_lock.release()
@@ -965,11 +992,23 @@ class XendDomainInfo:
     def _maybeRestart(self, reason):
         # Dispatch to the correct method based upon the configured on_{reason}
         # behaviour.
-        {"destroy"        : self.destroy,
-         "restart"        : self._restart,
-         "preserve"       : self._preserve,
-         "rename-restart" : self._renameRestart}[self.info['on_' + reason]]()
-
+        actions =  {"destroy"        : self.destroy,
+                    "restart"        : self._restart,
+                    "preserve"       : self._preserve,
+                    "rename-restart" : self._renameRestart}
+
+        action_conf = {
+            'poweroff': 'actions_after_shutdown',
+            'reboot': 'actions_after_reboot',
+            'crash': 'actions_after_crash',
+        }
+
+        action_target = self.info.get(action_conf.get(reason))
+        func = actions.get(action_target, None)
+        if func and callable(func):
+            func()
+        else:
+            self.destroy() # default to destroy
 
     def _renameRestart(self):
         self._restart(True)
@@ -1008,7 +1047,7 @@ class XendDomainInfo:
                 log.error(
                     'VM %s restarting too fast (%f seconds since the last '
                     'restart).  Refusing to restart to avoid loops.',
-                    self.info['name'], timeout)
+                    self.info['name_label'], timeout)
                 self.destroy()
                 return
 
@@ -1055,11 +1094,11 @@ class XendDomainInfo:
         new_uuid = uuid.createString()
         new_name = 'Domain-%s' % new_uuid
         log.info("Renaming dead domain %s (%d, %s) to %s (%s).",
-                 self.info['name'], self.domid, self.info['uuid'],
+                 self.info['name_label'], self.domid, self.info['uuid'],
                  new_name, new_uuid)
         self._unwatchVm()
         self._releaseDevices()
-        self.info['name'] = new_name
+        self.info['name_label'] = new_name
         self.info['uuid'] = new_uuid
         self.vmpath = XS_VMROOT + new_uuid
         self._storeVmDetails()
@@ -1067,7 +1106,7 @@ class XendDomainInfo:
 
 
     def _preserve(self):
-        log.info("Preserving dead domain %s (%d).", self.info['name'],
+        log.info("Preserving dead domain %s (%d).", self.info['name_label'],
                  self.domid)
         self._unwatchVm()
         self._storeDom('xend/shutdown_completed', 'True')
@@ -1084,7 +1123,7 @@ class XendDomainInfo:
             if not corefile:
                 this_time = time.strftime("%Y-%m%d-%H%M.%S", time.localtime())
                 corefile = "/var/xen/dump/%s-%s.%s.core" % (this_time,
-                                  self.info['name'], self.domid)
+                                  self.info['name_label'], self.domid)
                 
             if os.path.isdir(corefile):
                 raise XendError("Cannot dump core in a directory: %s" %
@@ -1095,7 +1134,7 @@ class XendDomainInfo:
             corefile_incomp = corefile+'-incomplete'
             os.rename(corefile, corefile_incomp)
             log.exception("XendDomainInfo.dumpCore failed: id = %s name = %s",
-                          self.domid, self.info['name'])
+                          self.domid, self.info['name_label'])
             raise XendError("Failed to dump core: %s" %  str(ex))
 
     #
@@ -1117,8 +1156,8 @@ class XendDomainInfo:
 
         @raise: VmError for invalid devices
         """
-        for (devclass, config) in self.info.all_devices_sxpr():
-            if devclass in XendDevices.valid_devices():
+        for (devclass, config) in self.info.get('devices', {}).values():
+            if devclass in XendDevices.valid_devices():            
                 log.info("createDevice: %s : %s" % (devclass, config))
                 self._createDevice(devclass, config)
 
@@ -1139,7 +1178,7 @@ class XendDomainInfo:
                         # there's nothing more we can do.
                         log.exception(
                            "Device release failed: %s; %s; %s",
-                           self.info['name'], devclass, dev)
+                           self.info['name_label'], devclass, dev)
             if t.commit():
                 break
 
@@ -1211,11 +1250,12 @@ class XendDomainInfo:
 
         log.debug('XendDomainInfo.constructDomain')
 
-        hvm = (self._infoIsSet('image') and
-               sxp.name(self.info['image']) == "hvm")
+        image_cfg = self.info.get('image', {})
+        hvm = image_cfg.has_key('hvm')
+
         if hvm:
             info = xc.xeninfo()
-            if not 'hvm' in info['xen_caps']:
+            if 'hvm' not in info['xen_caps']:
                 raise VmError("HVM guest support is unavailable: is VT/AMD-V "
                               "supported by your CPU and enabled in your "
                               "BIOS?")
@@ -1228,14 +1268,14 @@ class XendDomainInfo:
 
         if self.domid < 0:
             raise VmError('Creating domain failed: name=%s' %
-                          self.info['name'])
+                          self.info['name_label'])
 
         self.dompath = GetDomainPath(self.domid)
 
         self._recreateDom()
 
         # Set maximum number of vcpus in domain
-        xc.domain_max_vcpus(self.domid, int(self.info['vcpus']))
+        xc.domain_max_vcpus(self.domid, int(self.info['vcpus_number']))
 
 
     def _introduceDomain(self):
@@ -1256,7 +1296,7 @@ class XendDomainInfo:
 
         # if we have a boot loader but no image, then we need to set things
         # up by running the boot loader non-interactively
-        if self._infoIsSet('bootloader') and not self._infoIsSet('image'):
+        if self.info.get('bootloader') and self.info.get('image'):
             self._configureBootloader()
 
         if not self._infoIsSet('image'):
@@ -1264,8 +1304,9 @@ class XendDomainInfo:
 
         try:
             self.image = image.create(self,
+                                      self.info,
                                       self.info['image'],
-                                      self.info.all_devices_sxpr())
+                                      self.info['devices'])
 
             localtime = self.info.get('localtime', 0)
             if localtime is not None and localtime == 1:
@@ -1284,12 +1325,12 @@ class XendDomainInfo:
             # the various headrooms necessary, given the raw configured
             # values. maxmem, memory, and shadow are all in KiB.
             maxmem = self.image.getRequiredAvailableMemory(
-                self.info['maxmem'] * 1024)
+                self.info['memory_static_min'] * 1024)
             memory = self.image.getRequiredAvailableMemory(
-                self.info['memory'] * 1024)
+                self.info['memory_static_max'] * 1024)
             shadow = self.image.getRequiredShadowMemory(
                 self.info['shadow_memory'] * 1024,
-                self.info['maxmem'] * 1024)
+                self.info['memory_static_max'] * 1024)
 
             # Round shadow up to a multiple of a MiB, as shadow_mem_control
             # takes MiB and we must not round down and end up under-providing.
@@ -1317,7 +1358,7 @@ class XendDomainInfo:
 
             self._createDevices()
 
-            if self.info['bootloader'] not in [None, 'kernel_external']:
+            if self.info['bootloader']:
                 self.image.cleanupBootloading()
 
             self.info['start_time'] = time.time()
@@ -1325,7 +1366,7 @@ class XendDomainInfo:
             self._stateSet(DOM_STATE_RUNNING)
         except RuntimeError, exn:
             log.exception("XendDomainInfo.initDomain: exception occurred")
-            if self.info['bootloader'] not in [None, 'kernel_external'] \
+            if self.info['bootloader'] not in (None, 'kernel_external') \
                    and self.image is not None:
                 self.image.cleanupBootloading()
             raise VmError(str(exn))
@@ -1338,7 +1379,6 @@ class XendDomainInfo:
         self.refresh_shutdown_lock.acquire()
         try:
             self.unwatchShutdown()
-
             self._releaseDevices()
 
             if self.image:
@@ -1459,14 +1499,14 @@ class XendDomainInfo:
 
     def _configureBootloader(self):
         """Run the bootloader if we're configured to do so."""
-        if not self.info['bootloader']:
+        if not self.info.get('bootloader'):
             return
         blcfg = None
         # FIXME: this assumes that we want to use the first disk device
-        for (n, c) in self.info.all_devices_sxpr():
-            if not n or not c or not(n in ["vbd", "tap"]):
+        for devuuid, (devtype, devinfo) in self.info.all_devices_sxpr():
+            if not devtype or not devinfo or devtype not in ('vbd', 'tap'):
                 continue
-            disk = sxp.child_value(c, "uname")
+            disk = devinfo.get('uname')
             if disk is None:
                 continue
             fn = blkdev_uname_to_file(disk)
@@ -1478,7 +1518,8 @@ class XendDomainInfo:
             msg = "Had a bootloader specified, but can't find disk"
             log.error(msg)
             raise VmError(msg)
-        self.info['image'] = blcfg
+        
+        self.info.update_with_image_sxp(blcfg)
 
     # 
     # VM Functions
@@ -1516,7 +1557,8 @@ class XendDomainInfo:
         if arch.type == "x86":
             # 1MB per vcpu plus 4Kib/Mib of RAM.  This is higher than 
             # the minimum that Xen would allocate if no value were given.
-            overhead_kb = self.info['vcpus'] * 1024 + self.info['maxmem'] * 4
+            overhead_kb = self.info['vcpus_number'] * 1024 + \
+                          self.info['memory_static_max'] * 4
             overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
             # The domain might already have some shadow memory
             overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
@@ -1558,12 +1600,15 @@ class XendDomainInfo:
     def _storeVmDetails(self):
         to_store = {}
 
-        for k in VM_STORE_ENTRIES:
-            if self._infoIsSet(k[0]):
-                to_store[k[0]] = str(self.info[k[0]])
-
-        if self._infoIsSet('image'):
-            to_store['image'] = sxp.to_string(self.info['image'])
+        for key in XendConfig.LEGACY_XENSTORE_VM_PARAMS:
+            info_key = XendConfig.LEGACY_CFG_TO_XENAPI_CFG.get(key, key)
+            if self._infoIsSet(info_key):
+                to_store[key] = str(self.info[info_key])
+
+        if self.info.get('image'):
+            image_sxpr = self.info.image_sxpr()
+            if image_sxpr:
+                to_store['image'] = sxp.to_string(image_sxpr)
 
         if self._infoIsSet('security'):
             secinfo = self.info['security']
@@ -1656,6 +1701,7 @@ class XendDomainInfo:
                     #create new security element
                     self.info.update({'security':
                                       [['ssidref', str(info['ssidref'])]]})
+                    
         #ssidref field not used any longer
         if 'ssidref' in info:
             info.pop('ssidref')
@@ -1663,8 +1709,7 @@ class XendDomainInfo:
         # make sure state is reset for info
         # TODO: we should eventually get rid of old_dom_states
 
-        self.info.update(info)
-        self.info.validate()
+        self.info.update_config(info)
 
         if refresh:
             self.refreshShutdown(info)
@@ -1673,7 +1718,7 @@ class XendDomainInfo:
                   str(self.domid), self.info)
 
     def sxpr(self, ignore_store = False):
-        result = self.info.get_sxp(domain = self,
+        result = self.info.to_sxp(domain = self,
                                    ignore_devices = ignore_store)
 
         if not ignore_store and self.dompath:
@@ -1695,9 +1740,15 @@ class XendDomainInfo:
         return dom_uuid
     
     def get_memory_static_max(self):
-        return self.info['maxmem']
+        return self.info['memory_static_max']
     def get_memory_static_min(self):
-        return self.info['memory']
+        return self.info['memory_static_min']
+    def get_memory_dynamic_max(self):
+        return self.info['memory_dynamic_min']
+    def get_memory_dynamic_min(self):
+        return self.info['memory_static_min']
+    
+    
     def get_vcpus_policy(self):
         sched_id = xc.sched_id_get()
         if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
@@ -1717,21 +1768,17 @@ class XendDomainInfo:
     def get_platform_keymap(self):
         return ''
     def get_platform_serial(self):
-        return '' # TODO
+        return self.info['platform_serial']
     def get_platform_localtime(self):
-        return False # TODO
+        return self.info['platform_localtime']
     def get_platform_clock_offset(self):
-        return False # TODO
+        return self.info['platform_clock_offset']
     def get_platform_enable_audio(self):
-        return False # TODO
+        return self.info['platform_enable_audio']
     def get_builder(self):
-        return 'Linux' # TODO
+        return self.info['builder']
     def get_boot_method(self):
-        bootloader = self.info['bootloader']
-        if not bootloader or bootloader not in XEN_API_BOOT_TYPE:
-            return 'kernel_external'
-        return bootloader
-    
+        return self.info['boot_method']
     def get_kernel_image(self):
         return self.info['kernel_kernel']
     def get_kernel_initrd(self):
@@ -1748,25 +1795,26 @@ class XendDomainInfo:
         return {} # TODO
     
     def get_on_shutdown(self):
-        after_shutdown = self.info.get('on_poweroff')
+        after_shutdown = self.info.get('action_after_shutdown')
         if not after_shutdown or after_shutdown not in XEN_API_ON_NORMAL_EXIT:
             return XEN_API_ON_NORMAL_EXIT[-1]
         return after_shutdown
 
     def get_on_reboot(self):
-        after_reboot = self.info.get('on_reboot')
+        after_reboot = self.info.get('action_after_reboot')
         if not after_reboot or after_reboot not in XEN_API_ON_NORMAL_EXIT:
             return XEN_API_ON_NORMAL_EXIT[-1]
         return after_reboot
 
     def get_on_suspend(self):
-        after_suspend = self.info.get('on_suspend') # TODO: not supported
+        # TODO: not supported        
+        after_suspend = self.info.get('action_after_suspend') 
         if not after_suspend or after_suspend not in XEN_API_ON_NORMAL_EXIT:
             return XEN_API_ON_NORMAL_EXIT[-1]
         return after_suspend        
 
     def get_on_crash(self):
-        after_crash = self.info.get('on_crash')
+        after_crash = self.info.get('action_after_crash')
         if not after_crash or after_crash not in XEN_API_ON_CRASH_BEHAVIOUR:
             return XEN_API_ON_CRASH_BEHAVIOUR[0]
         return after_crash
@@ -1780,7 +1828,7 @@ class XendDomainInfo:
 
         @rtype: dictionary
         """
-        dev_type_config = self.info['device'].get(dev_uuid)
+        dev_type_config = self.info['devices'].get(dev_uuid)
 
         # shortcut if the domain isn't started because
         # the devcontrollers will have no better information
@@ -1840,7 +1888,7 @@ class XendDomainInfo:
             config['IO_bandwidth_incoming_kbs'] = 0.0
             config['IO_bandwidth_outgoing_kbs'] = 0.0
 
-        if dev_class =='vbd':
+        if dev_class == 'vbd':
             config['VDI'] = '' # TODO
             config['device'] = config.get('dev', '')
             config['driver'] = 'paravirtualised' # TODO
@@ -1984,8 +2032,8 @@ class XendDomainInfo:
 
     def __str__(self):
         return '<domain id=%s name=%s memory=%s state=%s>' % \
-               (str(self.domid), self.info['name'],
-                str(self.info['memory']), DOM_STATES[self.state])
+               (str(self.domid), self.info['name_label'],
+                str(self.info['memory_static_min']), DOM_STATES[self.state])
 
     __repr__ = __str__
 
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/image.py    Thu Nov 30 14:44:58 2006 +0000
@@ -23,7 +23,6 @@ import signal
 import signal
 
 import xen.lowlevel.xc
-from xen.xend import sxp
 from xen.xend.XendError import VmError, XendError
 from xen.xend.XendLogging import log
 from xen.xend.server.netif import randomMAC
@@ -31,19 +30,18 @@ from xen.xend import arch
 from xen.xend import arch
 from xen.xend import FlatDeviceTree
 
-
 xc = xen.lowlevel.xc.xc()
 
-
 MAX_GUEST_CMDLINE = 1024
 
 
-def create(vm, imageConfig, deviceConfig):
+def create(vm, vmConfig, imageConfig, deviceConfig):
     """Create an image handler for a vm.
 
     @return ImageHandler instance
     """
-    return findImageHandlerClass(imageConfig)(vm, imageConfig, deviceConfig)
+    return findImageHandlerClass(imageConfig)(vm, vmConfig, imageConfig,
+                                              deviceConfig)
 
 
 class ImageHandler:
@@ -66,34 +64,20 @@ class ImageHandler:
     ostype = None
 
 
-    def __init__(self, vm, imageConfig, deviceConfig):
+    def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
         self.vm = vm
 
         self.kernel = None
         self.ramdisk = None
         self.cmdline = None
 
-        self.configure(imageConfig, deviceConfig)
-
-    def configure(self, imageConfig, _):
+        self.configure(vmConfig, imageConfig, deviceConfig)
+
+    def configure(self, vmConfig, imageConfig, _):
         """Config actions common to all unix-like domains."""
-
-        def get_cfg(name, default = None):
-            return sxp.child_value(imageConfig, name, default)
-
-        self.kernel = get_cfg("kernel")
-        self.cmdline = ""
-        ip = get_cfg("ip")
-        if ip:
-            self.cmdline += " ip=" + ip
-        root = get_cfg("root")
-        if root:
-            self.cmdline += " root=" + root
-        args = get_cfg("args")
-        if args:
-            self.cmdline += " " + args
-        self.ramdisk = get_cfg("ramdisk", '')
-        
+        self.kernel = vmConfig['kernel_kernel']
+        self.cmdline = vmConfig['kernel_args']
+        self.ramdisk = vmConfig['kernel_initrd']
         self.vm.storeVm(("image/ostype", self.ostype),
                         ("image/kernel", self.kernel),
                         ("image/cmdline", self.cmdline),
@@ -214,8 +198,8 @@ class PPC_LinuxImageHandler(LinuxImageHa
 
     ostype = "linux"
 
-    def configure(self, imageConfig, deviceConfig):
-        LinuxImageHandler.configure(self, imageConfig, deviceConfig)
+    def configure(self, vmConfig, imageConfig, deviceConfig):
+        LinuxImageHandler.configure(self, vmConfig, imageConfig, deviceConfig)
         self.imageConfig = imageConfig
 
     def buildDomain(self):
@@ -248,25 +232,26 @@ class PPC_LinuxImageHandler(LinuxImageHa
 
 class HVMImageHandler(ImageHandler):
 
-    def __init__(self, vm, imageConfig, deviceConfig):
-        ImageHandler.__init__(self, vm, imageConfig, deviceConfig)
+    def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
+        ImageHandler.__init__(self, vm, vmConfig, imageConfig, deviceConfig)
         self.shutdownWatch = None
 
-    def configure(self, imageConfig, deviceConfig):
-        ImageHandler.configure(self, imageConfig, deviceConfig)
+    def configure(self, vmConfig, imageConfig, deviceConfig):
+        ImageHandler.configure(self, vmConfig, imageConfig, deviceConfig)
 
         info = xc.xeninfo()
-        if not 'hvm' in info['xen_caps']:
+        if 'hvm' not in info['xen_caps']:
             raise VmError("HVM guest support is unavailable: is VT/AMD-V "
                           "supported by your CPU and enabled in your BIOS?")
 
         self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
-        self.device_model = sxp.child_value(imageConfig, 'device_model')
+        self.device_model = imageConfig['hvm'].get('device_model')
         if not self.device_model:
             raise VmError("hvm: missing device model")
-        self.display = sxp.child_value(imageConfig, 'display')
-        self.xauthority = sxp.child_value(imageConfig, 'xauthority')
-        self.vncconsole = sxp.child_value(imageConfig, 'vncconsole')
+        
+        self.display = imageConfig['hvm'].get('display')
+        self.xauthority = imageConfig['hvm'].get('xauthority')
+        self.vncconsole = imageConfig['hvm'].get('vncconsole')
 
         self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
                         ("image/device-model", self.device_model),
@@ -276,9 +261,9 @@ class HVMImageHandler(ImageHandler):
 
         self.dmargs += self.configVNC(imageConfig)
 
-        self.pae  = int(sxp.child_value(imageConfig, 'pae',  1))
-        self.acpi = int(sxp.child_value(imageConfig, 'acpi', 1))
-        self.apic = int(sxp.child_value(imageConfig, 'apic', 1))
+        self.pae  = imageConfig['hvm'].get('pae', 0)
+        self.acpi  = imageConfig['hvm'].get('acpi', 0)
+        self.apic  = imageConfig['hvm'].get('apic', 0)
 
     def buildDomain(self):
         store_evtchn = self.vm.getStorePort()
@@ -312,8 +297,12 @@ class HVMImageHandler(ImageHandler):
                    'localtime', 'serial', 'stdvga', 'isa', 'vcpus',
                    'acpi', 'usb', 'usbdevice', 'keymap' ]
         ret = []
+        hvmDeviceConfig = imageConfig['hvm']['devices']
+        
         for a in dmargs:
-            v = sxp.child_value(imageConfig, a)
+            v = hvmDeviceConfig.get(a)
+            if a == 'vcpus':
+                v = hvmDeviceConfig.get('vcpus_number')
 
             # python doesn't allow '-' in variable names
             if a == 'stdvga': a = 'std-vga'
@@ -328,7 +317,7 @@ class HVMImageHandler(ImageHandler):
                     ret.append("-%s" % a)
                     ret.append("%s" % v)
 
-            if a in ['fda', 'fdb' ]:
+            if a in ['fda', 'fdb']:
                 if v:
                     if not os.path.isabs(v):
                         raise VmError("Floppy file %s does not exist." % v)
@@ -336,26 +325,27 @@ class HVMImageHandler(ImageHandler):
 
         # Handle disk/network related options
         mac = None
-        ret = ret + ["-domain-name", "%s" % self.vm.info['name']]
+        ret = ret + ["-domain-name", str(self.vm.info['name_label'])]
         nics = 0
-        for (name, info) in deviceConfig:
-            if name == 'vbd':
-                uname = sxp.child_value(info, 'uname')
+        
+        for devuuid, (devtype, devinfo) in deviceConfig.items():
+            if devtype == 'vbd':
+                uname = devinfo['uname']
                 if uname is not None and 'file:' in uname:
                     (_, vbdparam) = string.split(uname, ':', 1)
                     if not os.path.isfile(vbdparam):
                         raise VmError('Disk image does not exist: %s' %
                                       vbdparam)
-            if name == 'vif':
-                type = sxp.child_value(info, 'type')
-                if type != 'ioemu':
+            if devtype == 'vif':
+                dtype = devinfo.get('type', 'ioemu')
+                if dtype != 'ioemu':
                     continue
                 nics += 1
-                mac = sxp.child_value(info, 'mac')
+                mac = devinfo.get('mac')
                 if mac == None:
                     mac = randomMAC()
-                bridge = sxp.child_value(info, 'bridge', 'xenbr0')
-                model = sxp.child_value(info, 'model', 'rtl8139')
+                bridge = devinfo.get('bridge', 'xenbr0')
+                model = devinfo.get('model', 'rtl8139')
                 ret.append("-net")
                 ret.append("nic,vlan=%d,macaddr=%s,model=%s" %
                            (nics, mac, model))
@@ -363,31 +353,32 @@ class HVMImageHandler(ImageHandler):
                 ret.append("tap,vlan=%d,bridge=%s" % (nics, bridge))
         return ret
 
-    def configVNC(self, config):
+    def configVNC(self, imageConfig):
         # Handle graphics library related options
-        vnc = sxp.child_value(config, 'vnc')
-        sdl = sxp.child_value(config, 'sdl')
+        vnc = imageConfig.get('vnc')
+        sdl = imageConfig.get('sdl')
         ret = []
-        nographic = sxp.child_value(config, 'nographic')
+        nographic = imageConfig.get('nographic')
 
         # get password from VM config (if password omitted, None)
-        vncpasswd_vmconfig = sxp.child_value(config, 'vncpasswd')
+        vncpasswd_vmconfig = imageConfig.get('vncpasswd')
 
         if nographic:
             ret.append('-nographic')
             return ret
 
         if vnc:
-            vncdisplay = int(sxp.child_value(config, 'vncdisplay',
-                                             self.vm.getDomid()))
-
-            vncunused = sxp.child_value(config, 'vncunused')
+            vncdisplay = imageConfig.get('vncdisplay',
+                                         int(self.vm.getDomid()))
+            vncunused = imageConfig.get('vncunused')
+
             if vncunused:
                 ret += ['-vncunused']
             else:
                 ret += ['-vnc', '%d' % vncdisplay]
 
-            vnclisten = sxp.child_value(config, 'vnclisten')
+            vnclisten = imageConfig.get('vnclisten')
+
             if not(vnclisten):
                 vnclisten = (xen.xend.XendRoot.instance().
                              get_vnclisten_address())
@@ -423,21 +414,26 @@ class HVMImageHandler(ImageHandler):
         if self.vncconsole:
             args = args + ([ "-vncviewer" ])
         log.info("spawning device models: %s %s", self.device_model, args)
+        # keep track of pid and spawned options to kill it later
         self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
         log.info("device model pid: %d", self.pid)
 
     def destroy(self):
-        self.unregister_shutdown_watch();
+        self.unregister_shutdown_watch()
         if not self.pid:
             return
-        os.kill(self.pid, signal.SIGKILL)
-        os.waitpid(self.pid, 0)
+        try:
+            os.kill(self.pid, signal.SIGKILL)
+            os.waitpid(self.pid, 0)
+        except OSError, e:
+            log.warning("Unable to kill device model (pid: %d)" % self.pid)
+            
         self.pid = 0
 
     def register_shutdown_watch(self):
         """ add xen store watch on control/shutdown """
-        self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", \
-                                    self.hvm_shutdown)
+        self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown",
+                                     self.hvm_shutdown)
         log.debug("hvm shutdown watch registered")
 
     def unregister_shutdown_watch(self):
@@ -529,10 +525,10 @@ def findImageHandlerClass(image):
     @param image config
     @return ImageHandler subclass or None
     """
-    type = sxp.name(image)
-    if type is None:
+    image_type = image['type']
+    if image_type is None:
         raise VmError('missing image type')
     try:
-        return _handlers[arch.type][type]
+        return _handlers[arch.type][image_type]
     except KeyError:
-        raise VmError('unknown image type: ' + type)
+        raise VmError('unknown image type: ' + image_type)
diff -r e7cb5813e2a7 -r 5bed7bc05c8a 
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py     Thu Nov 30 14:05:27 
2006 +0000
+++ b/tools/python/xen/xend/server/DevController.py     Thu Nov 30 14:44:58 
2006 +0000
@@ -17,6 +17,7 @@
 #============================================================================
 
 from threading import Event
+import types
 
 from xen.xend import sxp
 from xen.xend.XendError import VmError
@@ -86,7 +87,7 @@ class DevController:
 
         import xen.xend.XendDomain
         xd = xen.xend.XendDomain.instance()
-        backdom_name = sxp.child_value(config, 'backend')
+        backdom_name = config.get('backend')
         if backdom_name is None:
             backdom = xen.xend.XendDomain.DOM0_ID
         else:
@@ -223,7 +224,7 @@ class DevController:
         configDict = self.getDeviceConfiguration(devid)
         sxpr = [self.deviceClass]
         for key, val in configDict.items():
-            if type(val) == type(list()):
+            if isinstance(val, (types.ListType, types.TupleType)):
                 for v in val:
                     sxpr.append([key, v])
             else:
@@ -405,7 +406,7 @@ class DevController:
         import xen.xend.XendDomain
         xd = xen.xend.XendDomain.instance()
 
-        backdom_name = sxp.child_value(config, 'backend')
+        backdom_name = config.get('backend')
         if backdom_name:
             backdom = xd.domain_lookup_nr(backdom_name)
         else:
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py     Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/blkif.py     Thu Nov 30 14:44:58 2006 +0000
@@ -21,7 +21,6 @@ import string
 
 from xen.util import blkif
 from xen.util import security
-from xen.xend import sxp
 from xen.xend.XendError import VmError
 from xen.xend.server.DevController import DevController
 
@@ -37,9 +36,9 @@ class BlkifController(DevController):
 
     def getDeviceDetails(self, config):
         """@see DevController.getDeviceDetails"""
-        uname = sxp.child_value(config, 'uname', '')
-        dev = sxp.child_value(config, 'dev', '')
-
+        uname = config.get('uname', '')
+        dev = config.get('dev', '')
+        
         if 'ioemu:' in dev:
             (_, dev) = string.split(dev, ':', 1)
         try:
@@ -59,17 +58,17 @@ class BlkifController(DevController):
             except ValueError:
                 (typ, params) = ("", "")
 
-        mode = sxp.child_value(config, 'mode', 'r')
+        mode = config.get('mode', 'r')
         if mode not in ('r', 'w', 'w!'):
             raise VmError('Invalid mode')
 
-        back = { 'dev'    : dev,
-                 'type'   : typ,
-                 'params' : params,
-                 'mode'   : mode
-               }
+        back = {'dev'    : dev,
+                'type'   : typ,
+                'params' : params,
+                'mode'   : mode,
+                }
 
-        uuid = sxp.child_value(config, 'uuid')
+        uuid = config.get('uuid')
         if uuid:
             back['uuid'] = uuid
 
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/server/iopif.py
--- a/tools/python/xen/xend/server/iopif.py     Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/iopif.py     Thu Nov 30 14:44:58 2006 +0000
@@ -22,7 +22,6 @@ import types
 
 import xen.lowlevel.xc
 
-from xen.xend import sxp
 from xen.xend.XendError import VmError
 
 from xen.xend.server.DevController import DevController
@@ -49,13 +48,12 @@ class IOPortsController(DevController):
     def __init__(self, vm):
         DevController.__init__(self, vm)
 
-
     def getDeviceDetails(self, config):
         """@see DevController.getDeviceDetails"""
 
         def get_param(field):
             try:
-                val = sxp.child_value(config, field)
+                val = config.get(field)
 
                 if not val:
                     raise VmError('ioports: Missing %s config setting' % field)
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/server/irqif.py
--- a/tools/python/xen/xend/server/irqif.py     Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/irqif.py     Thu Nov 30 14:44:58 2006 +0000
@@ -45,7 +45,7 @@ class IRQController(DevController):
 
         def get_param(field):
             try:
-                val = sxp.child_value(config, field)
+                val = config.get(field)
 
                 if not val:
                     raise VmError('irq: Missing %s config setting' % field)
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/server/netif.py
--- a/tools/python/xen/xend/server/netif.py     Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/netif.py     Thu Nov 30 14:44:58 2006 +0000
@@ -24,7 +24,6 @@ import random
 import random
 import re
 
-from xen.xend import sxp
 from xen.xend import XendRoot
 from xen.xend.server.DevController import DevController
 
@@ -139,22 +138,15 @@ class NetifController(DevController):
     def getDeviceDetails(self, config):
         """@see DevController.getDeviceDetails"""
 
-        def _get_config_ipaddr(config):
-            val = []
-            for ipaddr in sxp.children(config, elt='ip'):
-                val.append(sxp.child0(ipaddr))
-            return val
-
         script = os.path.join(xroot.network_script_dir,
-                              sxp.child_value(config, 'script',
-                                              xroot.get_vif_script()))
-        typ = sxp.child_value(config, 'type')
-        bridge  = sxp.child_value(config, 'bridge')
-        mac     = sxp.child_value(config, 'mac')
-        vifname = sxp.child_value(config, 'vifname')
-        rate    = sxp.child_value(config, 'rate')
-        uuid    = sxp.child_value(config, 'uuid')
-        ipaddr  = _get_config_ipaddr(config)
+                              config.get('script', xroot.get_vif_script()))
+        typ = config.get('type')
+        bridge  = config.get('bridge')
+        mac     = config.get('mac')
+        vifname = config.get('vifname')
+        rate    = config.get('rate')
+        uuid    = config.get('uuid')
+        ipaddr  = config.get('ip')
 
         devid = self.allocateDeviceID()
 
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py     Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/pciif.py     Thu Nov 30 14:44:58 2006 +0000
@@ -53,60 +53,29 @@ class PciController(DevController):
 
     def getDeviceDetails(self, config):
         """@see DevController.getDeviceDetails"""
-        #log.debug('pci config='+sxp.to_string(config))
-
-        def get_param(config, field, default=None):
+        def parse_hex(val):
             try:
-                val = sxp.child_value(config, field)
-
-                if not val:
-                    if default==None:
-                        raise VmError('pci: Missing %s config setting' % field)
-                    else:
-                        return default
-
                 if isinstance(val, types.StringTypes):
                     return int(val, 16)
                 else:
                     return val
-            except:
-                if default==None:
-                    raise VmError('pci: Invalid config setting %s: %s' %
-                              (field, val))
-                else:
-                    return default
-        
+            except ValueError:
+                return None
+            
         back = {}
+        pcidevid = 0
+        for pci_config in config.get('devs', []):
+            domain = parse_hex(pci_config.get('domain', 0))
+            bus = parse_hex(pci_config.get('bus', 0))
+            slot = parse_hex(pci_config.get('slot', 0))
+            func = parse_hex(pci_config.get('func', 0))            
+            self.setupDevice(domain, bus, slot, func)
+            back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%02x" % \
+                                        (domain, bus, slot, func)
+            pcidevid += 1
 
-        val = sxp.child_value(config, 'dev')
-        if isinstance(val, (types.ListType, types.TupleType)):
-            pcidevid = 0
-            for dev_config in sxp.children(config, 'dev'):
-                domain = get_param(dev_config, 'domain', 0)
-                bus = get_param(dev_config,'bus')
-                slot = get_param(dev_config,'slot')
-                func = get_param(dev_config,'func')
-
-                self.setupDevice(domain, bus, slot, func)
-
-                back['dev-%i' % pcidevid]="%04x:%02x:%02x.%02x"% \
-                        (domain, bus, slot, func)
-                pcidevid+=1
-            
-            back['num_devs']=str(pcidevid)
-
-        else:
-            # Xen 2.0 configuration compatibility
-            domain = get_param(config, 'domain', 0)
-            bus  = get_param(config, 'bus')
-            slot = get_param(config, 'dev')
-            func = get_param(config, 'func')
-
-            self.setupDevice(domain, bus, slot, func)
-
-            back['dev-0']="%04x:%02x:%02x.%02x"%(domain, bus, slot, func)
-            back['num_devs']=str(1)
-
+        back['num_devs']=str(pcidevid)
+        back['uuid'] = config.get('uuid','')
         return (0, back, {})
 
     def getDeviceConfiguration(self, devid):
@@ -129,7 +98,8 @@ class PciController(DevController):
                                  'slot': '0x%(slot)s' % pci_dev_info,
                                  'func': '0x%(func)s' % pci_dev_info})
 
-        result['dev'] = pci_devs
+        result['devs'] = pci_devs
+        result['uuid'] = self.readBackend(devid, 'uuid')
         return result
 
     def configuration(self, devid):
@@ -142,7 +112,8 @@ class PciController(DevController):
         sxpr = [self.deviceClass]
 
         # remove devs
-        devs = configDict.pop('dev', [])
+        devs = configDict.pop('devs', [])
+        
         for dev in devs:
             dev_sxpr = ['dev']
             for dev_item in dev.items():
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/server/pciquirk.py
--- a/tools/python/xen/xend/server/pciquirk.py  Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/pciquirk.py  Thu Nov 30 14:44:58 2006 +0000
@@ -15,25 +15,24 @@ class PCIQuirk:
         self.device = device
         self.subvendor = subvendor
         self.subdevice = subdevice
-       self.domain = domain
-       self.bus = bus
-       self.slot = slot
-       self.func = func
+        self.domain = domain
+        self.bus = bus
+        self.slot = slot
+        self.func = func
 
         self.devid = "%04x:%04x:%04x:%04x" % (vendor, device, subvendor, 
subdevice)
-       self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
+        self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
+        self.quirks = self.__getQuirksByID()
 
-        self.quirks = self.__getQuirksByID( )
-
-       self.__sendQuirks( )
-       self.__sendPermDevs( )
+        self.__sendQuirks()
+        self.__sendPermDevs()
 
     def __matchPCIdev( self, list ):
         ret = False
         if list == None:
             return False
         for id in list:
-            if id.startswith( self.devid[:9] ): # id's vendor and device ID 
match
+            if id.startswith(self.devid[:9]): # id's vendor and device ID match
                 skey = id.split(':')
                 size = len(skey)
                 if (size == 2):                # subvendor/subdevice not 
suplied
@@ -41,13 +40,13 @@ class PCIQuirk:
                     break
                 elif (size == 4):      # check subvendor/subdevice
                     # check subvendor
-                   subven = '%04x' % self.subvendor
+                    subven = '%04x' % self.subvendor
                     if ((skey[2] != 'FFFF') and 
                         (skey[2] != 'ffff') and 
                         (skey[2] != subven)):
                             continue
                     # check subdevice
-                   subdev = '%04x' % self.subdevice
+                    subdev = '%04x' % self.subdevice
                     if ((skey[3] != 'FFFF') and 
                         (skey[3] != 'ffff') and 
                         (skey[3] != subdev)):
@@ -101,8 +100,8 @@ class PCIQuirk:
                        self.slot, self.func, quirk) )
                 f.close()
             except Exception, e:
-                raise VmError("pci: failed to open/write/close quirks sysfs " 
+ \
-                       "node - " + str(e))
+                raise VmError("pci: failed to open/write/close quirks " +
+                              "sysfs node - " + str(e))
 
     def __devIsUnconstrained( self ):
         if os.path.exists(PERMISSIVE_CONFIG_FILE):
@@ -126,20 +125,22 @@ class PCIQuirk:
 
         devices = child_at(child(pci_perm_dev_config, 
'unconstrained_dev_ids'),0)
        if self.__matchPCIdev( devices ):
-            log.debug("Permissive mode enabled for PCI device [%s]" % 
self.devid)
+            log.debug("Permissive mode enabled for PCI device [%s]" %
+                      self.devid)
             return True
-        log.debug("Permissive mode NOT enabled for PCI device [%s]" % 
self.devid)
+        log.debug("Permissive mode NOT enabled for PCI device [%s]" %
+                  self.devid)
         return False
 
     def __sendPermDevs(self):
        if self.__devIsUnconstrained( ):
-            log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % 
(self.domain,
-                   self.bus, self.slot, self.func))
+            log.debug("Unconstrained device: %04x:%02x:%02x.%1x" %
+                      (self.domain, self.bus, self.slot, self.func))
             try:
                 f = file(PERMISSIVE_SYSFS_NODE ,"w")
                 f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus,
-                       self.slot, self.func) )
+                                                 self.slot, self.func))
                 f.close()
             except Exception, e:
-                raise VmError("pci: failed to open/write/close permissive " + \
-               "sysfs node: " + str(e))
+                raise VmError("pci: failed to open/write/close permissive " +
+                              "sysfs node: " + str(e))
diff -r e7cb5813e2a7 -r 5bed7bc05c8a 
tools/python/xen/xend/server/tests/test_controllers.py
--- a/tools/python/xen/xend/server/tests/test_controllers.py    Thu Nov 30 
14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/tests/test_controllers.py    Thu Nov 30 
14:44:58 2006 +0000
@@ -21,11 +21,11 @@ class test_controllers(unittest.TestCase
     def testNetif(self):
         controller = self.controllerInstance(netif.NetifController)
 
-        self.assertNetif(controller.getDeviceDetails(['vif']), None)
+        self.assertNetif(controller.getDeviceDetails({}), None)
         self.assertNetif(
-            controller.getDeviceDetails(
-            ['vif', ['mac', 'aa:bb:cc:dd:ee:ff']]),
+            controller.getDeviceDetails({'mac': 'aa:bb:cc:dd:ee:ff'}),
             'aa:bb:cc:dd:ee:ff')
+
 
 
     def assertNetif(self, results, expectedMac):
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xend/server/tpmif.py
--- a/tools/python/xen/xend/server/tpmif.py     Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xend/server/tpmif.py     Thu Nov 30 14:44:58 2006 +0000
@@ -18,10 +18,8 @@
 # Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
-"""Support for virtual TPM interfaces.
-"""
+"""Support for virtual TPM interfaces."""
 
-from xen.xend import sxp
 from xen.xend import XendRoot
 from xen.xend.XendLogging import log
 from xen.xend.XendError import XendError
@@ -49,12 +47,12 @@ class TPMifController(DevController):
         """@see DevController.getDeviceDetails"""
 
         devid = self.allocateDeviceID()
-        inst = int(sxp.child_value(config, 'pref_instance', '-1'))
+        inst = int(config.get('pref_instance', -1))
         if inst == -1:
-            inst = int(sxp.child_value(config, 'instance' , '0'))
+            inst = int(config.get('instance', 0))
 
-        typ    = sxp.child_value(config, 'type')
-        uuid   = sxp.child_value(config, 'uuid')
+        typ    = config.get('type')
+        uuid   = config.get('uuid')
 
         log.info("The domain has a TPM with pref. instance %d and devid %d.",
                  inst, devid)
diff -r e7cb5813e2a7 -r 5bed7bc05c8a tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Thu Nov 30 14:05:27 2006 +0000
+++ b/tools/python/xen/xm/main.py       Thu Nov 30 14:44:58 2006 +0000
@@ -581,8 +581,8 @@ def parse_doms_info(info):
     return {
         'domid'    : get_info('domid',        str,   ''),
         'name'     : get_info('name',         str,   '??'),
-        'mem'      : get_info('memory_dynamic_max', int,   0),
-        'vcpus'    : get_info('online_vcpus', int,   0),
+        'mem'      : get_info('memory_dynamic_min', int,   0),
+        'vcpus'    : get_info('vcpus',        int,   0),
         'state'    : get_info('state',        str,    ''),
         'cpu_time' : get_info('cpu_time',     float, 0),
         'up_time'  : get_info('up_time',      float, -1),

_______________________________________________
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®.