ia64/xen-unstable
changeset 14456:6b2875302558
Support xm create through the Xen-API.
Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
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 +