Support xm create through the Xen-API.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
This commit is contained in:
Ewan Mellor committed 2007-03-17 23:59:05 +00:00
1 parent c0767e1cc9
commit 61fd72f748
7 files changed
+939 -68

No files matched your search

+76 -29
View File
@@ -105,8 +105,6 @@ XENAPI_CFG_TO_LEGACY_CFG = {
'uuid': 'uuid',
'vcpus_number': 'vcpus',
'cpus': 'cpus',
'memory_static_min': 'memory',
'memory_static_max': 'maxmem',
'name_label': 'name',
'actions_after_shutdown': 'on_poweroff',
'actions_after_reboot': 'on_reboot',
@@ -136,11 +134,10 @@ XENAPI_CFG_TYPES = {
'user_version': str,
'is_a_template': bool0,
'resident_on': str,
'memory_static_min': int,
'memory_static_min': int, # note these are stored in bytes, not KB!
'memory_static_max': int,
'memory_dynamic_min': int,
'memory_dynamic_max': int,
'memory_actual': int,
'cpus': list,
'vcpus_policy': str,
'vcpus_params': dict,
@@ -314,7 +311,6 @@ class XendConfig(dict):
'shadow_memory': 0,
'memory_static_max': 0,
'memory_dynamic_max': 0,
'memory_actual': 0,
'devices': {},
'security': None,
'on_xend_start': 'ignore',
@@ -334,20 +330,39 @@ class XendConfig(dict):
return defaults
#
# Here we assume these values exist in the dict.
# If they don't we have a bigger problem, lets not
# try and 'fix it up' but acutually fix the cause ;-)
#
def _memory_sanity_check(self):
if self['memory_static_min'] == 0:
self['memory_static_min'] = self['memory_dynamic_min']
# If the static max is not set, let's set it to dynamic max.
# If the static max is smaller than static min, then fix it!
self['memory_static_max'] = max(self['memory_static_max'],
self['memory_dynamic_max'],
self['memory_static_min'])
for mem_type in ('memory_static_min', 'memory_static_max'):
if self[mem_type] <= 0:
raise XendConfigError('Memory value too low for %s: %d' %
(mem_type, self[mem_type]))
log.debug("_memory_sanity_check memory_static_min: %s, "
"memory_static_max: %i, "
"memory_dynamic_min: %i, "
"memory_dynamic_max: %i",
self["memory_static_min"],
self["memory_static_max"],
self["memory_dynamic_min"],
self["memory_dynamic_max"])
if not self["memory_static_min"] <= self["memory_static_max"]:
raise XendConfigError("memory_static_min must be less " \
"than or equal to memory_static_max")
if not self["memory_dynamic_min"] <= self["memory_dynamic_max"]:
raise XendConfigError("memory_dynamic_min must be less " \
"than or equal to memory_dynamic_max")
if not self["memory_static_min"] <= self["memory_dynamic_min"]:
raise XendConfigError("memory_static_min must be less " \
"than or equal to memory_dynamic_min")
if not self["memory_dynamic_max"] <= self["memory_static_max"]:
raise XendConfigError("memory_dynamic_max must be less " \
"than or equal to memory_static_max")
if not self["memory_dynamic_max"] > 0:
raise XendConfigError("memory_dynamic_max must be greater " \
"than zero")
if not self["memory_static_max"] > 0:
raise XendConfigError("memory_static_max must be greater " \
"than zero")
def _actions_sanity_check(self):
for event in ['shutdown', 'reboot', 'crash']:
@@ -392,8 +407,12 @@ class XendConfig(dict):
self['domid'] = dominfo['domid']
self['online_vcpus'] = dominfo['online_vcpus']
self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024
self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024
self['memory_static_min'] = 0
self['memory_static_max'] = dominfo['maxmem_kb'] * 1024
self['cpu_time'] = dominfo['cpu_time']/1e9
# TODO: i don't know what the security stuff expects here
if dominfo.get('ssidref'):
@@ -447,6 +466,13 @@ class XendConfig(dict):
log.warn('Ignoring unrecognised value for deprecated option:'
'restart = \'%s\'', restart)
# Handle memory, passed in as MiB
if sxp.child_value(sxp_cfg, "memory") != None:
cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory"))
if sxp.child_value(sxp_cfg, "maxmem") != None:
cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
# Only extract options we know about.
extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
@@ -616,6 +642,21 @@ class XendConfig(dict):
except KeyError:
pass
# Lets try and handle memory correctly
MiB = 1024 * 1024
if "memory" in cfg:
self["memory_static_min"] = 0
self["memory_static_max"] = int(cfg["memory"]) * MiB
self["memory_dynamic_min"] = int(cfg["memory"]) * MiB
self["memory_dynamic_max"] = int(cfg["memory"]) * MiB
if "maxmem" in cfg:
self["memory_static_max"] = int(cfg["maxmem"]) * MiB
self._memory_sanity_check()
def update_with(n, o):
if not self.get(n):
self[n] = cfg.get(o, '')
@@ -632,13 +673,6 @@ class XendConfig(dict):
if key in cfg:
self['platform'][key] = cfg[key]
# make sure a sane maximum is set
if self['memory_static_max'] <= 0:
self['memory_static_max'] = self['memory_static_min']
self['memory_dynamic_max'] = self['memory_static_max']
self['memory_dynamic_min'] = self['memory_static_min']
# set device references in the configuration
self['devices'] = cfg.get('devices', {})
self['console_refs'] = cfg.get('console_refs', [])
@@ -812,6 +846,21 @@ class XendConfig(dict):
else:
sxpr.append([legacy, self[xenapi]])
MiB = 1024*1024
sxpr.append(["maxmem", int(self["memory_static_max"])/MiB])
sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
if not legacy_only:
sxpr.append(['memory_dynamic_min',
int(self.get('memory_dynamic_min'))])
sxpr.append(['memory_dynamic_max',
int(self.get('memory_dynamic_max'))])
sxpr.append(['memory_static_max',
int(self.get('memory_static_max'))])
sxpr.append(['memory_static_min',
int(self.get('memory_static_min'))])
for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
if legacy in ('domid', 'uuid'): # skip these
continue
@@ -820,8 +869,6 @@ class XendConfig(dict):
sxpr.append(['image', self.image_sxpr()])
sxpr.append(['status', domain.state])
sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')])
sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')])
if domain.getDomid() is not None:
sxpr.append(['state', self._get_old_state_string()])
+41 -11
View File
@@ -576,7 +576,7 @@ class XendDomainInfo:
if target <= 0:
raise XendError('Invalid memory size')
self.info['memory_static_min'] = target
self.info['memory_static_min'] = target * 1024 * 1024
if self.domid >= 0:
self.storeVm("memory", target)
self.storeDom("memory/target", target << 10)
@@ -664,6 +664,10 @@ class XendDomainInfo:
if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
self.info[xapiarg] = val
elif arg == "memory":
self.info["static_memory_min"] = val
elif arg == "maxmem":
self.info["static_memory_max"] = val
else:
self.info[arg] = val
@@ -780,7 +784,7 @@ class XendDomainInfo:
'vm': self.vmpath,
'name': self.info['name_label'],
'console/limit': str(xoptions.get_console_limit() * 1024),
'memory/target': str(self.info['memory_static_min'] * 1024),
'memory/target': str(self.info['memory_dynamic_max'] / 1024),
}
def f(n, v):
@@ -864,7 +868,15 @@ class XendDomainInfo:
xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
if val != None and val != self.info[xapiarg]:
self.info[xapiarg] = val
changed= True
changed = True
elif arg == "memory":
if val != None and val != self.info["static_memory_min"]:
self.info["static_memory_min"] = val
changed = True
elif arg == "maxmem":
if val != None and val != self.info["static_memory_max"]:
self.info["static_memory_max"] = val
changed = True
# Check whether image definition has been updated
image_sxp = self._readVm('image')
@@ -969,11 +981,12 @@ class XendDomainInfo:
def getMemoryTarget(self):
"""Get this domain's target memory size, in KB."""
return self.info['memory_static_min'] * 1024
return self.info['memory_static_min'] / 1024
def getMemoryMaximum(self):
"""Get this domain's maximum memory size, in KB."""
return self.info['memory_static_max'] * 1024
# remember, info now stores memory in bytes
return self.info['memory_static_max'] / 1024
def getResume(self):
return str(self._resume)
@@ -1455,13 +1468,14 @@ class XendDomainInfo:
# Use architecture- and image-specific calculations to determine
# the various headrooms necessary, given the raw configured
# values. maxmem, memory, and shadow are all in KiB.
# but memory_static_max etc are all stored in bytes now.
memory = self.image.getRequiredAvailableMemory(
self.info['memory_static_min'] * 1024)
self.info['memory_static_min'] / 1024)
maxmem = self.image.getRequiredAvailableMemory(
self.info['memory_static_max'] * 1024)
self.info['memory_static_max'] / 1024)
shadow = self.image.getRequiredShadowMemory(
self.info['shadow_memory'] * 1024,
self.info['memory_static_max'] * 1024)
self.info['shadow_memory'] / 1024,
self.info['memory_static_max'] / 1024)
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'],)
# Round shadow up to a multiple of a MiB, as shadow_mem_control
@@ -1650,7 +1664,18 @@ class XendDomainInfo:
log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
from xen.xend import XendDomain
XendDomain.instance().remove_domain(self)
if "transient" in self.info["other_config"]\
and bool(self.info["other_config"]["transient"]):
xendDomainInstance = XendDomain.instance()
xendDomainInstance.domains_lock.acquire()
xendDomainInstance._refresh(refresh_shutdown = False)
xendDomainInstance.domains_lock.release()
xendDomainInstance.domain_delete(self.info["name_label"])
else:
XendDomain.instance().remove_domain(self)
self.cleanupDomain()
self._cleanup_phantom_devs(paths)
@@ -1833,7 +1858,7 @@ class XendDomainInfo:
# 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
# the minimum that Xen would allocate if no value were given.
overhead_kb = self.info['vcpus_number'] * 1024 + \
self.info['memory_static_max'] * 4
(self.info['memory_static_max'] / 1024 / 1024) * 4
overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
# The domain might already have some shadow memory
overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
@@ -1899,6 +1924,11 @@ class XendDomainInfo:
if self._infoIsSet(info_key):
to_store[key] = str(self.info[info_key])
if self._infoIsSet("static_memory_min"):
to_store["memory"] = str(self.info["static_memory_min"])
if self._infoIsSet("static_memory_max"):
to_store["maxmem"] = str(self.info["static_memory_max"])
image_sxpr = self.info.image_sxpr()
if image_sxpr:
to_store['image'] = sxp.to_string(image_sxpr)
+2 -1
View File
@@ -530,7 +530,8 @@ class XendNode:
info['cores_per_socket'] *
info['threads_per_core'])
info['cpu_mhz'] = info['cpu_khz'] / 1000
# physinfo is in KiB
# physinfo is in KiB, need it in MiB
info['total_memory'] = info['total_memory'] / 1024
info['free_memory'] = info['free_memory'] / 1024
+118
View File
@@ -0,0 +1,118 @@
<!ENTITY % HTMLlat1 PUBLIC
"-//W3C//ENTITIES Latin 1 for XHTML//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
%HTMLlat1;
<!ENTITY % HTMLsymbol PUBLIC
"-//W3C//ENTITIES Symbols for XHTML//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
%HTMLsymbol;
<!ENTITY % HTMLspecial PUBLIC
"-//W3C//ENTITIES Special for XHTML//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
%HTMLspecial;
<!-- a Uniform Resource Identifier, see [RFC2396] -->
<!ENTITY % URI "CDATA">
<!ENTITY % NAMEID "name ID #REQUIRED">
<!ENTITY % CRASH_BEHAVIOUR "( destroy
| coredump_and_destroy
| restart
| coredump_and_restart
| preserve
| rename_restart )">
<!ENTITY % NORMAL_EXIT "( destroy | restart )">
<!ENTITY % VDI_TYPE "( system
| user
| ephemeral
| suspend
| crashdump )">
<!ELEMENT xm (vm*,
vdi*)>
<!ELEMENT version (#PCDATA)>
<!ELEMENT vm (name,
version,
(pv|hvm),
memory,
vbd*,
vif*,
vcpu_param*,
other_config*)>
<!ATTLIST vm is_a_template CDATA #REQUIRED
auto_power_on CDATA #REQUIRED
vcpus_max CDATA #REQUIRED
vcpus_at_startup CDATA #REQUIRED
actions_after_shutdown %NORMAL_EXIT; #REQUIRED
actions_after_reboot %NORMAL_EXIT; #REQUIRED
actions_after_crash %CRASH_BEHAVIOUR; #REQUIRED
platform_std_VGA CDATA #REQUIRED
platform_serial CDATA #REQUIRED
platform_localtime CDATA #REQUIRED
platform_clock_offet CDATA #REQUIRED
platform_enable_audio CDATA #REQUIRED
PCI_bus CDATA #REQUIRED>
<!ELEMENT memory EMPTY>
<!ATTLIST memory static_min CDATA #REQUIRED
static_max CDATA #REQUIRED
dynamic_min CDATA #REQUIRED
dynamic_max CDATA #REQUIRED>
<!ELEMENT vbd (qos_algorithm_param*)>
<!ATTLIST vbd %NAMEID;
mode (RO | RW) #REQUIRED
vdi IDREF #REQUIRED
device CDATA #REQUIRED
bootable CDATA #REQUIRED
type (CD | disk) #REQUIRED
qos_algorithm_type CDATA #REQUIRED>
<!ELEMENT vif (qos_algorithm_param*)>
<!ATTLIST vif %NAMEID;
mac CDATA #REQUIRED
mtu CDATA #REQUIRED
device CDATA #REQUIRED
qos_algorithm_type CDATA #REQUIRED
bridge CDATA #IMPLIED
network CDATA #IMPLIED>
<!ELEMENT pv EMPTY>
<!ATTLIST pv kernel CDATA #REQUIRED
bootloader CDATA #REQUIRED
ramdisk CDATA #REQUIRED
args CDATA #REQUIRED
bootloader_args CDATA #REQUIRED>
<!ELEMENT hvm (boot_param*)>
<!ATTLIST hvm boot_policy CDATA #REQUIRED>
<!ELEMENT boot_param EMPTY>
<!ATTLIST boot_param key CDATA #REQUIRED
value CDATA #REQUIRED>
<!ELEMENT vdi (name)>
<!ATTLIST vdi %NAMEID;
src %URI; #REQUIRED
type %VDI_TYPE; #REQUIRED
size CDATA #REQUIRED
shareable CDATA #REQUIRED
read_only CDATA #REQUIRED>
<!ELEMENT name (label,
description)>
<!ELEMENT label (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT vcpu_param EMPTY>
<!ATTLIST vcpu_param key CDATA #REQUIRED
value CDATA #REQUIRED>
<!ELEMENT other_config EMPTY>
<!ATTLIST other_config key CDATA #REQUIRED
value CDATA #REQUIRED>
<!ELEMENT qos_algorithm_param EMPTY>
<!ATTLIST qos_algorithm_param key CDATA #REQUIRED
value CDATA #REQUIRED>
+56 -26
View File
@@ -28,12 +28,14 @@ import time
import xmlrpclib
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend import PrettyPrint as SXPPrettyPrint
from xen.xend import osdep
import xen.xend.XendClient
from xen.xend.XendBootloader import bootloader
from xen.util import blkif
from xen.util import security
from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
from xen.xm.xenapi_create import sxp2xml, xenapi_create
from xen.xm.opts import *
@@ -98,6 +100,11 @@ gopts.opt('dryrun', short='n',
use="Dry run - prints the resulting configuration in SXP but "
"does not create the domain.")
gopts.opt('xmldryrun', short='x',
fn=set_true, default=0,
use="XML dry run - prints the resulting configuration in XML but "
"does not create the domain.")
gopts.opt('paused', short='p',
fn=set_true, default=0,
use='Leave the domain paused after it is created.')
@@ -1241,34 +1248,57 @@ def main(argv):
except IOError, exn:
raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
if serverType == SERVER_XEN_API:
sxp2xml_inst = sxp2xml()
doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
SXPPrettyPrint.prettyprint(config)
if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
from xml.dom.ext import PrettyPrint as XMLPrettyPrint
XMLPrettyPrint(doc)
if opts.vals.dryrun or opts.vals.xmldryrun:
return
if opts.vals.console_autoconnect:
do_console(sxp.child_value(config, 'name', -1))
if serverType == SERVER_XEN_API:
xenapi_create_inst = xenapi_create()
vm_refs = xenapi_create_inst.create(document = doc)
map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
else:
if not create_security_check(config):
raise security.ACMError('Security Configuration prevents domain from starting')
else:
if opts.vals.console_autoconnect:
cpid = os.fork()
if cpid != 0:
for i in range(10):
# Catch failure of the create process
time.sleep(1)
(p, rv) = os.waitpid(cpid, os.WNOHANG)
if os.WIFEXITED(rv):
if os.WEXITSTATUS(rv) != 0:
sys.exit(os.WEXITSTATUS(rv))
try:
# Acquire the console of the created dom
name = sxp.child_value(config, 'name', -1)
dom = server.xend.domain(name)
domid = int(sxp.child_value(dom, 'domid', '-1'))
console.execConsole(domid)
except:
pass
print("Could not start console\n");
sys.exit(0)
dom = make_domain(opts, config)
raise security.ACMError(
'Security Configuration prevents domain from starting')
dom = make_domain(opts, config)
def do_console(domain_name):
cpid = os.fork()
if cpid != 0:
for i in range(10):
# Catch failure of the create process
time.sleep(1)
(p, rv) = os.waitpid(cpid, os.WNOHANG)
if os.WIFEXITED(rv):
if os.WEXITSTATUS(rv) != 0:
sys.exit(os.WEXITSTATUS(rv))
try:
# Acquire the console of the created dom
if serverType == SERVER_XEN_API:
domid = server.xenapi.VM.get_domid(
get_single_vm(domain_name))
else:
dom = server.xend.domain(name)
domid = int(sxp.child_value(dom, 'domid', '-1'))
console.execConsole(domid)
except:
pass
print("Could not start console\n");
sys.exit(0)
if __name__ == '__main__':
main(sys.argv)
+12 -1
View File
@@ -22,6 +22,9 @@ from xen.xend import PrettyPrint
from xen.xend import sxp
from xen.xend import XendClient
from xen.xm.main import serverType, SERVER_XEN_API
from xen.xm.xenapi_create import *
from opts import *
from create import *
@@ -65,7 +68,15 @@ def main(argv):
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
else:
return
if serverType == SERVER_XEN_API:
sxp2xml_inst = sxp2xml()
doc = sxp2xml_inst.convert_sxp_to_xml(config)
xenapi_create_inst = xenapi_create()
vm_refs = xenapi_create_inst.create(document = doc)
else:
make_unstarted_domain(opts, config)
if __name__ == '__main__':
+634
View File
@@ -0,0 +1,634 @@
#!/usr/bin/python
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2007 Tom Wilkie <tom.wilkie@gmail.com>
#============================================================================
"""Domain creation using new XenAPI
"""
from xen.xm.main import server
from xml.dom.minidom import parse, getDOMImplementation
from xml.dom.ext import PrettyPrint
from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
from xen.xend import sxp
from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
XEN_API_ON_CRASH_BEHAVIOUR
import sys
import os
import traceback
def log(_, msg):
#print "> " + msg
pass
DEBUG = 0
def get_name_label(node):
name_node = node.getElementsByTagName("name")[0]
label_node = name_node.getElementsByTagName("label")[0]
return " ".join([child.nodeValue for child in label_node.childNodes])
def get_name_description(node):
name_node = node.getElementsByTagName("name")[0]
description_node = name_node.getElementsByTagName("description")[0]
return " ".join([child.nodeValue for child in description_node.childNodes])
def get_text_in_child_node(node, child):
tag_node = node.getElementsByTagName(child)[0]
return tag_node.nodeValue
def get_child_node_attribute(node, child, attribute):
tag_node = node.getElementsByTagName(child)[0]
return tag_node.attributes[attribute].value
def get_child_nodes_as_dict(node, child_name,
key_attribute_name,
value_attribute_name):
return dict([(child.attributes[key_attribute_name].value,
child.attributes[value_attribute_name].value)
for child in node.getElementsByTagName(child_name)])
def try_quietly(fn, *args):
try:
return fn(*args)
except:
return None
class xenapi_create:
def __init__(self):
self.DEFAULT_STORAGE_REPOSITORY = [sr_ref
for sr_ref in server.xenapi.SR.get_all()
if server.xenapi.SR.get_type(sr_ref) == "local"][0]
self.dtd = "/usr/lib/python/xen/xm/create.dtd"
def create(self, filename=None, document=None):
"""
Create a domain from an XML file or DOM tree
"""
if filename is not None:
self.check_dtd(file)
document = parse(file)
elif document is not None:
self.check_dom_against_dtd(document)
self.check_doc(document)
vdis = document.getElementsByTagName("vdi")
vdi_refs_dict = self.create_vdis(vdis)
try:
vms = document.getElementsByTagName("vm")
return self.create_vms(vms, vdi_refs_dict)
except Exception, exn:
try_quietly(self.cleanup_vdis(vdi_refs_dict))
raise exn
# Methods to check xml file
# try to use dtd to check where possible
def check_dtd(self, file):
"""
Check file against DTD.
Use this if possible as it gives nice
error messages
"""
dtd = xmldtd.load_dtd(self.dtd)
parser = xmlproc.XMLProcessor()
parser.set_application(xmlval.ValidatingApp(dtd, parser))
parser.dtd = dtd
parser.ent = dtd
parser.parse_resource(file)
def check_dom_against_dtd(self, dom):
"""
Check DOM again DTD.
Doesn't give as nice error messages.
(no location info)
"""
dtd = xmldtd.load_dtd(self.dtd)
app = xmlval.ValidatingApp(dtd, self)
app.set_locator(self)
self.dom2sax(dom, app)
# Get errors back from ValidatingApp
def report_error(self, number, args=None):
self.errors = xmlproc.errors.english
try:
msg = self.errors[number]
if args != None:
msg = msg % args
except KeyError:
msg = self.errors[4002] % number # Unknown err msg :-)
print msg
sys.exit(-1)
# Here for compatibility with ValidatingApp
def get_line(self):
return -1
def get_column(self):
return -1
def dom2sax(self, dom, app):
"""
Take a dom tree and tarverse it,
issuing SAX calls to app.
"""
for child in dom.childNodes:
if child.nodeType == child.TEXT_NODE:
data = child.nodeValue
app.handle_data(data, 0, len(data))
else:
app.handle_start_tag(
child.nodeName,
self.attrs_to_dict(child.attributes))
self.dom2sax(child, app)
app.handle_end_tag(child.nodeName)
def attrs_to_dict(self, attrs):
return dict(attrs.items())
#
# Checks which cannot be done with dtd
#
def check_doc(self, doc):
vms = doc.getElementsByTagName("vm")
self.check_vms(vms)
def check_vms(self, vms):
map(self.check_vm, vms)
def check_vm(self, vm):
vifs = vm.getElementsByTagName("vif")
self.check_vifs(vifs)
def check_vifs(self, vifs):
map(self.check_vif, vifs)
def check_vif(self, vif):
"""
Check that the vif has
either a bridge or network
name but not both
"""
if "bridge" in vif.attributes.keys() \
and "network" in vif.attributes.keys():
raise "You cannot specify both a bridge and\
a network name."
# Cleanup methods here
def cleanup_vdis(self, vdi_refs_dict):
map(self.cleanup_vdi, vdi_refs_dict.values())
def cleanup_vdi(self, vdi_ref):
server.xenapi.VDI.destroy(vdi_ref)
def cleanup_vms(self, vm_refs):
map(self.cleanup_vm, vm_refs)
def cleanup_vm(self, vm_ref):
server.xenapi.VM.destroy(vm_ref)
# Create methods here
def create_vdis(self, vdis):
log(DEBUG, "create_vdis")
return dict(map(self.create_vdi, vdis))
def create_vdi(self, vdi):
log(DEBUG, "create_vdi")
vdi_record = {
"name_label": get_name_label(vdi),
"name_description": get_name_description(vdi),
"SR": self.DEFAULT_STORAGE_REPOSITORY,
"virtual_size": vdi.attributes["size"].value,
"type": vdi.attributes["type"].value,
"shareable": vdi.attributes["shareable"].value,
"read_only": vdi.attributes["read_only"].value,
"other_config": {"location":
vdi.attributes["src"].value}
}
key = vdi.attributes["name"].value
value = server.xenapi.VDI.create(vdi_record)
return (key, value)
def create_vms(self, vms, vdis):
log(DEBUG, "create_vms")
return map(lambda vm: self.create_vm(vm, vdis), vms)
def create_vm(self, vm, vdis):
log(DEBUG, "create_vm")
vm_record = {
"name_label":
get_name_label(vm),
"name_description":
get_name_description(vm),
"user_version":
get_text_in_child_node(vm, "version"),
"is_a_template":
vm.attributes["is_a_template"].value,
"auto_power_on":
vm.attributes["auto_power_on"].value,
"memory_static_max":
get_child_node_attribute(vm, "memory", "static_max"),
"memory_static_min":
get_child_node_attribute(vm, "memory", "static_min"),
"memory_dynamic_max":
get_child_node_attribute(vm, "memory", "dynamic_max"),
"memory_dynamic_min":
get_child_node_attribute(vm, "memory", "dynamic_min"),
"vcpus_params":
get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
"vcpus_max":
vm.attributes["vcpus_max"].value,
"vcpus_at_startup":
vm.attributes["vcpus_at_startup"].value,
"actions_after_shutdown":
vm.attributes["actions_after_shutdown"].value,
"actions_after_reboot":
vm.attributes["actions_after_reboot"].value,
"actions_after_crash":
vm.attributes["actions_after_crash"].value,
"platform_std_VGA":
vm.attributes["platform_std_VGA"].value,
"platform_serial":
vm.attributes["platform_serial"].value,
"platform_localtime":
vm.attributes["platform_localtime"].value,
"platform_clock_offet":
vm.attributes["platform_clock_offet"].value,
"platform_enable_audio":
vm.attributes["platform_enable_audio"].value,
"PCI_bus":
vm.attributes["platform_enable_audio"].value,
"other_config":
get_child_nodes_as_dict(vm, "other_config", "key", "value")
}
if len(vm.getElementsByTagName("pv")) > 0:
vm_record.update({
"PV_bootloader":
get_child_node_attribute(vm, "pv", "bootloader"),
"PV_kernel":
get_child_node_attribute(vm, "pv", "kernel"),
"PV_ramdisk":
get_child_node_attribute(vm, "pv", "ramdisk"),
"PV_args":
get_child_node_attribute(vm, "pv", "args"),
"PV_bootloader_args":
get_child_node_attribute(vm, "pv", "bootloader_args")
})
else:
hvm = vm.getElementsByTagName("hvm")[0]
vm_record.update({
"HVM_boot_policy":
get_child_node_attribute(vm, "hvm", "boot_policy"),
"HVM_boot_params":
get_child_nodes_as_dict(hvm, "boot_params", "key", "value")
})
try:
vm_ref = server.xenapi.VM.create(vm_record)
except:
traceback.print_exc()
sys.exit(-1)
# Now create vbds
vbds = vm.getElementsByTagName("vbd")
self.create_vbds(vm_ref, vbds, vdis)
# Now create vifs
vifs = vm.getElementsByTagName("vif")
self.create_vifs(vm_ref, vifs)
return vm_ref
def create_vbds(self, vm_ref, vbds, vdis):
log(DEBUG, "create_vbds")
return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
def create_vbd(self, vm_ref, vbd, vdis):
log(DEBUG, "create_vbd")
vbd_record = {
"VM":
vm_ref,
"VDI":
vdis[vbd.attributes["vdi"].value],
"device":
vbd.attributes["device"].value,
"bootable":
vbd.attributes["bootable"].value,
"mode":
vbd.attributes["mode"].value,
"type":
vbd.attributes["type"].value,
"qos_algorithm_type":
vbd.attributes["qos_algorithm_type"].value,
"qos_algorithm_params":
get_child_nodes_as_dict(vbd,
"qos_algorithm_param", "key", "value")
}
return server.xenapi.VBD.create(vbd_record)
def create_vifs(self, vm_ref, vifs):
log(DEBUG, "create_vifs")
return map(lambda vif: self.create_vif(vm_ref, vif), vifs)
def create_vif(self, vm_ref, vif):
log(DEBUG, "create_vif")
if "bridge" in vif.attributes.keys():
raise "Not allowed to add by bridge just yet"
elif "network" in vif.attributes.keys():
network = [network_ref
for network_ref in server.xenapi.network.get_all()
if server.xenapi.network.get_name_label(network_ref)
== vif.attributes["network"].value][0]
else:
network = self._get_network_ref()
vif_record = {
"device":
vif.attributes["device"].value,
"network":
network,
"VM":
vm_ref,
"MAC":
vif.attributes["mac"].value,
"MTU":
vif.attributes["mtu"].value,
"qos_algorithm_type":
vif.attributes["qos_algorithm_type"].value,
"qos_algorithm_params":
get_child_nodes_as_dict(vif,
"qos_algorithm_param", "key", "value")
}
return server.xenapi.VIF.create(vif_record)
_network_refs = []
def _get_network_ref(self):
try:
return self._network_refs.pop(0)
except IndexError:
self._network_refs = server.xenapi.network.get_all()
return self._network_refs.pop(0)
def get_child_by_name(exp, childname, default = None):
try:
return [child for child in sxp.children(exp)
if child[0] == childname][0][1]
except:
return default
# Convert old sxp into new xml
class sxp2xml:
def convert_sxp_to_xml(self, config, transient=False):
devices = [child for child in sxp.children(config)
if len(child) > 0 and child[0] == "device"]
vbds_sxp = map(lambda x: x[1], [device for device in devices
if device[1][0] == "vbd"])
vifs_sxp = map(lambda x: x[1], [device for device in devices
if device[1][0] == "vif"])
# Create XML Document
impl = getDOMImplementation()
document = impl.createDocument(None, "xm", None)
# Lets make the VM tag..
vm = document.createElement("vm")
# Some string compatibility
actions_after_shutdown \
= get_child_by_name(config, "on_poweroff", "destroy")
actions_after_reboot \
= get_child_by_name(config, "on_reboot", "restart")
actions_after_crash \
= get_child_by_name(config, "on_crash", "restart")
def conv_chk(val, vals):
val.replace("-", "_")
if val not in vals:
raise "Invalid value: " + val
else:
return val
actions_after_shutdown = conv_chk(actions_after_shutdown,\
XEN_API_ON_NORMAL_EXIT)
actions_after_reboot = conv_chk(actions_after_reboot, \
XEN_API_ON_NORMAL_EXIT)
actions_after_crash = conv_chk(actions_after_crash, \
XEN_API_ON_CRASH_BEHAVIOUR)
# Flesh out tag attributes
vm.attributes["is_a_template"] = "false"
vm.attributes["auto_power_on"] = "false"
vm.attributes["actions_after_shutdown"] \
= actions_after_shutdown
vm.attributes["actions_after_reboot"] \
= actions_after_reboot
vm.attributes["actions_after_crash"] \
= actions_after_crash
vm.attributes["platform_std_VGA"] = "false"
vm.attributes["platform_serial"] = ""
vm.attributes["platform_localtime"] = ""
vm.attributes["platform_clock_offet"] = ""
vm.attributes["platform_enable_audio"] = ""
vm.attributes["PCI_bus"] = ""
vm.attributes["vcpus_max"] \
= str(get_child_by_name(config, "vcpus", 1))
vm.attributes["vcpus_at_startup"] \
= str(get_child_by_name(config, "vcpus", 1))
# Make the name tag
vm.appendChild(self.make_name_tag(
get_child_by_name(config, "name"), document))
# Make version tag
version = document.createElement("version")
version.appendChild(document.createTextNode("1.0"))
vm.appendChild(version)
# Make pv or hvm tag
image = get_child_by_name(config, "image")
if image[0] == "linux":
pv = document.createElement("pv")
pv.attributes["kernel"] \
= get_child_by_name(image, "kernel", "")
pv.attributes["bootloader"] = ""
pv.attributes["ramdisk"] \
= get_child_by_name(image, "ramdisk", "")
pv.attributes["args"] \
= "root=" + get_child_by_name(image, "root", "") \
+ " " + get_child_by_name(image, "args", "")
pv.attributes["bootloader_args"] = ""
vm.appendChild(pv)
elif image[0] == "hvm":
hvm = document.createElement("hvm")
hvm.attributes["boot_policy"] = ""
vm.appendChild(hvm)
# Make memory tag
memory = document.createElement("memory")
memory_str = str(int(
get_child_by_name(config, "memory"))*1024*1024)
memory.attributes["static_min"] = memory_str
memory.attributes["static_max"] = memory_str
memory.attributes["dynamic_min"] = memory_str
memory.attributes["dynamic_max"] = memory_str
vm.appendChild(memory)
# And now the vbds
vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
map(vm.appendChild, vbds)
# And now the vifs
vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
map(vm.appendChild, vifs)
# transient?
if transient:
other_config = document.createElement("other_config")
other_config.attributes["key"] = "transient"
other_config.attributes["value"] = "True"
vm.appendChild(other_config)
# Add it to doc_root
document.documentElement.appendChild(vm)
# We want to pull out vdis
vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
map(document.documentElement.appendChild, vdis)
return document
def make_name_tag(self, label_text, document):
name = document.createElement("name")
label = document.createElement("label")
label.appendChild(document.createTextNode(str(label_text)))
name.appendChild(label)
description = document.createElement("description")
description.appendChild(document.createTextNode(" "))
name.appendChild(description)
return name
def extract_vbd(self, vbd_sxp, document):
src = get_child_by_name(vbd_sxp, "uname")
name = str(src.__hash__())
vbd = document.createElement("vbd")
vbd.attributes["name"] = "vdb" + name
vbd.attributes["vdi"] = "vdi" + name
vbd.attributes["mode"] \
= get_child_by_name(vbd_sxp, "mode") != "w" \
and "RO" or "RW"
vbd.attributes["device"] \
= get_child_by_name(vbd_sxp, "dev")
vbd.attributes["bootable"] = "1"
vbd.attributes["type"] = "disk"
vbd.attributes["qos_algorithm_type"] = ""
return vbd
def extract_vdi(self, vbd_sxp, document):
src = get_child_by_name(vbd_sxp, "uname")
name = "vdi" + str(src.__hash__())
path = src[src.find(":")+1:]
vdi = document.createElement("vdi")
vdi.attributes["src"] = src
vdi.attributes["read_only"] \
= (get_child_by_name(vbd_sxp, "mode") != "w") \
and "true" or "false"
vdi.attributes["size"] \
= str(os.path.getsize(path))
vdi.attributes["type"] = "system"
vdi.attributes["shareable"] = "false"
vdi.attributes["name"] = name
vdi.appendChild(self.make_name_tag(name, document))
return vdi
def extract_vif(self, vif_sxp, document):
vif = document.createElement("vif")
dev = get_child_by_name(vif_sxp, "vifname", "eth0")
vif.attributes["name"] \
= "vif" + str(dev.__hash__())
vif.attributes["mac"] \
= get_child_by_name(vif_sxp, "mac", "")
vif.attributes["mtu"] \
= get_child_by_name(vif_sxp, "mtu", "")
vif.attributes["device"] = dev
vif.attributes["qos_algorithm_type"] = ""
if get_child_by_name(vif_sxp, "bridge") is not None:
vif.attributes["bridge"] \
= get_child_by_name(vif_sxp, "bridge")
return vif
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.