direct-io.hg

changeset 14425:6b2875302558

Support xm create through the Xen-API.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
author Ewan Mellor <ewan@xensource.com>
date Sat Mar 17 23:59:05 2007 +0000 (2007-03-17)
parents cfb265b93b2d
children afbf744440d2
files tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/XendNode.py tools/python/xen/xm/create.dtd tools/python/xen/xm/create.py tools/python/xen/xm/new.py tools/python/xen/xm/xenapi_create.py
line diff
     1.1 --- a/tools/python/xen/xend/XendConfig.py	Sat Mar 17 23:57:17 2007 +0000
     1.2 +++ b/tools/python/xen/xend/XendConfig.py	Sat Mar 17 23:59:05 2007 +0000
     1.3 @@ -105,8 +105,6 @@ XENAPI_CFG_TO_LEGACY_CFG = {
     1.4      'uuid': 'uuid',
     1.5      'vcpus_number': 'vcpus',
     1.6      'cpus': 'cpus',
     1.7 -    'memory_static_min': 'memory',
     1.8 -    'memory_static_max': 'maxmem',
     1.9      'name_label': 'name',
    1.10      'actions_after_shutdown': 'on_poweroff',
    1.11      'actions_after_reboot': 'on_reboot',
    1.12 @@ -136,11 +134,10 @@ XENAPI_CFG_TYPES = {
    1.13      'user_version': str,
    1.14      'is_a_template': bool0,
    1.15      'resident_on': str,
    1.16 -    'memory_static_min': int,
    1.17 +    'memory_static_min': int,  # note these are stored in bytes, not KB!
    1.18      'memory_static_max': int,
    1.19      'memory_dynamic_min': int,
    1.20      'memory_dynamic_max': int,
    1.21 -    'memory_actual': int,
    1.22      'cpus': list,
    1.23      'vcpus_policy': str,
    1.24      'vcpus_params': dict,
    1.25 @@ -314,7 +311,6 @@ class XendConfig(dict):
    1.26              'shadow_memory': 0,
    1.27              'memory_static_max': 0,
    1.28              'memory_dynamic_max': 0,
    1.29 -            'memory_actual': 0,
    1.30              'devices': {},
    1.31              'security': None,
    1.32              'on_xend_start': 'ignore',
    1.33 @@ -334,20 +330,39 @@ class XendConfig(dict):
    1.34          
    1.35          return defaults
    1.36  
    1.37 +    #
    1.38 +    # Here we assume these values exist in the dict.
    1.39 +    # If they don't we have a bigger problem, lets not
    1.40 +    # try and 'fix it up' but acutually fix the cause ;-)
    1.41 +    #
    1.42      def _memory_sanity_check(self):
    1.43 -        if self['memory_static_min'] == 0:
    1.44 -            self['memory_static_min'] = self['memory_dynamic_min']
    1.45 -
    1.46 -        # If the static max is not set, let's set it to dynamic max.
    1.47 -        # If the static max is smaller than static min, then fix it!
    1.48 -        self['memory_static_max'] = max(self['memory_static_max'],
    1.49 -                                        self['memory_dynamic_max'],
    1.50 -                                        self['memory_static_min'])
    1.51 -
    1.52 -        for mem_type in ('memory_static_min', 'memory_static_max'):
    1.53 -            if self[mem_type] <= 0:
    1.54 -                raise XendConfigError('Memory value too low for %s: %d' %
    1.55 -                                      (mem_type, self[mem_type]))
    1.56 +        log.debug("_memory_sanity_check memory_static_min: %s, "
    1.57 +                      "memory_static_max: %i, "
    1.58 +                      "memory_dynamic_min: %i, " 
    1.59 +                      "memory_dynamic_max: %i",
    1.60 +                      self["memory_static_min"],
    1.61 +                      self["memory_static_max"],
    1.62 +                      self["memory_dynamic_min"],
    1.63 +                      self["memory_dynamic_max"])
    1.64 +        
    1.65 +        if not self["memory_static_min"] <= self["memory_static_max"]:
    1.66 +            raise XendConfigError("memory_static_min must be less " \
    1.67 +                                  "than or equal to memory_static_max") 
    1.68 +        if not self["memory_dynamic_min"] <= self["memory_dynamic_max"]:
    1.69 +            raise XendConfigError("memory_dynamic_min must be less " \
    1.70 +                                  "than or equal to memory_dynamic_max")
    1.71 +        if not self["memory_static_min"] <= self["memory_dynamic_min"]:
    1.72 +            raise XendConfigError("memory_static_min must be less " \
    1.73 +                                  "than or equal to memory_dynamic_min")
    1.74 +        if not self["memory_dynamic_max"] <= self["memory_static_max"]:
    1.75 +            raise XendConfigError("memory_dynamic_max must be less " \
    1.76 +                                  "than or equal to memory_static_max")
    1.77 +        if not self["memory_dynamic_max"] > 0:
    1.78 +            raise XendConfigError("memory_dynamic_max must be greater " \
    1.79 +                                  "than zero")
    1.80 +        if not self["memory_static_max"] > 0:
    1.81 +            raise XendConfigError("memory_static_max must be greater " \
    1.82 +                                  "than zero")
    1.83  
    1.84      def _actions_sanity_check(self):
    1.85          for event in ['shutdown', 'reboot', 'crash']:
    1.86 @@ -392,8 +407,12 @@ class XendConfig(dict):
    1.87          self['domid'] = dominfo['domid']
    1.88          self['online_vcpus'] = dominfo['online_vcpus']
    1.89          self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
    1.90 -        self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
    1.91 -        self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
    1.92 +
    1.93 +        self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024
    1.94 +        self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024
    1.95 +        self['memory_static_min'] = 0
    1.96 +        self['memory_static_max'] = dominfo['maxmem_kb'] * 1024
    1.97 +
    1.98          self['cpu_time'] = dominfo['cpu_time']/1e9
    1.99          # TODO: i don't know what the security stuff expects here
   1.100          if dominfo.get('ssidref'):
   1.101 @@ -447,6 +466,13 @@ class XendConfig(dict):
   1.102                  log.warn('Ignoring unrecognised value for deprecated option:'
   1.103                           'restart = \'%s\'', restart)
   1.104  
   1.105 +        # Handle memory, passed in as MiB
   1.106 +
   1.107 +        if sxp.child_value(sxp_cfg, "memory") != None:
   1.108 +            cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory"))
   1.109 +        if sxp.child_value(sxp_cfg, "maxmem") != None:
   1.110 +            cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
   1.111 +            
   1.112          # Only extract options we know about.
   1.113          extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
   1.114          extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
   1.115 @@ -616,6 +642,21 @@ class XendConfig(dict):
   1.116              except KeyError:
   1.117                  pass
   1.118  
   1.119 +        # Lets try and handle memory correctly
   1.120 +
   1.121 +        MiB = 1024 * 1024
   1.122 +
   1.123 +        if "memory" in cfg:
   1.124 +            self["memory_static_min"] = 0
   1.125 +            self["memory_static_max"] = int(cfg["memory"]) * MiB
   1.126 +            self["memory_dynamic_min"] = int(cfg["memory"]) * MiB
   1.127 +            self["memory_dynamic_max"] = int(cfg["memory"]) * MiB
   1.128 +            
   1.129 +            if "maxmem" in cfg:
   1.130 +                self["memory_static_max"] = int(cfg["maxmem"]) * MiB
   1.131 +
   1.132 +        self._memory_sanity_check()
   1.133 +
   1.134          def update_with(n, o):
   1.135              if not self.get(n):
   1.136                  self[n] = cfg.get(o, '')
   1.137 @@ -632,13 +673,6 @@ class XendConfig(dict):
   1.138              if key in cfg:
   1.139                  self['platform'][key] = cfg[key]
   1.140  
   1.141 -        # make sure a sane maximum is set
   1.142 -        if self['memory_static_max'] <= 0:
   1.143 -            self['memory_static_max'] = self['memory_static_min']
   1.144 -            
   1.145 -        self['memory_dynamic_max'] = self['memory_static_max']
   1.146 -        self['memory_dynamic_min'] = self['memory_static_min']
   1.147 -
   1.148          # set device references in the configuration
   1.149          self['devices'] = cfg.get('devices', {})
   1.150          self['console_refs'] = cfg.get('console_refs', [])
   1.151 @@ -812,6 +846,21 @@ class XendConfig(dict):
   1.152                  else:
   1.153                      sxpr.append([legacy, self[xenapi]])
   1.154  
   1.155 +        MiB = 1024*1024
   1.156 +
   1.157 +        sxpr.append(["maxmem", int(self["memory_static_max"])/MiB])
   1.158 +        sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
   1.159 +
   1.160 +        if not legacy_only:
   1.161 +            sxpr.append(['memory_dynamic_min',
   1.162 +                     int(self.get('memory_dynamic_min'))])
   1.163 +            sxpr.append(['memory_dynamic_max',
   1.164 +                     int(self.get('memory_dynamic_max'))])
   1.165 +            sxpr.append(['memory_static_max',
   1.166 +                     int(self.get('memory_static_max'))])
   1.167 +            sxpr.append(['memory_static_min',
   1.168 +                     int(self.get('memory_static_min'))])
   1.169 +
   1.170          for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
   1.171              if legacy in ('domid', 'uuid'): # skip these
   1.172                  continue
   1.173 @@ -820,8 +869,6 @@ class XendConfig(dict):
   1.174  
   1.175          sxpr.append(['image', self.image_sxpr()])
   1.176          sxpr.append(['status', domain.state])
   1.177 -        sxpr.append(['memory_dynamic_min',  self.get('memory_dynamic_min')])
   1.178 -        sxpr.append(['memory_dynamic_max',  self.get('memory_dynamic_max')])
   1.179  
   1.180          if domain.getDomid() is not None:
   1.181              sxpr.append(['state', self._get_old_state_string()])
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Sat Mar 17 23:57:17 2007 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Sat Mar 17 23:59:05 2007 +0000
     2.3 @@ -576,7 +576,7 @@ class XendDomainInfo:
     2.4          if target <= 0:
     2.5              raise XendError('Invalid memory size')
     2.6          
     2.7 -        self.info['memory_static_min'] = target
     2.8 +        self.info['memory_static_min'] = target * 1024 * 1024
     2.9          if self.domid >= 0:
    2.10              self.storeVm("memory", target)
    2.11              self.storeDom("memory/target", target << 10)
    2.12 @@ -664,6 +664,10 @@ class XendDomainInfo:
    2.13                  if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
    2.14                      xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
    2.15                      self.info[xapiarg] = val
    2.16 +                elif arg == "memory":
    2.17 +                    self.info["static_memory_min"] = val
    2.18 +                elif arg == "maxmem":
    2.19 +                    self.info["static_memory_max"] = val
    2.20                  else:
    2.21                      self.info[arg] = val
    2.22  
    2.23 @@ -780,7 +784,7 @@ class XendDomainInfo:
    2.24              'vm':                 self.vmpath,
    2.25              'name':               self.info['name_label'],
    2.26              'console/limit':      str(xoptions.get_console_limit() * 1024),
    2.27 -            'memory/target':      str(self.info['memory_static_min'] * 1024),
    2.28 +            'memory/target':      str(self.info['memory_dynamic_max'] / 1024),
    2.29              }
    2.30  
    2.31          def f(n, v):
    2.32 @@ -864,7 +868,15 @@ class XendDomainInfo:
    2.33                  xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
    2.34                  if val != None and val != self.info[xapiarg]:
    2.35                      self.info[xapiarg] = val
    2.36 -                    changed= True
    2.37 +                    changed = True
    2.38 +            elif arg == "memory":
    2.39 +                if val != None and val != self.info["static_memory_min"]:
    2.40 +                    self.info["static_memory_min"] = val
    2.41 +                    changed = True
    2.42 +            elif arg == "maxmem":
    2.43 +                if val != None and val != self.info["static_memory_max"]:
    2.44 +                    self.info["static_memory_max"] = val
    2.45 +                    changed = True
    2.46  
    2.47          # Check whether image definition has been updated
    2.48          image_sxp = self._readVm('image')
    2.49 @@ -969,11 +981,12 @@ class XendDomainInfo:
    2.50  
    2.51      def getMemoryTarget(self):
    2.52          """Get this domain's target memory size, in KB."""
    2.53 -        return self.info['memory_static_min'] * 1024
    2.54 +        return self.info['memory_static_min'] / 1024
    2.55  
    2.56      def getMemoryMaximum(self):
    2.57          """Get this domain's maximum memory size, in KB."""
    2.58 -        return self.info['memory_static_max'] * 1024
    2.59 +        # remember, info now stores memory in bytes
    2.60 +        return self.info['memory_static_max'] / 1024
    2.61  
    2.62      def getResume(self):
    2.63          return str(self._resume)
    2.64 @@ -1455,13 +1468,14 @@ class XendDomainInfo:
    2.65              # Use architecture- and image-specific calculations to determine
    2.66              # the various headrooms necessary, given the raw configured
    2.67              # values. maxmem, memory, and shadow are all in KiB.
    2.68 +            # but memory_static_max etc are all stored in bytes now.
    2.69              memory = self.image.getRequiredAvailableMemory(
    2.70 -                self.info['memory_static_min'] * 1024)
    2.71 +                self.info['memory_static_min'] / 1024)
    2.72              maxmem = self.image.getRequiredAvailableMemory(
    2.73 -                self.info['memory_static_max'] * 1024)
    2.74 +                self.info['memory_static_max'] / 1024)
    2.75              shadow = self.image.getRequiredShadowMemory(
    2.76 -                self.info['shadow_memory'] * 1024,
    2.77 -                self.info['memory_static_max'] * 1024)
    2.78 +                self.info['shadow_memory'] / 1024,
    2.79 +                self.info['memory_static_max'] / 1024)
    2.80  
    2.81              log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
    2.82              # Round shadow up to a multiple of a MiB, as shadow_mem_control
    2.83 @@ -1650,7 +1664,18 @@ class XendDomainInfo:
    2.84              log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
    2.85  
    2.86          from xen.xend import XendDomain
    2.87 -        XendDomain.instance().remove_domain(self)
    2.88 +
    2.89 +        if "transient" in self.info["other_config"]\
    2.90 +           and bool(self.info["other_config"]["transient"]):
    2.91 +            xendDomainInstance = XendDomain.instance()
    2.92 +            
    2.93 +            xendDomainInstance.domains_lock.acquire()
    2.94 +            xendDomainInstance._refresh(refresh_shutdown = False)
    2.95 +            xendDomainInstance.domains_lock.release()
    2.96 +            
    2.97 +            xendDomainInstance.domain_delete(self.info["name_label"])
    2.98 +        else:
    2.99 +            XendDomain.instance().remove_domain(self)
   2.100  
   2.101          self.cleanupDomain()
   2.102          self._cleanup_phantom_devs(paths)
   2.103 @@ -1833,7 +1858,7 @@ class XendDomainInfo:
   2.104              # 1MB per vcpu plus 4Kib/Mib of RAM.  This is higher than 
   2.105              # the minimum that Xen would allocate if no value were given.
   2.106              overhead_kb = self.info['vcpus_number'] * 1024 + \
   2.107 -                          self.info['memory_static_max'] * 4
   2.108 +                          (self.info['memory_static_max'] / 1024 / 1024) * 4
   2.109              overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
   2.110              # The domain might already have some shadow memory
   2.111              overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
   2.112 @@ -1899,6 +1924,11 @@ class XendDomainInfo:
   2.113              if self._infoIsSet(info_key):
   2.114                  to_store[key] = str(self.info[info_key])
   2.115  
   2.116 +        if self._infoIsSet("static_memory_min"):
   2.117 +            to_store["memory"] = str(self.info["static_memory_min"])
   2.118 +        if self._infoIsSet("static_memory_max"):
   2.119 +            to_store["maxmem"] = str(self.info["static_memory_max"])
   2.120 +
   2.121          image_sxpr = self.info.image_sxpr()
   2.122          if image_sxpr:
   2.123              to_store['image'] = sxp.to_string(image_sxpr)
     3.1 --- a/tools/python/xen/xend/XendNode.py	Sat Mar 17 23:57:17 2007 +0000
     3.2 +++ b/tools/python/xen/xend/XendNode.py	Sat Mar 17 23:59:05 2007 +0000
     3.3 @@ -530,7 +530,8 @@ class XendNode:
     3.4                             info['cores_per_socket'] *
     3.5                             info['threads_per_core'])
     3.6          info['cpu_mhz'] = info['cpu_khz'] / 1000
     3.7 -        # physinfo is in KiB
     3.8 +        
     3.9 +        # physinfo is in KiB, need it in MiB
    3.10          info['total_memory'] = info['total_memory'] / 1024
    3.11          info['free_memory']  = info['free_memory'] / 1024
    3.12  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/python/xen/xm/create.dtd	Sat Mar 17 23:59:05 2007 +0000
     4.3 @@ -0,0 +1,118 @@
     4.4 +<!ENTITY % HTMLlat1 PUBLIC 
     4.5 +   "-//W3C//ENTITIES Latin 1 for XHTML//EN" 
     4.6 +   "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent"> 
     4.7 +%HTMLlat1; 
     4.8 +<!ENTITY % HTMLsymbol PUBLIC 
     4.9 +   "-//W3C//ENTITIES Symbols for XHTML//EN" 
    4.10 +   "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent"> 
    4.11 +%HTMLsymbol; 
    4.12 +<!ENTITY % HTMLspecial PUBLIC 
    4.13 +   "-//W3C//ENTITIES Special for XHTML//EN" 
    4.14 +   "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent"> 
    4.15 +%HTMLspecial; 
    4.16 +<!-- a Uniform Resource Identifier, see [RFC2396] --> 
    4.17 +<!ENTITY % URI "CDATA"> 
    4.18 +<!ENTITY % NAMEID "name ID #REQUIRED"> 
    4.19 +<!ENTITY % CRASH_BEHAVIOUR "( destroy 
    4.20 +                            | coredump_and_destroy
    4.21 +                            | restart
    4.22 +                            | coredump_and_restart
    4.23 +                            | preserve
    4.24 +                            | rename_restart )">
    4.25 +<!ENTITY % NORMAL_EXIT     "( destroy | restart )">
    4.26 +<!ENTITY % VDI_TYPE        "( system
    4.27 +                            | user
    4.28 +                            | ephemeral
    4.29 +                            | suspend
    4.30 +                            | crashdump )">
    4.31 +
    4.32 +<!ELEMENT xm (vm*, 
    4.33 +              vdi*)> 
    4.34 +
    4.35 +<!ELEMENT version (#PCDATA)>
    4.36 + 
    4.37 +<!ELEMENT vm    (name,
    4.38 +                 version,
    4.39 +                 (pv|hvm), 
    4.40 +                 memory,
    4.41 +                 vbd*,
    4.42 +                 vif*,
    4.43 +                 vcpu_param*,
    4.44 +                 other_config*)> 
    4.45 +<!ATTLIST vm     is_a_template          CDATA #REQUIRED
    4.46 +                 auto_power_on          CDATA #REQUIRED
    4.47 +                 vcpus_max              CDATA #REQUIRED
    4.48 +                 vcpus_at_startup       CDATA #REQUIRED
    4.49 +                 actions_after_shutdown %NORMAL_EXIT; #REQUIRED 
    4.50 +                 actions_after_reboot   %NORMAL_EXIT; #REQUIRED
    4.51 +                 actions_after_crash    %CRASH_BEHAVIOUR; #REQUIRED
    4.52 +                 platform_std_VGA       CDATA #REQUIRED
    4.53 +                 platform_serial        CDATA #REQUIRED
    4.54 +                 platform_localtime     CDATA #REQUIRED 
    4.55 +                 platform_clock_offet   CDATA #REQUIRED
    4.56 +                 platform_enable_audio  CDATA #REQUIRED
    4.57 +                 PCI_bus                CDATA #REQUIRED> 
    4.58 +
    4.59 +<!ELEMENT memory EMPTY> 
    4.60 +<!ATTLIST memory static_min      CDATA #REQUIRED
    4.61 +                 static_max      CDATA #REQUIRED
    4.62 +                 dynamic_min     CDATA #REQUIRED 
    4.63 +                 dynamic_max     CDATA #REQUIRED> 
    4.64 +
    4.65 +<!ELEMENT vbd    (qos_algorithm_param*)> 
    4.66 +<!ATTLIST vbd    %NAMEID; 
    4.67 +                 mode            (RO | RW)   #REQUIRED 
    4.68 +                 vdi             IDREF       #REQUIRED
    4.69 +                 device          CDATA       #REQUIRED
    4.70 +                 bootable        CDATA       #REQUIRED
    4.71 +                 type            (CD | disk) #REQUIRED
    4.72 +                 qos_algorithm_type CDATA #REQUIRED> 
    4.73 +
    4.74 +<!ELEMENT vif    (qos_algorithm_param*)>
    4.75 +<!ATTLIST vif    %NAMEID; 
    4.76 +                 mac             CDATA       #REQUIRED 
    4.77 +                 mtu             CDATA       #REQUIRED
    4.78 +                 device          CDATA       #REQUIRED
    4.79 +                 qos_algorithm_type CDATA    #REQUIRED
    4.80 +                 bridge          CDATA       #IMPLIED
    4.81 +                 network         CDATA       #IMPLIED> 
    4.82 +
    4.83 +<!ELEMENT pv     EMPTY>
    4.84 +<!ATTLIST pv     kernel          CDATA #REQUIRED
    4.85 +                 bootloader      CDATA #REQUIRED
    4.86 +                 ramdisk         CDATA #REQUIRED
    4.87 +                 args            CDATA #REQUIRED
    4.88 +                 bootloader_args CDATA #REQUIRED>
    4.89 +
    4.90 +<!ELEMENT hvm    (boot_param*)>
    4.91 +<!ATTLIST hvm    boot_policy     CDATA #REQUIRED>
    4.92 +
    4.93 +<!ELEMENT boot_param EMPTY>
    4.94 +<!ATTLIST boot_param key         CDATA #REQUIRED
    4.95 +                     value       CDATA #REQUIRED>
    4.96 +
    4.97 +<!ELEMENT vdi    (name)> 
    4.98 +<!ATTLIST vdi    %NAMEID; 
    4.99 +                 src             %URI; #REQUIRED
   4.100 +                 type            %VDI_TYPE; #REQUIRED
   4.101 +                 size            CDATA #REQUIRED
   4.102 +                 shareable       CDATA #REQUIRED
   4.103 +                 read_only       CDATA #REQUIRED>
   4.104 +
   4.105 +<!ELEMENT name   (label, 
   4.106 +                  description)> 
   4.107 +
   4.108 +<!ELEMENT label  (#PCDATA)> 
   4.109 +<!ELEMENT description (#PCDATA)>
   4.110 +
   4.111 +<!ELEMENT vcpu_param EMPTY>
   4.112 +<!ATTLIST vcpu_param key   CDATA #REQUIRED
   4.113 +                     value CDATA #REQUIRED>
   4.114 +
   4.115 +<!ELEMENT other_config EMPTY>
   4.116 +<!ATTLIST other_config key   CDATA #REQUIRED
   4.117 +                      value CDATA #REQUIRED>
   4.118 +
   4.119 +<!ELEMENT qos_algorithm_param EMPTY>
   4.120 +<!ATTLIST qos_algorithm_param key   CDATA #REQUIRED
   4.121 +                              value CDATA #REQUIRED>
     5.1 --- a/tools/python/xen/xm/create.py	Sat Mar 17 23:57:17 2007 +0000
     5.2 +++ b/tools/python/xen/xm/create.py	Sat Mar 17 23:59:05 2007 +0000
     5.3 @@ -28,12 +28,14 @@ import time
     5.4  import xmlrpclib
     5.5  
     5.6  from xen.xend import sxp
     5.7 -from xen.xend import PrettyPrint
     5.8 +from xen.xend import PrettyPrint as SXPPrettyPrint
     5.9  from xen.xend import osdep
    5.10  import xen.xend.XendClient
    5.11  from xen.xend.XendBootloader import bootloader
    5.12  from xen.util import blkif
    5.13  from xen.util import security
    5.14 +from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
    5.15 +from xen.xm.xenapi_create import sxp2xml, xenapi_create
    5.16  
    5.17  from xen.xm.opts import *
    5.18  
    5.19 @@ -98,6 +100,11 @@ gopts.opt('dryrun', short='n',
    5.20            use="Dry run - prints the resulting configuration in SXP but "
    5.21            "does not create the domain.")
    5.22  
    5.23 +gopts.opt('xmldryrun', short='x',
    5.24 +          fn=set_true, default=0,
    5.25 +          use="XML dry run - prints the resulting configuration in XML but "
    5.26 +          "does not create the domain.")
    5.27 +
    5.28  gopts.opt('paused', short='p',
    5.29            fn=set_true, default=0,
    5.30            use='Leave the domain paused after it is created.')
    5.31 @@ -1241,34 +1248,57 @@ def main(argv):
    5.32          except IOError, exn:
    5.33              raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
    5.34  
    5.35 +    if serverType == SERVER_XEN_API:
    5.36 +        sxp2xml_inst = sxp2xml()
    5.37 +        doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
    5.38 +
    5.39      if opts.vals.dryrun:
    5.40 -        PrettyPrint.prettyprint(config)
    5.41 +        SXPPrettyPrint.prettyprint(config)
    5.42 +
    5.43 +    if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
    5.44 +        from xml.dom.ext import PrettyPrint as XMLPrettyPrint
    5.45 +        XMLPrettyPrint(doc)
    5.46 +
    5.47 +    if opts.vals.dryrun or opts.vals.xmldryrun:
    5.48 +        return                                               
    5.49 +
    5.50 +    if opts.vals.console_autoconnect:
    5.51 +        do_console(sxp.child_value(config, 'name', -1))
    5.52 +    
    5.53 +    if serverType == SERVER_XEN_API:        
    5.54 +        xenapi_create_inst = xenapi_create()
    5.55 +        vm_refs = xenapi_create_inst.create(document = doc)
    5.56 +
    5.57 +        map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
    5.58      else:
    5.59          if not create_security_check(config):
    5.60 -            raise security.ACMError('Security Configuration prevents domain from starting')
    5.61 -        else:
    5.62 -            if opts.vals.console_autoconnect:
    5.63 -                cpid = os.fork() 
    5.64 -                if cpid != 0:
    5.65 -                    for i in range(10):
    5.66 -                        # Catch failure of the create process 
    5.67 -                        time.sleep(1)
    5.68 -                        (p, rv) = os.waitpid(cpid, os.WNOHANG)
    5.69 -                        if os.WIFEXITED(rv):
    5.70 -                            if os.WEXITSTATUS(rv) != 0:
    5.71 -                                sys.exit(os.WEXITSTATUS(rv))
    5.72 -                        try:
    5.73 -                            # Acquire the console of the created dom
    5.74 -                            name = sxp.child_value(config, 'name', -1)
    5.75 -                            dom = server.xend.domain(name)
    5.76 -                            domid = int(sxp.child_value(dom, 'domid', '-1'))
    5.77 -                            console.execConsole(domid)
    5.78 -                        except:
    5.79 -                            pass
    5.80 -                    print("Could not start console\n");
    5.81 -                    sys.exit(0)
    5.82 -            dom = make_domain(opts, config)
    5.83 -
    5.84 +            raise security.ACMError(
    5.85 +                'Security Configuration prevents domain from starting')
    5.86 +        dom = make_domain(opts, config)
    5.87 +        
    5.88 +def do_console(domain_name):
    5.89 +    cpid = os.fork() 
    5.90 +    if cpid != 0:
    5.91 +        for i in range(10):
    5.92 +            # Catch failure of the create process 
    5.93 +            time.sleep(1)
    5.94 +            (p, rv) = os.waitpid(cpid, os.WNOHANG)
    5.95 +            if os.WIFEXITED(rv):
    5.96 +                if os.WEXITSTATUS(rv) != 0:
    5.97 +                    sys.exit(os.WEXITSTATUS(rv))
    5.98 +            try:
    5.99 +                # Acquire the console of the created dom
   5.100 +                if serverType == SERVER_XEN_API:
   5.101 +                    domid = server.xenapi.VM.get_domid(
   5.102 +                               get_single_vm(domain_name))
   5.103 +                else:
   5.104 +                    dom = server.xend.domain(name)
   5.105 +                    domid = int(sxp.child_value(dom, 'domid', '-1'))
   5.106 +                console.execConsole(domid)
   5.107 +            except:
   5.108 +                pass
   5.109 +        print("Could not start console\n");
   5.110 +        sys.exit(0)
   5.111  
   5.112  if __name__ == '__main__':
   5.113      main(sys.argv)
     6.1 --- a/tools/python/xen/xm/new.py	Sat Mar 17 23:57:17 2007 +0000
     6.2 +++ b/tools/python/xen/xm/new.py	Sat Mar 17 23:59:05 2007 +0000
     6.3 @@ -22,6 +22,9 @@ from xen.xend import PrettyPrint
     6.4  from xen.xend import sxp
     6.5  from xen.xend import XendClient
     6.6  
     6.7 +from xen.xm.main import serverType, SERVER_XEN_API
     6.8 +from xen.xm.xenapi_create import *
     6.9 +
    6.10  from opts import *
    6.11  from create import *
    6.12  
    6.13 @@ -65,7 +68,15 @@ def main(argv):
    6.14  
    6.15      if opts.vals.dryrun:
    6.16          PrettyPrint.prettyprint(config)
    6.17 -    else:
    6.18 +        return
    6.19 +    
    6.20 +    if serverType == SERVER_XEN_API:
    6.21 +        sxp2xml_inst = sxp2xml()
    6.22 +        doc = sxp2xml_inst.convert_sxp_to_xml(config) 
    6.23 +        
    6.24 +        xenapi_create_inst = xenapi_create()
    6.25 +        vm_refs = xenapi_create_inst.create(document = doc)
    6.26 +    else:       
    6.27          make_unstarted_domain(opts, config)
    6.28          
    6.29  if __name__ == '__main__':
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/python/xen/xm/xenapi_create.py	Sat Mar 17 23:59:05 2007 +0000
     7.3 @@ -0,0 +1,634 @@
     7.4 +#!/usr/bin/python
     7.5 +#============================================================================
     7.6 +# This library is free software; you can redistribute it and/or
     7.7 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
     7.8 +# License as published by the Free Software Foundation.
     7.9 +#
    7.10 +# This library is distributed in the hope that it will be useful,
    7.11 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.12 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    7.13 +# Lesser General Public License for more details.
    7.14 +#
    7.15 +# You should have received a copy of the GNU Lesser General Public
    7.16 +# License along with this library; if not, write to the Free Software
    7.17 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.18 +#============================================================================
    7.19 +# Copyright (C) 2007 Tom Wilkie <tom.wilkie@gmail.com>
    7.20 +#============================================================================
    7.21 +"""Domain creation using new XenAPI
    7.22 +"""
    7.23 +
    7.24 +from xen.xm.main import server
    7.25 +from xml.dom.minidom import parse, getDOMImplementation
    7.26 +from xml.dom.ext import PrettyPrint
    7.27 +from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
    7.28 +from xen.xend import sxp
    7.29 +from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
    7.30 +     XEN_API_ON_CRASH_BEHAVIOUR
    7.31 +
    7.32 +
    7.33 +import sys
    7.34 +import os
    7.35 +import traceback
    7.36 +
    7.37 +def log(_, msg):
    7.38 +    #print "> " + msg
    7.39 +    pass
    7.40 +
    7.41 +DEBUG = 0
    7.42 +
    7.43 +def get_name_label(node):
    7.44 +    name_node = node.getElementsByTagName("name")[0]
    7.45 +    label_node = name_node.getElementsByTagName("label")[0]
    7.46 +    return " ".join([child.nodeValue for child in label_node.childNodes])
    7.47 +
    7.48 +def get_name_description(node):
    7.49 +    name_node = node.getElementsByTagName("name")[0]
    7.50 +    description_node = name_node.getElementsByTagName("description")[0]
    7.51 +    return " ".join([child.nodeValue for child in description_node.childNodes])
    7.52 +
    7.53 +def get_text_in_child_node(node, child):
    7.54 +    tag_node = node.getElementsByTagName(child)[0]
    7.55 +    return tag_node.nodeValue
    7.56 +
    7.57 +def get_child_node_attribute(node, child, attribute):
    7.58 +    tag_node = node.getElementsByTagName(child)[0]
    7.59 +    return tag_node.attributes[attribute].value
    7.60 +
    7.61 +def get_child_nodes_as_dict(node, child_name,
    7.62 +                            key_attribute_name,
    7.63 +                            value_attribute_name):
    7.64 +    return dict([(child.attributes[key_attribute_name].value,
    7.65 +                  child.attributes[value_attribute_name].value)
    7.66 +                 for child in node.getElementsByTagName(child_name)])
    7.67 +
    7.68 +def try_quietly(fn, *args):
    7.69 +    try:
    7.70 +        return fn(*args)
    7.71 +    except:
    7.72 +        return None
    7.73 +
    7.74 +class xenapi_create:
    7.75 +
    7.76 +    def __init__(self):
    7.77 +        self.DEFAULT_STORAGE_REPOSITORY = [sr_ref
    7.78 +                  for sr_ref in server.xenapi.SR.get_all()
    7.79 +                  if server.xenapi.SR.get_type(sr_ref) == "local"][0]
    7.80 +
    7.81 +        self.dtd = "/usr/lib/python/xen/xm/create.dtd"
    7.82 +
    7.83 +    def create(self, filename=None, document=None):
    7.84 +        """
    7.85 +        Create a domain from an XML file or DOM tree
    7.86 +        """
    7.87 +        if filename is not None:
    7.88 +            self.check_dtd(file)
    7.89 +            document = parse(file)
    7.90 +        elif document is not None:
    7.91 +            self.check_dom_against_dtd(document)
    7.92 +
    7.93 +        self.check_doc(document)
    7.94 +
    7.95 +        vdis = document.getElementsByTagName("vdi")
    7.96 +        vdi_refs_dict = self.create_vdis(vdis)
    7.97 +        
    7.98 +        try:    
    7.99 +            vms = document.getElementsByTagName("vm")
   7.100 +            return self.create_vms(vms, vdi_refs_dict)
   7.101 +        except Exception, exn:
   7.102 +            try_quietly(self.cleanup_vdis(vdi_refs_dict))
   7.103 +            raise exn
   7.104 +
   7.105 +    # Methods to check xml file
   7.106 +    # try to use dtd to check where possible
   7.107 +    def check_dtd(self, file):
   7.108 +        """
   7.109 +        Check file against DTD.
   7.110 +        Use this if possible as it gives nice
   7.111 +        error messages
   7.112 +        """
   7.113 +        dtd = xmldtd.load_dtd(self.dtd)
   7.114 +        parser = xmlproc.XMLProcessor()
   7.115 +        parser.set_application(xmlval.ValidatingApp(dtd, parser))
   7.116 +        parser.dtd = dtd
   7.117 +        parser.ent = dtd
   7.118 +        parser.parse_resource(file)
   7.119 +
   7.120 +    def check_dom_against_dtd(self, dom):
   7.121 +        """
   7.122 +        Check DOM again DTD.
   7.123 +        Doesn't give as nice error messages.
   7.124 +        (no location info)
   7.125 +        """
   7.126 +        dtd = xmldtd.load_dtd(self.dtd)
   7.127 +        app = xmlval.ValidatingApp(dtd, self)
   7.128 +        app.set_locator(self)
   7.129 +        self.dom2sax(dom, app)
   7.130 +
   7.131 +    # Get errors back from ValidatingApp       
   7.132 +    def report_error(self, number, args=None):
   7.133 +        self.errors = xmlproc.errors.english
   7.134 +        try:
   7.135 +            msg = self.errors[number]
   7.136 +            if args != None:
   7.137 +                msg = msg % args
   7.138 +        except KeyError:
   7.139 +            msg = self.errors[4002] % number # Unknown err msg :-)
   7.140 +        print msg 
   7.141 +        sys.exit(-1)
   7.142 +
   7.143 +    # Here for compatibility with ValidatingApp
   7.144 +    def get_line(self):
   7.145 +        return -1
   7.146 +
   7.147 +    def get_column(self):
   7.148 +        return -1
   7.149 +
   7.150 +    def dom2sax(self, dom, app):
   7.151 +        """
   7.152 +        Take a dom tree and tarverse it,
   7.153 +        issuing SAX calls to app.
   7.154 +        """
   7.155 +        for child in dom.childNodes:
   7.156 +            if child.nodeType == child.TEXT_NODE:
   7.157 +                data = child.nodeValue
   7.158 +                app.handle_data(data, 0, len(data))
   7.159 +            else:
   7.160 +                app.handle_start_tag(
   7.161 +                    child.nodeName,
   7.162 +                    self.attrs_to_dict(child.attributes))
   7.163 +                self.dom2sax(child, app)
   7.164 +                app.handle_end_tag(child.nodeName)
   7.165 +
   7.166 +    def attrs_to_dict(self, attrs):
   7.167 +        return dict(attrs.items())     
   7.168 +
   7.169 +    #
   7.170 +    # Checks which cannot be done with dtd
   7.171 +    #
   7.172 +    def check_doc(self, doc):
   7.173 +        vms = doc.getElementsByTagName("vm")
   7.174 +        self.check_vms(vms)
   7.175 +
   7.176 +    def check_vms(self, vms):
   7.177 +        map(self.check_vm, vms)
   7.178 +
   7.179 +    def check_vm(self, vm):
   7.180 +        vifs = vm.getElementsByTagName("vif")
   7.181 +        self.check_vifs(vifs)
   7.182 +
   7.183 +    def check_vifs(self, vifs):
   7.184 +        map(self.check_vif, vifs)
   7.185 +
   7.186 +    def check_vif(self, vif):
   7.187 +        """
   7.188 +        Check that the vif has
   7.189 +        either a bridge or network
   7.190 +        name but not both
   7.191 +        """
   7.192 +        if "bridge" in vif.attributes.keys() \
   7.193 +               and "network" in vif.attributes.keys():
   7.194 +            raise "You cannot specify both a bridge and\
   7.195 +                   a network name."
   7.196 +
   7.197 +    # Cleanup methods here
   7.198 +    def cleanup_vdis(self, vdi_refs_dict):
   7.199 +        map(self.cleanup_vdi, vdi_refs_dict.values())
   7.200 +
   7.201 +    def cleanup_vdi(self, vdi_ref):
   7.202 +        server.xenapi.VDI.destroy(vdi_ref)
   7.203 +
   7.204 +    def cleanup_vms(self, vm_refs):
   7.205 +        map(self.cleanup_vm, vm_refs)
   7.206 +
   7.207 +    def cleanup_vm(self, vm_ref):
   7.208 +        server.xenapi.VM.destroy(vm_ref)
   7.209 +
   7.210 +    # Create methods here
   7.211 +    def create_vdis(self, vdis):
   7.212 +        log(DEBUG, "create_vdis")
   7.213 +        return dict(map(self.create_vdi, vdis))
   7.214 +
   7.215 +    def create_vdi(self, vdi):
   7.216 +        log(DEBUG, "create_vdi")
   7.217 +
   7.218 +        vdi_record = {
   7.219 +            "name_label":       get_name_label(vdi),
   7.220 +            "name_description": get_name_description(vdi),
   7.221 +            "SR":               self.DEFAULT_STORAGE_REPOSITORY,  
   7.222 +            "virtual_size":     vdi.attributes["size"].value,
   7.223 +            "type":             vdi.attributes["type"].value,
   7.224 +            "shareable":        vdi.attributes["shareable"].value,
   7.225 +            "read_only":        vdi.attributes["read_only"].value,
   7.226 +            "other_config":     {"location":
   7.227 +                vdi.attributes["src"].value}
   7.228 +            }
   7.229 +
   7.230 +        key = vdi.attributes["name"].value
   7.231 +        value = server.xenapi.VDI.create(vdi_record)
   7.232 +        
   7.233 +        return (key, value)
   7.234 +
   7.235 +    def create_vms(self, vms, vdis):
   7.236 +        log(DEBUG, "create_vms")
   7.237 +        return map(lambda vm: self.create_vm(vm, vdis), vms)
   7.238 +
   7.239 +    def create_vm(self, vm, vdis):
   7.240 +        log(DEBUG, "create_vm")
   7.241 +
   7.242 +        vm_record = {
   7.243 +            "name_label":
   7.244 +                get_name_label(vm),
   7.245 +            "name_description":
   7.246 +                get_name_description(vm),
   7.247 +            "user_version":
   7.248 +                get_text_in_child_node(vm, "version"),
   7.249 +            "is_a_template":
   7.250 +                vm.attributes["is_a_template"].value,
   7.251 +            "auto_power_on":
   7.252 +                vm.attributes["auto_power_on"].value,
   7.253 +            "memory_static_max":
   7.254 +                get_child_node_attribute(vm, "memory", "static_max"),
   7.255 +            "memory_static_min":
   7.256 +                get_child_node_attribute(vm, "memory", "static_min"),
   7.257 +            "memory_dynamic_max":
   7.258 +                get_child_node_attribute(vm, "memory", "dynamic_max"),
   7.259 +            "memory_dynamic_min":
   7.260 +                get_child_node_attribute(vm, "memory", "dynamic_min"),
   7.261 +            "vcpus_params":
   7.262 +                get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
   7.263 +            "vcpus_max":
   7.264 +                vm.attributes["vcpus_max"].value,
   7.265 +            "vcpus_at_startup":
   7.266 +                vm.attributes["vcpus_at_startup"].value,
   7.267 +            "actions_after_shutdown":
   7.268 +                vm.attributes["actions_after_shutdown"].value,
   7.269 +            "actions_after_reboot":
   7.270 +                vm.attributes["actions_after_reboot"].value,
   7.271 +            "actions_after_crash":
   7.272 +                vm.attributes["actions_after_crash"].value,
   7.273 +            "platform_std_VGA":
   7.274 +                vm.attributes["platform_std_VGA"].value,
   7.275 +            "platform_serial":
   7.276 +                vm.attributes["platform_serial"].value,
   7.277 +            "platform_localtime":
   7.278 +                vm.attributes["platform_localtime"].value,
   7.279 +            "platform_clock_offet":
   7.280 +                vm.attributes["platform_clock_offet"].value,
   7.281 +            "platform_enable_audio":
   7.282 +                vm.attributes["platform_enable_audio"].value,
   7.283 +            "PCI_bus":
   7.284 +                vm.attributes["platform_enable_audio"].value,
   7.285 +            "other_config":
   7.286 +                get_child_nodes_as_dict(vm, "other_config", "key", "value")
   7.287 +            }
   7.288 +
   7.289 +        if len(vm.getElementsByTagName("pv")) > 0:
   7.290 +            vm_record.update({
   7.291 +                "PV_bootloader":
   7.292 +                    get_child_node_attribute(vm, "pv", "bootloader"),
   7.293 +                "PV_kernel":
   7.294 +                    get_child_node_attribute(vm, "pv", "kernel"),
   7.295 +                "PV_ramdisk":
   7.296 +                    get_child_node_attribute(vm, "pv", "ramdisk"),
   7.297 +                "PV_args":
   7.298 +                    get_child_node_attribute(vm, "pv", "args"),
   7.299 +                "PV_bootloader_args":
   7.300 +                    get_child_node_attribute(vm, "pv", "bootloader_args")
   7.301 +                })
   7.302 +        else:
   7.303 +            hvm = vm.getElementsByTagName("hvm")[0]
   7.304 +            vm_record.update({
   7.305 +                "HVM_boot_policy":
   7.306 +                    get_child_node_attribute(vm, "hvm", "boot_policy"),
   7.307 +                "HVM_boot_params":
   7.308 +                    get_child_nodes_as_dict(hvm, "boot_params", "key", "value")
   7.309 +                })
   7.310 +        try:
   7.311 +            vm_ref = server.xenapi.VM.create(vm_record)
   7.312 +        except:
   7.313 +            traceback.print_exc()
   7.314 +            sys.exit(-1)
   7.315 +
   7.316 +        # Now create vbds
   7.317 +
   7.318 +        vbds = vm.getElementsByTagName("vbd")
   7.319 +
   7.320 +        self.create_vbds(vm_ref, vbds, vdis)
   7.321 +
   7.322 +        # Now create vifs
   7.323 +
   7.324 +        vifs = vm.getElementsByTagName("vif")
   7.325 +
   7.326 +        self.create_vifs(vm_ref, vifs)
   7.327 +
   7.328 +        return vm_ref
   7.329 +        
   7.330 +    def create_vbds(self, vm_ref, vbds, vdis):
   7.331 +        log(DEBUG, "create_vbds")
   7.332 +        return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
   7.333 +
   7.334 +    def create_vbd(self, vm_ref, vbd, vdis):
   7.335 +        log(DEBUG, "create_vbd")
   7.336 +
   7.337 +        vbd_record = {
   7.338 +            "VM":
   7.339 +                vm_ref,
   7.340 +            "VDI":
   7.341 +                vdis[vbd.attributes["vdi"].value],
   7.342 +            "device":
   7.343 +                vbd.attributes["device"].value,
   7.344 +            "bootable":
   7.345 +                vbd.attributes["bootable"].value,
   7.346 +            "mode":
   7.347 +                vbd.attributes["mode"].value,
   7.348 +            "type":
   7.349 +                vbd.attributes["type"].value,
   7.350 +            "qos_algorithm_type":
   7.351 +                vbd.attributes["qos_algorithm_type"].value,
   7.352 +            "qos_algorithm_params":
   7.353 +                get_child_nodes_as_dict(vbd,
   7.354 +                  "qos_algorithm_param", "key", "value")
   7.355 +            }
   7.356 +
   7.357 +        return server.xenapi.VBD.create(vbd_record)
   7.358 +
   7.359 +    def create_vifs(self, vm_ref, vifs):
   7.360 +        log(DEBUG, "create_vifs")
   7.361 +        return map(lambda vif: self.create_vif(vm_ref, vif), vifs)
   7.362 +
   7.363 +    def create_vif(self, vm_ref, vif):
   7.364 +        log(DEBUG, "create_vif")
   7.365 +
   7.366 +        if "bridge" in vif.attributes.keys():
   7.367 +            raise "Not allowed to add by bridge just yet"
   7.368 +        elif "network" in vif.attributes.keys():
   7.369 +            network = [network_ref
   7.370 +                for network_ref in server.xenapi.network.get_all()
   7.371 +                if server.xenapi.network.get_name_label(network_ref)
   7.372 +                       == vif.attributes["network"].value][0]
   7.373 +        else:
   7.374 +            network = self._get_network_ref()
   7.375 +
   7.376 +        vif_record = {
   7.377 +            "device":
   7.378 +                vif.attributes["device"].value,
   7.379 +            "network":
   7.380 +                network,
   7.381 +            "VM":
   7.382 +                vm_ref,
   7.383 +            "MAC":
   7.384 +                vif.attributes["mac"].value,
   7.385 +            "MTU":
   7.386 +                vif.attributes["mtu"].value,
   7.387 +            "qos_algorithm_type":
   7.388 +                vif.attributes["qos_algorithm_type"].value,
   7.389 +            "qos_algorithm_params":
   7.390 +                get_child_nodes_as_dict(vif,
   7.391 +                    "qos_algorithm_param", "key", "value")
   7.392 +        }
   7.393 +
   7.394 +        return server.xenapi.VIF.create(vif_record)
   7.395 +
   7.396 +    _network_refs = []
   7.397 +
   7.398 +    def _get_network_ref(self):
   7.399 +        try:
   7.400 +            return self._network_refs.pop(0)
   7.401 +        except IndexError:
   7.402 +            self._network_refs = server.xenapi.network.get_all()
   7.403 +            return self._network_refs.pop(0)
   7.404 +
   7.405 +def get_child_by_name(exp, childname, default = None):
   7.406 +    try:
   7.407 +        return [child for child in sxp.children(exp)
   7.408 +                if child[0] == childname][0][1]
   7.409 +    except:
   7.410 +        return default
   7.411 +
   7.412 +# Convert old sxp into new xml
   7.413 +
   7.414 +class sxp2xml:
   7.415 +
   7.416 +    def convert_sxp_to_xml(self, config, transient=False):
   7.417 +       
   7.418 +        devices = [child for child in sxp.children(config)
   7.419 +                   if len(child) > 0 and child[0] == "device"]
   7.420 +                   
   7.421 +        vbds_sxp = map(lambda x: x[1], [device for device in devices
   7.422 +                                        if device[1][0] == "vbd"])
   7.423 +
   7.424 +        vifs_sxp = map(lambda x: x[1], [device for device in devices
   7.425 +                                        if device[1][0] == "vif"])
   7.426 +        # Create XML Document
   7.427 +        
   7.428 +        impl = getDOMImplementation()
   7.429 +
   7.430 +        document = impl.createDocument(None, "xm", None)
   7.431 +
   7.432 +        # Lets make the VM tag..
   7.433 +
   7.434 +        vm = document.createElement("vm")
   7.435 +
   7.436 +        # Some string compatibility
   7.437 +
   7.438 +        actions_after_shutdown \
   7.439 +            = get_child_by_name(config, "on_poweroff", "destroy")
   7.440 +        actions_after_reboot \
   7.441 +            = get_child_by_name(config, "on_reboot", "restart")
   7.442 +        actions_after_crash \
   7.443 +            = get_child_by_name(config, "on_crash", "restart")
   7.444 +
   7.445 +        def conv_chk(val, vals):
   7.446 +            val.replace("-", "_")
   7.447 +            if val not in vals:
   7.448 +                raise "Invalid value: " + val
   7.449 +            else:
   7.450 +                return val
   7.451 +
   7.452 +        actions_after_shutdown = conv_chk(actions_after_shutdown,\
   7.453 +                                          XEN_API_ON_NORMAL_EXIT)
   7.454 +        actions_after_reboot   = conv_chk(actions_after_reboot, \
   7.455 +                                          XEN_API_ON_NORMAL_EXIT)
   7.456 +        actions_after_crash    = conv_chk(actions_after_crash, \
   7.457 +                                          XEN_API_ON_CRASH_BEHAVIOUR)
   7.458 +        # Flesh out tag attributes            
   7.459 +
   7.460 +        vm.attributes["is_a_template"] = "false"
   7.461 +        vm.attributes["auto_power_on"] = "false"
   7.462 +        vm.attributes["actions_after_shutdown"] \
   7.463 +            = actions_after_shutdown              
   7.464 +        vm.attributes["actions_after_reboot"] \
   7.465 +            = actions_after_reboot
   7.466 +        vm.attributes["actions_after_crash"] \
   7.467 +            = actions_after_crash
   7.468 +        vm.attributes["platform_std_VGA"] = "false"
   7.469 +        vm.attributes["platform_serial"] = ""
   7.470 +        vm.attributes["platform_localtime"] = ""
   7.471 +        vm.attributes["platform_clock_offet"] = ""
   7.472 +        vm.attributes["platform_enable_audio"] = ""
   7.473 +        vm.attributes["PCI_bus"] = ""
   7.474 +
   7.475 +        vm.attributes["vcpus_max"] \
   7.476 +            = str(get_child_by_name(config, "vcpus", 1))
   7.477 +        vm.attributes["vcpus_at_startup"] \
   7.478 +            = str(get_child_by_name(config, "vcpus", 1))
   7.479 +
   7.480 +        # Make the name tag
   7.481 +
   7.482 +        vm.appendChild(self.make_name_tag(
   7.483 +            get_child_by_name(config, "name"), document))
   7.484 +
   7.485 +        # Make version tag
   7.486 +
   7.487 +        version = document.createElement("version")
   7.488 +        version.appendChild(document.createTextNode("1.0"))
   7.489 +        vm.appendChild(version)
   7.490 +        
   7.491 +        # Make pv or hvm tag
   7.492 +
   7.493 +        image = get_child_by_name(config, "image")
   7.494 +
   7.495 +        if image[0] == "linux":
   7.496 +            pv = document.createElement("pv")
   7.497 +            pv.attributes["kernel"] \
   7.498 +                = get_child_by_name(image, "kernel", "")
   7.499 +            pv.attributes["bootloader"] = ""
   7.500 +            pv.attributes["ramdisk"] \
   7.501 +                = get_child_by_name(image, "ramdisk", "")
   7.502 +            pv.attributes["args"] \
   7.503 +                = "root=" + get_child_by_name(image, "root", "") \
   7.504 +                + " " + get_child_by_name(image, "args", "")
   7.505 +            pv.attributes["bootloader_args"] = ""
   7.506 +
   7.507 +            vm.appendChild(pv)
   7.508 +        elif image[0] == "hvm":
   7.509 +            hvm = document.createElement("hvm")
   7.510 +            hvm.attributes["boot_policy"] = ""
   7.511 +
   7.512 +            vm.appendChild(hvm)
   7.513 +
   7.514 +        # Make memory tag
   7.515 +
   7.516 +        memory = document.createElement("memory")
   7.517 +
   7.518 +        memory_str = str(int(
   7.519 +            get_child_by_name(config, "memory"))*1024*1024)
   7.520 +
   7.521 +        memory.attributes["static_min"] = memory_str
   7.522 +        memory.attributes["static_max"] = memory_str
   7.523 +        memory.attributes["dynamic_min"] = memory_str
   7.524 +        memory.attributes["dynamic_max"] = memory_str
   7.525 +
   7.526 +        vm.appendChild(memory)
   7.527 +
   7.528 +        # And now the vbds
   7.529 +
   7.530 +        vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
   7.531 +
   7.532 +        map(vm.appendChild, vbds)
   7.533 +
   7.534 +        # And now the vifs
   7.535 +
   7.536 +        vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
   7.537 +
   7.538 +        map(vm.appendChild, vifs)
   7.539 +
   7.540 +        # transient?
   7.541 +
   7.542 +        if transient:
   7.543 +            other_config = document.createElement("other_config")
   7.544 +            other_config.attributes["key"] = "transient"
   7.545 +            other_config.attributes["value"] = "True"
   7.546 +            vm.appendChild(other_config)
   7.547 +        
   7.548 +        # Add it to doc_root
   7.549 +
   7.550 +        document.documentElement.appendChild(vm)
   7.551 +        
   7.552 +        # We want to pull out vdis
   7.553 +
   7.554 +        vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
   7.555 +
   7.556 +        map(document.documentElement.appendChild, vdis)
   7.557 +
   7.558 +        return document
   7.559 +
   7.560 +    def make_name_tag(self, label_text, document):
   7.561 +        name = document.createElement("name")
   7.562 +
   7.563 +        label = document.createElement("label")
   7.564 +        label.appendChild(document.createTextNode(str(label_text)))
   7.565 +        name.appendChild(label)
   7.566 +
   7.567 +        description = document.createElement("description")
   7.568 +        description.appendChild(document.createTextNode(" "))
   7.569 +        name.appendChild(description)
   7.570 +
   7.571 +        return name
   7.572 +
   7.573 +    def extract_vbd(self, vbd_sxp, document):
   7.574 +        src = get_child_by_name(vbd_sxp, "uname")
   7.575 +        name = str(src.__hash__())
   7.576 +
   7.577 +        vbd = document.createElement("vbd")
   7.578 +
   7.579 +        vbd.attributes["name"] = "vdb" + name
   7.580 +        vbd.attributes["vdi"] = "vdi" + name
   7.581 +        vbd.attributes["mode"] \
   7.582 +            = get_child_by_name(vbd_sxp, "mode") != "w" \
   7.583 +              and "RO" or "RW"
   7.584 +        vbd.attributes["device"] \
   7.585 +            = get_child_by_name(vbd_sxp, "dev")
   7.586 +        vbd.attributes["bootable"] = "1"
   7.587 +        vbd.attributes["type"] = "disk"
   7.588 +        vbd.attributes["qos_algorithm_type"] = ""
   7.589 +
   7.590 +        return vbd
   7.591 +
   7.592 +    def extract_vdi(self, vbd_sxp, document):
   7.593 +        src = get_child_by_name(vbd_sxp, "uname")
   7.594 +        name = "vdi" + str(src.__hash__())
   7.595 +        path = src[src.find(":")+1:]
   7.596 +
   7.597 +        vdi = document.createElement("vdi")
   7.598 +
   7.599 +        vdi.attributes["src"] = src
   7.600 +        vdi.attributes["read_only"] \
   7.601 +            = (get_child_by_name(vbd_sxp, "mode") != "w") \
   7.602 +               and "true" or "false"
   7.603 +        vdi.attributes["size"] \
   7.604 +            = str(os.path.getsize(path))
   7.605 +        vdi.attributes["type"] = "system"
   7.606 +        vdi.attributes["shareable"] = "false"
   7.607 +        vdi.attributes["name"] = name
   7.608 +
   7.609 +        vdi.appendChild(self.make_name_tag(name, document))
   7.610 +
   7.611 +        return vdi
   7.612 +
   7.613 +    def extract_vif(self, vif_sxp, document):
   7.614 +
   7.615 +        vif = document.createElement("vif")
   7.616 +
   7.617 +        dev = get_child_by_name(vif_sxp, "vifname", "eth0")
   7.618 +
   7.619 +        vif.attributes["name"] \
   7.620 +            = "vif" + str(dev.__hash__())
   7.621 +        vif.attributes["mac"] \
   7.622 +            = get_child_by_name(vif_sxp, "mac", "")               
   7.623 +        vif.attributes["mtu"] \
   7.624 +            = get_child_by_name(vif_sxp, "mtu", "")  
   7.625 +        vif.attributes["device"] = dev
   7.626 +        vif.attributes["qos_algorithm_type"] = ""
   7.627 +
   7.628 +        if get_child_by_name(vif_sxp, "bridge") is not None:
   7.629 +            vif.attributes["bridge"] \
   7.630 +                = get_child_by_name(vif_sxp, "bridge")
   7.631 +        
   7.632 +        return vif
   7.633 +
   7.634 +
   7.635 +
   7.636 +
   7.637 +