ia64/xen-unstable

view tools/python/xen/xm/xenapi_create.py @ 19639:205b1badbcfd

Add support for superpages (hugepages) in PV domain

This patch adds the option "superpages" to the domain configuration
file. If it is set, the domain is populated using 2M pages.

This code does not support fallback to small pages. If the domain can
not be created with 2M pages, the create will fail.

The patch also includes support for saving and restoring domains with
the superpage flag set. However, if a domain has freed small pages
within its physical page array and then extended the array, the
restore will fill in those freed pages. It will then attempt to
allocate more than its memory limit and will fail. This is
significant because apparently Linux does this during boot, thus a
freshly booted Linux image can not be saved and restored successfully.

Signed-off-by: Dave McCracken <dcm@mccr.org>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 26 09:58:38 2009 +0100 (2009-05-26)
parents 5c69f98c348e
children a3125a83e40b
line source
1 #!/usr/bin/python
2 #============================================================================
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of version 2.1 of the GNU Lesser General Public
5 # License as published by the Free Software Foundation.
6 #
7 # This library is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 # Lesser General Public License for more details.
11 #
12 # You should have received a copy of the GNU Lesser General Public
13 # License along with this library; if not, write to the Free Software
14 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 #============================================================================
16 # Copyright (C) 2007 Tom Wilkie <tom.wilkie@gmail.com>
17 #============================================================================
18 """Domain creation using new XenAPI
19 """
21 from xen.xm.main import server, get_default_SR
22 from xml.dom.minidom import parse, getDOMImplementation
23 from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
24 from xen.xend import sxp
25 from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
26 XEN_API_ON_CRASH_BEHAVIOUR
27 from xen.xm.opts import OptionError
28 from xen.util import xsconstants
29 import xen.util.xsm.xsm as security
31 import sys
32 import os
33 import traceback
34 import re
36 def log(_, msg):
37 #print "> " + msg
38 pass
40 DEBUG = 0
42 def get_name_label(node):
43 name_node = node.getElementsByTagName("name")[0]
44 label_node = name_node.getElementsByTagName("label")[0]
45 return " ".join([child.nodeValue for child in label_node.childNodes])
47 def get_name_description(node):
48 name_node = node.getElementsByTagName("name")[0]
49 description_node = name_node.getElementsByTagName("description")[0]
50 return " ".join([child.nodeValue for child in description_node.childNodes])
52 def get_text_in_child_node(node, child):
53 tag_node = node.getElementsByTagName(child)[0]
54 return " ".join([child.nodeValue for child in tag_node.childNodes])
56 def get_child_node_attribute(node, child, attribute):
57 tag_node = node.getElementsByTagName(child)[0]
58 return tag_node.attributes[attribute].value
60 def get_child_nodes_as_dict(node, child_name,
61 key_attribute_name,
62 value_attribute_name):
63 return dict([(child.attributes[key_attribute_name].value,
64 child.attributes[value_attribute_name].value)
65 for child in node.getElementsByTagName(child_name)])
67 def try_quietly(fn, *args):
68 try:
69 return fn(*args)
70 except:
71 return None
73 class xenapi_create:
75 def __init__(self):
76 self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
78 self.dtd = "/usr/share/xen/create.dtd"
80 def create(self, filename=None, document=None, skipdtd=False):
81 """
82 Create a domain from an XML file or DOM tree
83 """
84 if skipdtd:
85 print "Skipping DTD checks. Dangerous!"
87 if filename is not None:
88 if not skipdtd:
89 self.check_dtd(filename)
90 document = parse(filename)
91 elif document is not None:
92 if not skipdtd:
93 self.check_dom_against_dtd(document)
95 self.check_doc(document)
97 vdis = document.getElementsByTagName("vdi")
98 vdi_refs_dict = self.create_vdis(vdis)
100 networks = document.getElementsByTagName("network")
101 network_refs_dict = self.create_networks(networks)
103 try:
104 vms = document.getElementsByTagName("vm")
105 return self.create_vms(vms, vdi_refs_dict, network_refs_dict)
106 except Exception, exn:
107 try_quietly(self.cleanup_vdis(vdi_refs_dict))
108 raise exn
110 # Methods to check xml file
111 # try to use dtd to check where possible
112 def check_dtd(self, file):
113 """
114 Check file against DTD.
115 Use this if possible as it gives nice
116 error messages
117 """
118 dtd = xmldtd.load_dtd(self.dtd)
119 parser = xmlproc.XMLProcessor()
120 parser.set_application(xmlval.ValidatingApp(dtd, parser))
121 parser.dtd = dtd
122 parser.ent = dtd
123 parser.parse_resource(file)
125 def check_dom_against_dtd(self, dom):
126 """
127 Check DOM again DTD.
128 Doesn't give as nice error messages.
129 (no location info)
130 """
131 dtd = xmldtd.load_dtd(self.dtd)
132 app = xmlval.ValidatingApp(dtd, self)
133 app.set_locator(self)
134 self.dom2sax(dom, app)
136 # Get errors back from ValidatingApp
137 def report_error(self, number, args=None):
138 self.errors = xmlproc.errors.english
139 try:
140 msg = self.errors[number]
141 if args != None:
142 msg = msg % args
143 except KeyError:
144 msg = self.errors[4002] % number # Unknown err msg :-)
145 print msg
146 sys.exit(-1)
148 # Here for compatibility with ValidatingApp
149 def get_line(self):
150 return -1
152 def get_column(self):
153 return -1
155 def dom2sax(self, dom, app):
156 """
157 Take a dom tree and tarverse it,
158 issuing SAX calls to app.
159 """
160 for child in dom.childNodes:
161 if child.nodeType == child.TEXT_NODE:
162 data = child.nodeValue
163 app.handle_data(data, 0, len(data))
164 else:
165 app.handle_start_tag(
166 child.nodeName,
167 self.attrs_to_dict(child.attributes))
168 self.dom2sax(child, app)
169 app.handle_end_tag(child.nodeName)
171 def attrs_to_dict(self, attrs):
172 return dict(attrs.items())
174 #
175 # Checks which cannot be done with dtd
176 #
177 def check_doc(self, doc):
178 vms = doc.getElementsByTagName("vm")
179 self.check_vms(vms)
181 def check_vms(self, vms):
182 map(self.check_vm, vms)
184 def check_vm(self, vm):
185 vifs = vm.getElementsByTagName("vif")
186 self.check_vifs(vifs)
188 def check_vifs(self, vifs):
189 map(self.check_vif, vifs)
191 def check_vif(self, vif):
192 pass
194 # Cleanup methods here
195 def cleanup_vdis(self, vdi_refs_dict):
196 map(self.cleanup_vdi, vdi_refs_dict.values())
198 def cleanup_vdi(self, vdi_ref):
199 server.xenapi.VDI.destroy(vdi_ref)
201 def cleanup_vms(self, vm_refs):
202 map(self.cleanup_vm, vm_refs)
204 def cleanup_vm(self, vm_ref):
205 server.xenapi.VM.destroy(vm_ref)
207 # Create methods here
208 def create_vdis(self, vdis):
209 log(DEBUG, "create_vdis")
210 return dict(map(self.create_vdi, vdis))
212 def create_vdi(self, vdi):
213 log(DEBUG, "create_vdi")
215 vdi_record = {
216 "name_label": get_name_label(vdi),
217 "name_description": get_name_description(vdi),
218 "SR": self.DEFAULT_STORAGE_REPOSITORY,
219 "virtual_size": vdi.attributes["size"].value,
220 "type": vdi.attributes["type"].value,
221 "sharable": vdi.attributes["sharable"].value == "True",
222 "read_only": vdi.attributes["read_only"].value == "True",
223 "other_config": {"location":
224 vdi.attributes["src"].value}
225 }
227 key = vdi.attributes["name"].value
228 value = server.xenapi.VDI.create(vdi_record)
230 return (key, value)
232 def create_networks(self, networks):
233 log(DEBUG, "create_networks")
234 return dict(map(self.create_network, networks))
236 def create_network(self, network):
237 log(DEBUG, "create_network")
239 network_record = {
240 "name_label": get_name_label(network),
241 "name_description": get_name_description(network),
242 "other_config":
243 get_child_nodes_as_dict(network, "other_config",
244 "key", "value"),
245 "default_netmask": network.attributes["default_netmask"].value,
246 "default_gateway": network.attributes["default_gateway"].value
247 }
249 key = network.attributes["name"].value
250 value = server.xenapi.network.create(network_record)
252 return (key, value)
254 def create_vms(self, vms, vdis, networks):
255 log(DEBUG, "create_vms")
256 return map(lambda vm: self.create_vm(vm, vdis, networks), vms)
258 def create_vm(self, vm, vdis, networks):
259 log(DEBUG, "create_vm")
261 vm_record = {
262 "name_label":
263 get_name_label(vm),
264 "name_description":
265 get_name_description(vm),
266 "user_version":
267 get_text_in_child_node(vm, "version"),
268 "is_a_template":
269 vm.attributes["is_a_template"].value == 'true',
270 "auto_power_on":
271 vm.attributes["auto_power_on"].value == 'true',
272 "s3_integrity":
273 vm.attributes["s3_integrity"].value,
274 "superpages":
275 vm.attributes["superpages"].value,
276 "memory_static_max":
277 get_child_node_attribute(vm, "memory", "static_max"),
278 "memory_static_min":
279 get_child_node_attribute(vm, "memory", "static_min"),
280 "memory_dynamic_max":
281 get_child_node_attribute(vm, "memory", "dynamic_max"),
282 "memory_dynamic_min":
283 get_child_node_attribute(vm, "memory", "dynamic_min"),
284 "VCPUs_params":
285 get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
286 "VCPUs_max":
287 vm.attributes["vcpus_max"].value,
288 "VCPUs_at_startup":
289 vm.attributes["vcpus_at_startup"].value,
290 "actions_after_shutdown":
291 vm.attributes["actions_after_shutdown"].value,
292 "actions_after_reboot":
293 vm.attributes["actions_after_reboot"].value,
294 "actions_after_crash":
295 vm.attributes["actions_after_crash"].value,
296 "platform":
297 get_child_nodes_as_dict(vm, "platform", "key", "value"),
298 "other_config":
299 get_child_nodes_as_dict(vm, "other_config", "key", "value"),
300 "PV_bootloader":
301 "",
302 "PV_kernel":
303 "",
304 "PV_ramdisk":
305 "",
306 "PV_args":
307 "",
308 "PV_bootloader_args":
309 "",
310 "HVM_boot_policy":
311 "",
312 "HVM_boot_params":
313 {},
314 "PCI_bus":
315 ""
316 }
318 if vm.attributes.has_key("security_label"):
319 vm_record.update({
320 "security_label":
321 vm.attributes["security_label"].value
322 })
324 if len(vm.getElementsByTagName("pv")) > 0:
325 vm_record.update({
326 "PV_bootloader":
327 get_child_node_attribute(vm, "pv", "bootloader"),
328 "PV_kernel":
329 get_child_node_attribute(vm, "pv", "kernel"),
330 "PV_ramdisk":
331 get_child_node_attribute(vm, "pv", "ramdisk"),
332 "PV_args":
333 get_child_node_attribute(vm, "pv", "args"),
334 "PV_bootloader_args":
335 get_child_node_attribute(vm, "pv", "bootloader_args")
336 })
337 else:
338 hvm = vm.getElementsByTagName("hvm")[0]
339 vm_record.update({
340 "HVM_boot_policy":
341 get_child_node_attribute(vm, "hvm", "boot_policy"),
342 "HVM_boot_params":
343 get_child_nodes_as_dict(hvm, "boot_param", "key", "value")
344 })
345 try:
346 vm_ref = server.xenapi.VM.create(vm_record)
347 except:
348 traceback.print_exc()
349 sys.exit(-1)
351 try:
352 # Now create vbds
354 vbds = vm.getElementsByTagName("vbd")
356 self.create_vbds(vm_ref, vbds, vdis)
358 # Now create vifs
360 vifs = vm.getElementsByTagName("vif")
362 self.create_vifs(vm_ref, vifs, networks)
364 # Now create vtpms
366 vtpms = vm.getElementsByTagName("vtpm")
368 self.create_vtpms(vm_ref, vtpms)
370 # Now create consoles
372 consoles = vm.getElementsByTagName("console")
374 self.create_consoles(vm_ref, consoles)
376 # Now create pcis
378 pcis = vm.getElementsByTagName("pci")
380 self.create_pcis(vm_ref, pcis)
382 # Now create scsis
384 scsis = vm.getElementsByTagName("vscsi")
386 self.create_scsis(vm_ref, scsis)
388 return vm_ref
389 except:
390 server.xenapi.VM.destroy(vm_ref)
391 raise
393 def create_vbds(self, vm_ref, vbds, vdis):
394 log(DEBUG, "create_vbds")
395 return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
397 def create_vbd(self, vm_ref, vbd, vdis):
398 log(DEBUG, "create_vbd")
400 vbd_record = {
401 "VM":
402 vm_ref,
403 "VDI":
404 vdis[vbd.attributes["vdi"].value],
405 "device":
406 vbd.attributes["device"].value,
407 "bootable":
408 vbd.attributes["bootable"].value == "1",
409 "mode":
410 vbd.attributes["mode"].value,
411 "type":
412 vbd.attributes["type"].value,
413 "qos_algorithm_type":
414 vbd.attributes["qos_algorithm_type"].value,
415 "qos_algorithm_params":
416 get_child_nodes_as_dict(vbd,
417 "qos_algorithm_param", "key", "value")
418 }
420 return server.xenapi.VBD.create(vbd_record)
422 def create_vifs(self, vm_ref, vifs, networks):
423 log(DEBUG, "create_vifs")
424 return map(lambda vif: self.create_vif(vm_ref, vif, networks), vifs)
426 def create_vif(self, vm_ref, vif, networks):
427 log(DEBUG, "create_vif")
429 if 'network' in vif.attributes.keys():
430 network_name = vif.attributes['network'].value
432 if network_name in networks.keys():
433 network_uuid = networks[network_name]
434 else:
435 networks = dict([(record['name_label'], ref)
436 for ref, record in
437 server.xenapi.network.get_all_records().items()])
438 if network_name in networks.keys():
439 network_uuid = networks[network_name]
440 else:
441 raise OptionError("Network %s doesn't exist"
442 % vif.attributes["network"].value)
443 else:
444 network_uuid = self._get_network_ref()
446 vif_record = {
447 "device":
448 vif.attributes["device"].value,
449 "network":
450 network_uuid,
451 "VM":
452 vm_ref,
453 "MAC":
454 vif.attributes["mac"].value,
455 "MTU":
456 vif.attributes["mtu"].value,
457 "qos_algorithm_type":
458 vif.attributes["qos_algorithm_type"].value,
459 "qos_algorithm_params":
460 get_child_nodes_as_dict(vif,
461 "qos_algorithm_param", "key", "value"),
462 "security_label":
463 vif.attributes["security_label"].value
464 }
466 return server.xenapi.VIF.create(vif_record)
468 _network_refs = []
470 def _get_network_ref(self):
471 try:
472 return self._network_refs.pop(0)
473 except IndexError:
474 self._network_refs = server.xenapi.network.get_all()
475 return self._network_refs.pop(0)
477 def create_vtpms(self, vm_ref, vtpms):
478 if len(vtpms) > 1:
479 vtpms = [ vtpms[0] ]
480 log(DEBUG, "create_vtpms")
481 return map(lambda vtpm: self.create_vtpm(vm_ref, vtpm), vtpms)
483 def create_vtpm(self, vm_ref, vtpm):
484 vtpm_record = {
485 "VM":
486 vm_ref,
487 "backend":
488 vtpm.attributes["backend"].value
489 }
490 return server.xenapi.VTPM.create(vtpm_record)
492 def create_consoles(self, vm_ref, consoles):
493 log(DEBUG, "create_consoles")
494 return map(lambda console: self.create_console(vm_ref, console),
495 consoles)
497 def create_console(self, vm_ref, console):
498 log(DEBUG, "create_consoles")
500 console_record = {
501 "VM":
502 vm_ref,
503 "protocol":
504 console.attributes["protocol"].value,
505 "other_config":
506 get_child_nodes_as_dict(console,
507 "other_config", "key", "value")
508 }
510 return server.xenapi.console.create(console_record)
512 def create_pcis(self, vm_ref, pcis):
513 log(DEBUG, "create_pcis")
514 return map(lambda pci: self.create_pci(vm_ref, pci), pcis)
516 def create_pci(self, vm_ref, pci):
517 log(DEBUG, "create_pci")
519 domain = int(pci.attributes["domain"].value, 16)
520 bus = int(pci.attributes["bus"].value, 16)
521 slot = int(pci.attributes["slot"].value, 16)
522 func = int(pci.attributes["func"].value, 16)
523 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
525 target_ref = None
526 for ppci_ref in server.xenapi.PPCI.get_all():
527 if name == server.xenapi.PPCI.get_name(ppci_ref):
528 target_ref = ppci_ref
529 break
530 if target_ref is None:
531 log(DEBUG, "create_pci: pci device not found")
532 return None
534 dpci_record = {
535 "VM":
536 vm_ref,
537 "PPCI":
538 target_ref,
539 "hotplug_slot":
540 int(pci.attributes["func"].value, 16),
541 "options":
542 get_child_nodes_as_dict(pci,
543 "pci_opt", "key", "value")
544 }
546 return server.xenapi.DPCI.create(dpci_record)
548 def create_scsis(self, vm_ref, scsis):
549 log(DEBUG, "create_scsis")
550 return map(lambda scsi: self.create_scsi(vm_ref, scsi), scsis)
552 def create_scsi(self, vm_ref, scsi):
553 log(DEBUG, "create_scsi")
555 target_ref = None
556 for pscsi_ref in server.xenapi.PSCSI.get_all():
557 if scsi.attributes["p-dev"].value == server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
558 target_ref = pscsi_ref
559 break
560 if target_ref is None:
561 log(DEBUG, "create_scsi: scsi device not found")
562 return None
564 dscsi_record = {
565 "VM":
566 vm_ref,
567 "PSCSI":
568 target_ref,
569 "virtual_HCTL":
570 scsi.attributes["v-dev"].value
571 }
573 return server.xenapi.DSCSI.create(dscsi_record)
575 def get_child_by_name(exp, childname, default = None):
576 try:
577 return [child for child in sxp.children(exp)
578 if child[0] == childname][0][1]
579 except:
580 return default
582 # Convert old sxp into new xml
584 class sxp2xml:
586 def convert_sxp_to_xml(self, config, transient=False):
588 devices = [child for child in sxp.children(config)
589 if len(child) > 0 and child[0] == "device"]
591 vbds_sxp = map(lambda x: x[1], [device for device in devices
592 if device[1][0] in ("vbd", "tap")])
594 vifs_sxp = map(lambda x: x[1], [device for device in devices
595 if device[1][0] == "vif"])
597 vtpms_sxp = map(lambda x: x[1], [device for device in devices
598 if device[1][0] == "vtpm"])
600 vfbs_sxp = map(lambda x: x[1], [device for device in devices
601 if device[1][0] == "vfb"])
603 pcis_sxp = map(lambda x: x[1], [device for device in devices
604 if device[1][0] == "pci"])
606 scsis_sxp = map(lambda x: x[1], [device for device in devices
607 if device[1][0] == "vscsi"])
609 # Create XML Document
611 impl = getDOMImplementation()
613 document = impl.createDocument(None, "xm", None)
615 # Lets make the VM tag..
617 vm = document.createElement("vm")
619 # Some string compatibility
621 actions_after_shutdown \
622 = get_child_by_name(config, "on_poweroff", "destroy")
623 actions_after_reboot \
624 = get_child_by_name(config, "on_reboot", "restart")
625 actions_after_crash \
626 = get_child_by_name(config, "on_crash", "restart")
628 def conv_chk(val, vals):
629 val.replace("-", "_")
630 if val not in vals:
631 raise "Invalid value: " + val
632 else:
633 return val
635 actions_after_shutdown = conv_chk(actions_after_shutdown,\
636 XEN_API_ON_NORMAL_EXIT)
637 actions_after_reboot = conv_chk(actions_after_reboot, \
638 XEN_API_ON_NORMAL_EXIT)
639 actions_after_crash = conv_chk(actions_after_crash, \
640 XEN_API_ON_CRASH_BEHAVIOUR)
641 # Flesh out tag attributes
643 vm.attributes["is_a_template"] = "false"
644 vm.attributes["auto_power_on"] = "false"
645 vm.attributes["actions_after_shutdown"] \
646 = actions_after_shutdown
647 vm.attributes["actions_after_reboot"] \
648 = actions_after_reboot
649 vm.attributes["actions_after_crash"] \
650 = actions_after_crash
651 vm.attributes["PCI_bus"] = ""
653 vm.attributes["vcpus_max"] \
654 = str(get_child_by_name(config, "vcpus", 1))
655 vm.attributes["vcpus_at_startup"] \
656 = str(get_child_by_name(config, "vcpus", 1))
657 vm.attributes["s3_integrity"] \
658 = str(get_child_by_name(config, "s3_integrity", 0))
659 vm.attributes["superpages"] \
660 = str(get_child_by_name(config, "superpages", 0))
662 sec_data = get_child_by_name(config, "security")
663 if sec_data:
664 try :
665 vm.attributes['security_label'] = \
666 security.set_security_label(sec_data[0][1][1],sec_data[0][2][1])
667 except Exception, e:
668 raise "Invalid security data format: %s" % str(sec_data)
670 # Make the name tag
672 vm.appendChild(self.make_name_tag(
673 get_child_by_name(config, "name"), document))
675 # Make version tag
677 version = document.createElement("version")
678 version.appendChild(document.createTextNode("0"))
679 vm.appendChild(version)
681 # Make pv or hvm tag
683 image = get_child_by_name(config, "image")
685 if image[0] == "linux":
686 pv = document.createElement("pv")
687 pv.attributes["kernel"] \
688 = get_child_by_name(image, "kernel", "")
689 pv.attributes["bootloader"] \
690 = get_child_by_name(config, "bootloader", "")
691 pv.attributes["ramdisk"] \
692 = get_child_by_name(image, "ramdisk", "")
693 pv.attributes["args"] \
694 = "root=" + get_child_by_name(image, "root", "") \
695 + " " + get_child_by_name(image, "args", "")
696 pv.attributes["bootloader_args"] \
697 = get_child_by_name(config, "bootloader_args","")
699 vm.appendChild(pv)
700 elif image[0] == "hvm":
701 hvm = document.createElement("hvm")
702 hvm.attributes["boot_policy"] = "BIOS order"
704 boot_order = document.createElement("boot_param")
705 boot_order.attributes["key"] = "order"
706 boot_order.attributes["value"] \
707 = get_child_by_name(image, "boot", "abcd")
708 hvm.appendChild
710 vm.appendChild(hvm)
712 # Make memory tag
714 memory = document.createElement("memory")
716 memory_str = str(int(
717 get_child_by_name(config, "memory"))*1024*1024)
719 memory.attributes["static_min"] = str(0)
720 memory.attributes["static_max"] = memory_str
721 memory.attributes["dynamic_min"] = memory_str
722 memory.attributes["dynamic_max"] = memory_str
724 if get_child_by_name(config, "maxmem"):
725 memory.attributes["static_max"] = \
726 str(int(get_child_by_name(config, "maxmem")*1024*1024))
728 vm.appendChild(memory)
730 # And now the vbds
732 vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
734 map(vm.appendChild, vbds)
736 # And now the vifs
738 vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
740 map(vm.appendChild, vifs)
742 # And now the vTPMs
744 vtpms = map(lambda vtpm: self.extract_vtpm(vtpm, document), vtpms_sxp)
746 map(vm.appendChild, vtpms)
748 # And now the pcis
750 pcis = self.extract_pcis(pcis_sxp, document)
752 map(vm.appendChild, pcis)
754 # And now the scsis
756 scsis = self.extract_scsis(scsis_sxp, document)
758 map(vm.appendChild, scsis)
760 # Last but not least the consoles...
762 consoles = self.extract_consoles(image, document)
764 map(vm.appendChild, consoles)
766 vfbs = map(lambda vfb: self.extract_vfb(vfb, document), vfbs_sxp)
768 map(vm.appendChild, vfbs)
770 # Platform variables...
772 platform = self.extract_platform(image, document)
774 map(vm.appendChild, platform)
776 # transient?
778 if transient:
779 other_config = document.createElement("other_config")
780 other_config.attributes["key"] = "transient"
781 other_config.attributes["value"] = "True"
782 vm.appendChild(other_config)
784 # Add it to doc_root
786 document.documentElement.appendChild(vm)
788 # We want to pull out vdis
790 vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
792 map(document.documentElement.appendChild, vdis)
794 return document
796 def make_name_tag(self, label_text, document):
797 name = document.createElement("name")
799 label = document.createElement("label")
800 label.appendChild(document.createTextNode(str(label_text)))
801 name.appendChild(label)
803 description = document.createElement("description")
804 description.appendChild(document.createTextNode(" "))
805 name.appendChild(description)
807 return name
809 def extract_vbd(self, vbd_sxp, document):
810 src = get_child_by_name(vbd_sxp, "uname")
811 mode = get_child_by_name(vbd_sxp, "mode")
812 name = str(src.__hash__())
814 vbd = document.createElement("vbd")
816 vbd.attributes["name"] = "vdb" + name
817 vbd.attributes["vdi"] = "vdi" + name
818 vbd.attributes["mode"] \
819 = re.search("^w!{0,1}$", mode) and "RW" or "RO"
820 vbd.attributes["device"] \
821 = re.sub(":cdrom$", "", get_child_by_name(vbd_sxp, "dev"))
822 vbd.attributes["bootable"] = "1"
823 vbd.attributes["type"] \
824 = re.search(":cdrom$", get_child_by_name(vbd_sxp, "dev")) \
825 and "CD" or "disk"
826 vbd.attributes["qos_algorithm_type"] = ""
828 return vbd
830 def extract_vdi(self, vbd_sxp, document):
831 src = get_child_by_name(vbd_sxp, "uname")
832 mode = get_child_by_name(vbd_sxp, "mode")
833 name = "vdi" + str(src.__hash__())
835 vdi = document.createElement("vdi")
837 vdi.attributes["src"] = src
838 vdi.attributes["read_only"] \
839 = re.search("^w!{0,1}$", mode) and "False" or "True"
840 vdi.attributes["size"] = '-1'
841 vdi.attributes["type"] = "system"
842 vdi.attributes["sharable"] \
843 = re.search("^w!$", mode) and "True" or "False"
844 vdi.attributes["name"] = name
846 vdi.appendChild(self.make_name_tag(name, document))
848 return vdi
850 def extract_vif(self, vif_sxp, document):
852 vif = document.createElement("vif")
854 dev = get_child_by_name(vif_sxp, "vifname", None)
856 if dev is None:
857 dev = self.getFreshEthDevice()
859 vif.attributes["name"] \
860 = "vif" + str(dev.__hash__())
861 vif.attributes["mac"] \
862 = get_child_by_name(vif_sxp, "mac", "")
863 vif.attributes["mtu"] \
864 = get_child_by_name(vif_sxp, "mtu", "")
865 vif.attributes["device"] = dev
866 vif.attributes["qos_algorithm_type"] = ""
868 policy = get_child_by_name(vif_sxp, "policy")
869 label = get_child_by_name(vif_sxp, "label")
871 vif.attributes["security_label"] = security.set_security_label(policy, label)
873 if get_child_by_name(vif_sxp, "bridge") is not None:
874 vif.attributes["network"] \
875 = get_child_by_name(vif_sxp, "bridge")
877 return vif
879 def extract_vtpm(self, vtpm_sxp, document):
881 vtpm = document.createElement("vtpm")
883 vtpm.attributes["backend"] \
884 = get_child_by_name(vtpm_sxp, "backend", "0")
886 return vtpm
888 def extract_vfb(self, vfb_sxp, document):
890 vfb = document.createElement("console")
891 vfb.attributes["protocol"] = "rfb"
893 if get_child_by_name(vfb_sxp, "type", "") == "vnc":
894 vfb.appendChild(self.mk_other_config(
895 "type", "vnc",
896 document))
897 vfb.appendChild(self.mk_other_config(
898 "vncunused", get_child_by_name(vfb_sxp, "vncunused", "1"),
899 document))
900 vfb.appendChild(self.mk_other_config(
901 "vnclisten",
902 get_child_by_name(vfb_sxp, "vnclisten", "127.0.0.1"),
903 document))
904 vfb.appendChild(self.mk_other_config(
905 "vncdisplay", get_child_by_name(vfb_sxp, "vncdisplay", "0"),
906 document))
907 vfb.appendChild(self.mk_other_config(
908 "vncpasswd", get_child_by_name(vfb_sxp, "vncpasswd", ""),
909 document))
911 if get_child_by_name(vfb_sxp, "type", "") == "sdl":
912 vfb.appendChild(self.mk_other_config(
913 "type", "sdl",
914 document))
915 vfb.appendChild(self.mk_other_config(
916 "display", get_child_by_name(vfb_sxp, "display", ""),
917 document))
918 vfb.appendChild(self.mk_other_config(
919 "xauthority",
920 get_child_by_name(vfb_sxp, "xauthority", ""),
921 document))
922 vfb.appendChild(self.mk_other_config(
923 "opengl", get_child_by_name(vfb_sxp, "opengl", "1"),
924 document))
926 return vfb
928 def extract_pcis(self, pcis_sxp, document):
930 pcis = []
932 for pci_sxp in pcis_sxp:
933 for dev_sxp in sxp.children(pci_sxp, "dev"):
934 pci = document.createElement("pci")
936 pci.attributes["domain"] \
937 = get_child_by_name(dev_sxp, "domain", "0")
938 pci.attributes["bus"] \
939 = get_child_by_name(dev_sxp, "bus", "0")
940 pci.attributes["slot"] \
941 = get_child_by_name(dev_sxp, "slot", "0")
942 pci.attributes["func"] \
943 = get_child_by_name(dev_sxp, "func", "0")
944 pci.attributes["vslot"] \
945 = get_child_by_name(dev_sxp, "vslot", "0")
946 for opt in get_child_by_name(dev_sxp, "opts", ""):
947 if len(opt) > 0:
948 pci_opt = document.createElement("pci_opt")
949 pci_opt.attributes["key"] = opt[0]
950 pci_opt.attributes["value"] = opt[1]
951 pci.appendChild(pci_opt)
953 pcis.append(pci)
955 return pcis
957 def extract_scsis(self, scsis_sxp, document):
959 scsis = []
961 for scsi_sxp in scsis_sxp:
962 for dev_sxp in sxp.children(scsi_sxp, "dev"):
963 scsi = document.createElement("vscsi")
965 scsi.attributes["p-dev"] \
966 = get_child_by_name(dev_sxp, "p-dev")
967 scsi.attributes["v-dev"] \
968 = get_child_by_name(dev_sxp, "v-dev")
970 scsis.append(scsi)
972 return scsis
974 def mk_other_config(self, key, value, document):
975 other_config = document.createElement("other_config")
976 other_config.attributes["key"] = key
977 other_config.attributes["value"] = value
978 return other_config
980 def extract_consoles(self, image, document):
981 consoles = []
983 if int(get_child_by_name(image, "nographic", "1")) == 1:
984 return consoles
986 if int(get_child_by_name(image, "vnc", "0")) == 1:
987 console = document.createElement("console")
988 console.attributes["protocol"] = "rfb"
989 console.appendChild(self.mk_other_config(
990 "type", "vnc",
991 document))
992 console.appendChild(self.mk_other_config(
993 "vncunused", str(get_child_by_name(image, "vncunused", "1")),
994 document))
995 console.appendChild(self.mk_other_config(
996 "vnclisten",
997 get_child_by_name(image, "vnclisten", "127.0.0.1"),
998 document))
999 console.appendChild(self.mk_other_config(
1000 "vncdisplay", str(get_child_by_name(image, "vncdisplay", "0")),
1001 document))
1002 console.appendChild(self.mk_other_config(
1003 "vncpasswd", get_child_by_name(image, "vncpasswd", ""),
1004 document))
1005 consoles.append(console)
1006 if int(get_child_by_name(image, "sdl", "0")) == 1:
1007 console = document.createElement("console")
1008 console.attributes["protocol"] = "rfb"
1009 console.appendChild(self.mk_other_config(
1010 "type", "sdl",
1011 document))
1012 console.appendChild(self.mk_other_config(
1013 "display", get_child_by_name(image, "display", ""),
1014 document))
1015 console.appendChild(self.mk_other_config(
1016 "xauthority", get_child_by_name(image, "xauthority", ""),
1017 document))
1018 console.appendChild(self.mk_other_config(
1019 "opengl", str(get_child_by_name(image, "opengl", "1")),
1020 document))
1021 consoles.append(console)
1023 return consoles
1026 def extract_platform(self, image, document):
1028 platform_keys = [
1029 'acpi',
1030 'apic',
1031 'boot',
1032 'device_model',
1033 'loader',
1034 'fda',
1035 'fdb',
1036 'keymap',
1037 'isa',
1038 'localtime',
1039 'monitor',
1040 'pae',
1041 'rtc_timeoffset',
1042 'serial',
1043 'soundhw',
1044 'stdvga',
1045 'usb',
1046 'usbdevice',
1047 'hpet',
1048 'timer_mode',
1049 'vpt_align',
1050 'viridian',
1051 'vhpt',
1052 'guest_os_type',
1053 'hap',
1054 'pci_msitranslate',
1055 'pci_power_mgmt',
1056 'xen_platform_pci',
1059 platform_configs = []
1060 for key in platform_keys:
1061 value = get_child_by_name(image, key, None)
1062 if value is not None:
1063 platform = document.createElement("platform")
1064 platform.attributes["key"] = key
1065 platform.attributes["value"] = str(value)
1066 platform_configs.append(platform)
1068 return platform_configs
1070 _eths = -1
1072 def getFreshEthDevice(self):
1073 self._eths += 1
1074 return "eth%i" % self._eths