debuggers.hg

view tools/python/xen/xm/xenapi_create.py @ 21013:4ba4323889b9

python: Don't install anything directly under /usr/share
Signed-off-by: Guillaume Rousse <Guillaume.Rousse@inria.fr>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 22 18:47:22 2010 +0000 (2010-02-22)
parents d53db6af369f
children 6c338a5830b5
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 from xen.util.pci import pci_opts_list_from_sxp
30 from xen.util.path import SHAREDIR
31 import xen.util.xsm.xsm as security
33 import sys
34 import os
35 from os.path import join
36 import traceback
37 import re
39 def log(_, msg):
40 #print "> " + msg
41 pass
43 DEBUG = 0
45 def get_name_label(node):
46 name_node = node.getElementsByTagName("name")[0]
47 label_node = name_node.getElementsByTagName("label")[0]
48 return " ".join([child.nodeValue for child in label_node.childNodes])
50 def get_name_description(node):
51 name_node = node.getElementsByTagName("name")[0]
52 description_node = name_node.getElementsByTagName("description")[0]
53 return " ".join([child.nodeValue for child in description_node.childNodes])
55 def get_text_in_child_node(node, child):
56 tag_node = node.getElementsByTagName(child)[0]
57 return " ".join([child.nodeValue for child in tag_node.childNodes])
59 def get_child_node_attribute(node, child, attribute):
60 tag_node = node.getElementsByTagName(child)[0]
61 return tag_node.attributes[attribute].value
63 def get_child_nodes_as_dict(node, child_name,
64 key_attribute_name,
65 value_attribute_name):
66 return dict([(child.attributes[key_attribute_name].value,
67 child.attributes[value_attribute_name].value)
68 for child in node.getElementsByTagName(child_name)])
70 def try_quietly(fn, *args):
71 try:
72 return fn(*args)
73 except:
74 return None
76 class xenapi_create:
78 def __init__(self):
79 self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
81 self.dtd = join(SHAREDIR, "xen", "create.dtd")
83 def create(self, filename=None, document=None, skipdtd=False):
84 """
85 Create a domain from an XML file or DOM tree
86 """
87 if skipdtd:
88 print "Skipping DTD checks. Dangerous!"
90 if filename is not None:
91 if not skipdtd:
92 self.check_dtd(filename)
93 document = parse(filename)
94 elif document is not None:
95 if not skipdtd:
96 self.check_dom_against_dtd(document)
98 self.check_doc(document)
100 vdis = document.getElementsByTagName("vdi")
101 vdi_refs_dict = self.create_vdis(vdis)
103 networks = document.getElementsByTagName("network")
104 network_refs_dict = self.create_networks(networks)
106 try:
107 vms = document.getElementsByTagName("vm")
108 return self.create_vms(vms, vdi_refs_dict, network_refs_dict)
109 except Exception, exn:
110 try_quietly(self.cleanup_vdis(vdi_refs_dict))
111 raise exn
113 # Methods to check xml file
114 # try to use dtd to check where possible
115 def check_dtd(self, file):
116 """
117 Check file against DTD.
118 Use this if possible as it gives nice
119 error messages
120 """
121 dtd = xmldtd.load_dtd(self.dtd)
122 parser = xmlproc.XMLProcessor()
123 parser.set_application(xmlval.ValidatingApp(dtd, parser))
124 parser.dtd = dtd
125 parser.ent = dtd
126 parser.parse_resource(file)
128 def check_dom_against_dtd(self, dom):
129 """
130 Check DOM again DTD.
131 Doesn't give as nice error messages.
132 (no location info)
133 """
134 dtd = xmldtd.load_dtd(self.dtd)
135 app = xmlval.ValidatingApp(dtd, self)
136 app.set_locator(self)
137 self.dom2sax(dom, app)
139 # Get errors back from ValidatingApp
140 def report_error(self, number, args=None):
141 self.errors = xmlproc.errors.english
142 try:
143 msg = self.errors[number]
144 if args != None:
145 msg = msg % args
146 except KeyError:
147 msg = self.errors[4002] % number # Unknown err msg :-)
148 print msg
149 sys.exit(-1)
151 # Here for compatibility with ValidatingApp
152 def get_line(self):
153 return -1
155 def get_column(self):
156 return -1
158 def dom2sax(self, dom, app):
159 """
160 Take a dom tree and tarverse it,
161 issuing SAX calls to app.
162 """
163 for child in dom.childNodes:
164 if child.nodeType == child.TEXT_NODE:
165 data = child.nodeValue
166 app.handle_data(data, 0, len(data))
167 else:
168 app.handle_start_tag(
169 child.nodeName,
170 self.attrs_to_dict(child.attributes))
171 self.dom2sax(child, app)
172 app.handle_end_tag(child.nodeName)
174 def attrs_to_dict(self, attrs):
175 return dict(attrs.items())
177 #
178 # Checks which cannot be done with dtd
179 #
180 def check_doc(self, doc):
181 vms = doc.getElementsByTagName("vm")
182 self.check_vms(vms)
184 def check_vms(self, vms):
185 map(self.check_vm, vms)
187 def check_vm(self, vm):
188 vifs = vm.getElementsByTagName("vif")
189 self.check_vifs(vifs)
191 def check_vifs(self, vifs):
192 map(self.check_vif, vifs)
194 def check_vif(self, vif):
195 pass
197 # Cleanup methods here
198 def cleanup_vdis(self, vdi_refs_dict):
199 map(self.cleanup_vdi, vdi_refs_dict.values())
201 def cleanup_vdi(self, vdi_ref):
202 server.xenapi.VDI.destroy(vdi_ref)
204 def cleanup_vms(self, vm_refs):
205 map(self.cleanup_vm, vm_refs)
207 def cleanup_vm(self, vm_ref):
208 server.xenapi.VM.destroy(vm_ref)
210 # Create methods here
211 def create_vdis(self, vdis):
212 log(DEBUG, "create_vdis")
213 return dict(map(self.create_vdi, vdis))
215 def create_vdi(self, vdi):
216 log(DEBUG, "create_vdi")
218 for ref, record in server.xenapi.VDI.get_all_records().items():
219 location = record["other_config"]["location"]
220 if vdi.attributes["src"].value != location:
221 continue
223 # Reuse the VDI because the location is same.
224 key = vdi.attributes["name"].value
225 return (key, ref)
227 # Create a new VDI.
228 vdi_record = {
229 "name_label": get_name_label(vdi),
230 "name_description": get_name_description(vdi),
231 "SR": self.DEFAULT_STORAGE_REPOSITORY,
232 "virtual_size": vdi.attributes["size"].value,
233 "type": vdi.attributes["type"].value,
234 "sharable": vdi.attributes["sharable"].value == "True",
235 "read_only": vdi.attributes["read_only"].value == "True",
236 "other_config": {"location":
237 vdi.attributes["src"].value}
238 }
240 key = vdi.attributes["name"].value
241 value = server.xenapi.VDI.create(vdi_record)
243 return (key, value)
245 def create_networks(self, networks):
246 log(DEBUG, "create_networks")
247 return dict(map(self.create_network, networks))
249 def create_network(self, network):
250 log(DEBUG, "create_network")
252 network_record = {
253 "name_label": get_name_label(network),
254 "name_description": get_name_description(network),
255 "other_config":
256 get_child_nodes_as_dict(network, "other_config",
257 "key", "value"),
258 "default_netmask": network.attributes["default_netmask"].value,
259 "default_gateway": network.attributes["default_gateway"].value
260 }
262 key = network.attributes["name"].value
263 value = server.xenapi.network.create(network_record)
265 return (key, value)
267 def create_vms(self, vms, vdis, networks):
268 log(DEBUG, "create_vms")
269 return map(lambda vm: self.create_vm(vm, vdis, networks), vms)
271 def create_vm(self, vm, vdis, networks):
272 log(DEBUG, "create_vm")
274 vm_record = {
275 "name_label":
276 get_name_label(vm),
277 "name_description":
278 get_name_description(vm),
279 "user_version":
280 get_text_in_child_node(vm, "version"),
281 "is_a_template":
282 vm.attributes["is_a_template"].value == 'true',
283 "auto_power_on":
284 vm.attributes["auto_power_on"].value == 'true',
285 "s3_integrity":
286 vm.attributes["s3_integrity"].value,
287 "superpages":
288 vm.attributes["superpages"].value,
289 "memory_static_max":
290 get_child_node_attribute(vm, "memory", "static_max"),
291 "memory_static_min":
292 get_child_node_attribute(vm, "memory", "static_min"),
293 "memory_dynamic_max":
294 get_child_node_attribute(vm, "memory", "dynamic_max"),
295 "memory_dynamic_min":
296 get_child_node_attribute(vm, "memory", "dynamic_min"),
297 "VCPUs_params":
298 get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
299 "VCPUs_max":
300 vm.attributes["vcpus_max"].value,
301 "VCPUs_at_startup":
302 vm.attributes["vcpus_at_startup"].value,
303 "actions_after_shutdown":
304 vm.attributes["actions_after_shutdown"].value,
305 "actions_after_reboot":
306 vm.attributes["actions_after_reboot"].value,
307 "actions_after_crash":
308 vm.attributes["actions_after_crash"].value,
309 "platform":
310 get_child_nodes_as_dict(vm, "platform", "key", "value"),
311 "other_config":
312 get_child_nodes_as_dict(vm, "other_config", "key", "value"),
313 "PV_bootloader":
314 "",
315 "PV_kernel":
316 "",
317 "PV_ramdisk":
318 "",
319 "PV_args":
320 "",
321 "PV_bootloader_args":
322 "",
323 "HVM_boot_policy":
324 "",
325 "HVM_boot_params":
326 {},
327 "PCI_bus":
328 ""
329 }
331 if vm.attributes.has_key("security_label"):
332 vm_record.update({
333 "security_label":
334 vm.attributes["security_label"].value
335 })
337 if len(vm.getElementsByTagName("pv")) > 0:
338 vm_record.update({
339 "PV_bootloader":
340 get_child_node_attribute(vm, "pv", "bootloader"),
341 "PV_kernel":
342 get_child_node_attribute(vm, "pv", "kernel"),
343 "PV_ramdisk":
344 get_child_node_attribute(vm, "pv", "ramdisk"),
345 "PV_args":
346 get_child_node_attribute(vm, "pv", "args"),
347 "PV_bootloader_args":
348 get_child_node_attribute(vm, "pv", "bootloader_args")
349 })
350 else:
351 hvm = vm.getElementsByTagName("hvm")[0]
352 vm_record.update({
353 "HVM_boot_policy":
354 get_child_node_attribute(vm, "hvm", "boot_policy"),
355 "HVM_boot_params":
356 get_child_nodes_as_dict(hvm, "boot_param", "key", "value")
357 })
358 try:
359 vm_ref = server.xenapi.VM.create(vm_record)
360 except:
361 traceback.print_exc()
362 sys.exit(-1)
364 try:
365 # Now create vbds
367 vbds = vm.getElementsByTagName("vbd")
369 self.create_vbds(vm_ref, vbds, vdis)
371 # Now create vifs
373 vifs = vm.getElementsByTagName("vif")
375 self.create_vifs(vm_ref, vifs, networks)
377 # Now create vtpms
379 vtpms = vm.getElementsByTagName("vtpm")
381 self.create_vtpms(vm_ref, vtpms)
383 # Now create consoles
385 consoles = vm.getElementsByTagName("console")
387 self.create_consoles(vm_ref, consoles)
389 # Now create pcis
391 pcis = vm.getElementsByTagName("pci")
393 self.create_pcis(vm_ref, pcis)
395 # Now create scsis
397 scsis = vm.getElementsByTagName("vscsi")
399 self.create_scsis(vm_ref, scsis)
401 return vm_ref
402 except:
403 server.xenapi.VM.destroy(vm_ref)
404 raise
406 def create_vbds(self, vm_ref, vbds, vdis):
407 log(DEBUG, "create_vbds")
408 return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
410 def create_vbd(self, vm_ref, vbd, vdis):
411 log(DEBUG, "create_vbd")
413 vbd_record = {
414 "VM":
415 vm_ref,
416 "VDI":
417 vdis[vbd.attributes["vdi"].value],
418 "device":
419 vbd.attributes["device"].value,
420 "bootable":
421 vbd.attributes["bootable"].value == "1",
422 "mode":
423 vbd.attributes["mode"].value,
424 "type":
425 vbd.attributes["type"].value,
426 "qos_algorithm_type":
427 vbd.attributes["qos_algorithm_type"].value,
428 "qos_algorithm_params":
429 get_child_nodes_as_dict(vbd,
430 "qos_algorithm_param", "key", "value")
431 }
433 return server.xenapi.VBD.create(vbd_record)
435 def create_vifs(self, vm_ref, vifs, networks):
436 log(DEBUG, "create_vifs")
437 return map(lambda vif: self.create_vif(vm_ref, vif, networks), vifs)
439 def create_vif(self, vm_ref, vif, networks):
440 log(DEBUG, "create_vif")
442 if 'network' in vif.attributes.keys():
443 network_name = vif.attributes['network'].value
445 if network_name in networks.keys():
446 network_uuid = networks[network_name]
447 else:
448 networks = dict([(record['name_label'], ref)
449 for ref, record in
450 server.xenapi.network.get_all_records().items()])
451 if network_name in networks.keys():
452 network_uuid = networks[network_name]
453 else:
454 raise OptionError("Network %s doesn't exist"
455 % vif.attributes["network"].value)
456 else:
457 network_uuid = self._get_network_ref()
459 vif_record = {
460 "device":
461 vif.attributes["device"].value,
462 "network":
463 network_uuid,
464 "VM":
465 vm_ref,
466 "MAC":
467 vif.attributes["mac"].value,
468 "MTU":
469 vif.attributes["mtu"].value,
470 "qos_algorithm_type":
471 vif.attributes["qos_algorithm_type"].value,
472 "qos_algorithm_params":
473 get_child_nodes_as_dict(vif,
474 "qos_algorithm_param", "key", "value"),
475 "security_label":
476 vif.attributes["security_label"].value
477 }
479 return server.xenapi.VIF.create(vif_record)
481 _network_refs = []
483 def _get_network_ref(self):
484 try:
485 return self._network_refs.pop(0)
486 except IndexError:
487 self._network_refs = server.xenapi.network.get_all()
488 return self._network_refs.pop(0)
490 def create_vtpms(self, vm_ref, vtpms):
491 if len(vtpms) > 1:
492 vtpms = [ vtpms[0] ]
493 log(DEBUG, "create_vtpms")
494 return map(lambda vtpm: self.create_vtpm(vm_ref, vtpm), vtpms)
496 def create_vtpm(self, vm_ref, vtpm):
497 vtpm_record = {
498 "VM":
499 vm_ref,
500 "backend":
501 vtpm.attributes["backend"].value
502 }
503 return server.xenapi.VTPM.create(vtpm_record)
505 def create_consoles(self, vm_ref, consoles):
506 log(DEBUG, "create_consoles")
507 return map(lambda console: self.create_console(vm_ref, console),
508 consoles)
510 def create_console(self, vm_ref, console):
511 log(DEBUG, "create_consoles")
513 console_record = {
514 "VM":
515 vm_ref,
516 "protocol":
517 console.attributes["protocol"].value,
518 "other_config":
519 get_child_nodes_as_dict(console,
520 "other_config", "key", "value")
521 }
523 return server.xenapi.console.create(console_record)
525 def create_pcis(self, vm_ref, pcis):
526 log(DEBUG, "create_pcis")
527 return map(lambda pci: self.create_pci(vm_ref, pci), pcis)
529 def create_pci(self, vm_ref, pci):
530 log(DEBUG, "create_pci")
532 domain = int(pci.attributes["domain"].value, 16)
533 bus = int(pci.attributes["bus"].value, 16)
534 slot = int(pci.attributes["slot"].value, 16)
535 func = int(pci.attributes["func"].value, 16)
536 name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
538 target_ref = None
539 for ppci_ref in server.xenapi.PPCI.get_all():
540 if name == server.xenapi.PPCI.get_name(ppci_ref):
541 target_ref = ppci_ref
542 break
543 if target_ref is None:
544 log(DEBUG, "create_pci: pci device not found")
545 return None
547 dpci_record = {
548 "VM":
549 vm_ref,
550 "PPCI":
551 target_ref,
552 "hotplug_slot":
553 int(pci.attributes["vdevfn"].value, 16),
554 "options":
555 get_child_nodes_as_dict(pci,
556 "pci_opt", "key", "value"),
557 "key":
558 pci.attributes["key"].value
559 }
561 return server.xenapi.DPCI.create(dpci_record)
563 def create_scsis(self, vm_ref, scsis):
564 log(DEBUG, "create_scsis")
565 return map(lambda scsi: self.create_scsi(vm_ref, scsi), scsis)
567 def create_scsi(self, vm_ref, scsi):
568 log(DEBUG, "create_scsi")
570 if scsi.attributes["feature-host"].value == "True":
571 target_HBA_ref = None
572 for pscsi_HBA_ref in server.xenapi.PSCSI_HBA.get_all():
573 if int(scsi.attributes["devid"].value) == \
574 int(server.xenapi.PSCSI_HBA.get_physical_host(pscsi_HBA_ref)):
575 target_HBA_ref = pscsi_HBA_ref
576 break
577 if target_HBA_ref is None:
578 log(DEBUG, "create_scsi: scsi device not found")
579 return None
581 dscsi_record = {
582 "VM":
583 vm_ref,
584 "PSCSI_HBA":
585 target_HBA_ref,
586 "assignment_mode":
587 "HOST"
588 }
590 return server.xenapi.DSCSI_HBA.create(dscsi_record)
591 else:
592 target_ref = None
593 for pscsi_ref in server.xenapi.PSCSI.get_all():
594 if scsi.attributes["p-dev"].value == \
595 server.xenapi.PSCSI.get_physical_HCTL(pscsi_ref):
596 target_ref = pscsi_ref
597 break
598 if target_ref is None:
599 log(DEBUG, "create_scsi: scsi device not found")
600 return None
602 dscsi_record = {
603 "VM":
604 vm_ref,
605 "PSCSI":
606 target_ref,
607 "virtual_HCTL":
608 scsi.attributes["v-dev"].value
609 }
611 return server.xenapi.DSCSI.create(dscsi_record)
613 def get_child_by_name(exp, childname, default = None):
614 try:
615 return [child for child in sxp.children(exp)
616 if child[0] == childname][0][1]
617 except:
618 return default
620 # Convert old sxp into new xml
622 class sxp2xml:
624 def convert_sxp_to_xml(self, config, transient=False):
626 devices = [child for child in sxp.children(config)
627 if len(child) > 0 and child[0] == "device"]
629 vbds_sxp = map(lambda x: x[1], [device for device in devices
630 if device[1][0] in ("vbd", "tap", "tap2")])
632 vifs_sxp = map(lambda x: x[1], [device for device in devices
633 if device[1][0] == "vif"])
635 vtpms_sxp = map(lambda x: x[1], [device for device in devices
636 if device[1][0] == "vtpm"])
638 vfbs_sxp = map(lambda x: x[1], [device for device in devices
639 if device[1][0] == "vfb"])
641 pcis_sxp = map(lambda x: x[1], [device for device in devices
642 if device[1][0] == "pci"])
644 scsis_sxp = map(lambda x: x[1], [device for device in devices
645 if device[1][0] == "vscsi"])
647 # Create XML Document
649 impl = getDOMImplementation()
651 document = impl.createDocument(None, "xm", None)
653 # Lets make the VM tag..
655 vm = document.createElement("vm")
657 # Some string compatibility
659 actions_after_shutdown \
660 = get_child_by_name(config, "on_poweroff", "destroy")
661 actions_after_reboot \
662 = get_child_by_name(config, "on_reboot", "restart")
663 actions_after_crash \
664 = get_child_by_name(config, "on_crash", "restart")
666 def conv_chk(val, vals):
667 val.replace("-", "_")
668 if val not in vals:
669 raise "Invalid value: " + val
670 else:
671 return val
673 actions_after_shutdown = conv_chk(actions_after_shutdown,\
674 XEN_API_ON_NORMAL_EXIT)
675 actions_after_reboot = conv_chk(actions_after_reboot, \
676 XEN_API_ON_NORMAL_EXIT)
677 actions_after_crash = conv_chk(actions_after_crash, \
678 XEN_API_ON_CRASH_BEHAVIOUR)
679 # Flesh out tag attributes
681 vm.attributes["is_a_template"] = "false"
682 vm.attributes["auto_power_on"] = "false"
683 vm.attributes["actions_after_shutdown"] \
684 = actions_after_shutdown
685 vm.attributes["actions_after_reboot"] \
686 = actions_after_reboot
687 vm.attributes["actions_after_crash"] \
688 = actions_after_crash
689 vm.attributes["PCI_bus"] = ""
691 vm.attributes["vcpus_max"] \
692 = str(get_child_by_name(config, "vcpus", 1))
693 vm.attributes["vcpus_at_startup"] \
694 = str(get_child_by_name(config, "vcpus", 1))
695 vm.attributes["s3_integrity"] \
696 = str(get_child_by_name(config, "s3_integrity", 0))
697 vm.attributes["superpages"] \
698 = str(get_child_by_name(config, "superpages", 0))
700 sec_data = get_child_by_name(config, "security")
701 if sec_data:
702 try :
703 vm.attributes['security_label'] = \
704 security.set_security_label(sec_data[0][1][1],sec_data[0][2][1])
705 except Exception, e:
706 raise "Invalid security data format: %s" % str(sec_data)
708 # Make the name tag
710 vm.appendChild(self.make_name_tag(
711 get_child_by_name(config, "name"), document))
713 # Make version tag
715 version = document.createElement("version")
716 version.appendChild(document.createTextNode("0"))
717 vm.appendChild(version)
719 # Make pv or hvm tag
721 image = get_child_by_name(config, "image")
723 if image[0] == "linux":
724 pv = document.createElement("pv")
725 pv.attributes["kernel"] \
726 = get_child_by_name(image, "kernel", "")
727 pv.attributes["bootloader"] \
728 = get_child_by_name(config, "bootloader", "")
729 pv.attributes["ramdisk"] \
730 = get_child_by_name(image, "ramdisk", "")
731 pv.attributes["args"] \
732 = "root=" + get_child_by_name(image, "root", "") \
733 + " " + get_child_by_name(image, "args", "")
734 pv.attributes["bootloader_args"] \
735 = get_child_by_name(config, "bootloader_args","")
737 vm.appendChild(pv)
738 elif image[0] == "hvm":
739 hvm = document.createElement("hvm")
740 hvm.attributes["boot_policy"] = "BIOS order"
742 boot_order = document.createElement("boot_param")
743 boot_order.attributes["key"] = "order"
744 boot_order.attributes["value"] \
745 = get_child_by_name(image, "boot", "abcd")
746 hvm.appendChild
748 vm.appendChild(hvm)
750 # Make memory tag
752 memory = document.createElement("memory")
754 memory_str = str(int(
755 get_child_by_name(config, "memory"))*1024*1024)
757 memory.attributes["static_min"] = str(0)
758 memory.attributes["static_max"] = memory_str
759 memory.attributes["dynamic_min"] = memory_str
760 memory.attributes["dynamic_max"] = memory_str
762 if get_child_by_name(config, "maxmem"):
763 memory.attributes["static_max"] = \
764 str(int(get_child_by_name(config, "maxmem")*1024*1024))
766 vm.appendChild(memory)
768 # And now the vbds
770 vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
772 map(vm.appendChild, vbds)
774 # And now the vifs
776 vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
778 map(vm.appendChild, vifs)
780 # And now the vTPMs
782 vtpms = map(lambda vtpm: self.extract_vtpm(vtpm, document), vtpms_sxp)
784 map(vm.appendChild, vtpms)
786 # And now the pcis
788 pcis = self.extract_pcis(pcis_sxp, document)
790 map(vm.appendChild, pcis)
792 # And now the scsis
794 scsis = self.extract_scsis(scsis_sxp, document)
796 map(vm.appendChild, scsis)
798 # Last but not least the consoles...
800 consoles = self.extract_consoles(image, document)
802 map(vm.appendChild, consoles)
804 vfbs = map(lambda vfb: self.extract_vfb(vfb, document), vfbs_sxp)
806 map(vm.appendChild, vfbs)
808 # Platform variables...
810 platform = self.extract_platform(image, document)
812 map(vm.appendChild, platform)
814 # And now the vcpu_params
816 vcpu_params = self.extract_vcpu_params(config, document)
818 map(vm.appendChild, vcpu_params)
820 # transient?
822 if transient:
823 other_config = document.createElement("other_config")
824 other_config.attributes["key"] = "transient"
825 other_config.attributes["value"] = "True"
826 vm.appendChild(other_config)
828 # Add it to doc_root
830 document.documentElement.appendChild(vm)
832 # We want to pull out vdis
834 vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
836 map(document.documentElement.appendChild, vdis)
838 return document
840 def make_name_tag(self, label_text, document):
841 name = document.createElement("name")
843 label = document.createElement("label")
844 label.appendChild(document.createTextNode(str(label_text)))
845 name.appendChild(label)
847 description = document.createElement("description")
848 description.appendChild(document.createTextNode(" "))
849 name.appendChild(description)
851 return name
853 def extract_vbd(self, vbd_sxp, document):
854 src = get_child_by_name(vbd_sxp, "uname")
855 mode = get_child_by_name(vbd_sxp, "mode")
856 name = str(src.__hash__())
858 vbd = document.createElement("vbd")
860 vbd.attributes["name"] = "vdb" + name
861 vbd.attributes["vdi"] = "vdi" + name
862 vbd.attributes["mode"] \
863 = re.search("^w!{0,1}$", mode) and "RW" or "RO"
864 vbd.attributes["device"] \
865 = re.sub(":cdrom$", "", get_child_by_name(vbd_sxp, "dev"))
866 vbd.attributes["bootable"] = "1"
867 vbd.attributes["type"] \
868 = re.search(":cdrom$", get_child_by_name(vbd_sxp, "dev")) \
869 and "CD" or "disk"
870 vbd.attributes["qos_algorithm_type"] = ""
872 return vbd
874 def extract_vdi(self, vbd_sxp, document):
875 src = get_child_by_name(vbd_sxp, "uname")
876 mode = get_child_by_name(vbd_sxp, "mode")
877 name = "vdi" + str(src.__hash__())
879 vdi = document.createElement("vdi")
881 vdi.attributes["src"] = src
882 vdi.attributes["read_only"] \
883 = re.search("^w!{0,1}$", mode) and "False" or "True"
884 vdi.attributes["size"] = '-1'
885 vdi.attributes["type"] = "system"
886 vdi.attributes["sharable"] \
887 = re.search("^w!$", mode) and "True" or "False"
888 vdi.attributes["name"] = name
890 vdi.appendChild(self.make_name_tag(name, document))
892 return vdi
894 def extract_vif(self, vif_sxp, document):
896 vif = document.createElement("vif")
898 dev = get_child_by_name(vif_sxp, "vifname", None)
900 if dev is None:
901 dev = self.getFreshEthDevice()
903 vif.attributes["name"] \
904 = "vif" + str(dev.__hash__())
905 vif.attributes["mac"] \
906 = get_child_by_name(vif_sxp, "mac", "")
907 vif.attributes["mtu"] \
908 = get_child_by_name(vif_sxp, "mtu", "")
909 vif.attributes["device"] = dev
910 vif.attributes["qos_algorithm_type"] = ""
912 policy = get_child_by_name(vif_sxp, "policy")
913 label = get_child_by_name(vif_sxp, "label")
915 vif.attributes["security_label"] = security.set_security_label(policy, label)
917 if get_child_by_name(vif_sxp, "bridge") is not None:
918 vif.attributes["network"] \
919 = get_child_by_name(vif_sxp, "bridge")
921 return vif
923 def extract_vtpm(self, vtpm_sxp, document):
925 vtpm = document.createElement("vtpm")
927 vtpm.attributes["backend"] \
928 = get_child_by_name(vtpm_sxp, "backend", "0")
930 return vtpm
932 def extract_vfb(self, vfb_sxp, document):
934 vfb = document.createElement("console")
935 vfb.attributes["protocol"] = "rfb"
937 if get_child_by_name(vfb_sxp, "type", "") == "vnc":
938 vfb.appendChild(self.mk_other_config(
939 "type", "vnc",
940 document))
941 vfb.appendChild(self.mk_other_config(
942 "vncunused", get_child_by_name(vfb_sxp, "vncunused", "1"),
943 document))
944 vfb.appendChild(self.mk_other_config(
945 "vnclisten",
946 get_child_by_name(vfb_sxp, "vnclisten", "127.0.0.1"),
947 document))
948 vfb.appendChild(self.mk_other_config(
949 "vncdisplay", get_child_by_name(vfb_sxp, "vncdisplay", "0"),
950 document))
951 vfb.appendChild(self.mk_other_config(
952 "vncpasswd", get_child_by_name(vfb_sxp, "vncpasswd", ""),
953 document))
955 if get_child_by_name(vfb_sxp, "type", "") == "sdl":
956 vfb.appendChild(self.mk_other_config(
957 "type", "sdl",
958 document))
959 vfb.appendChild(self.mk_other_config(
960 "display", get_child_by_name(vfb_sxp, "display", ""),
961 document))
962 vfb.appendChild(self.mk_other_config(
963 "xauthority",
964 get_child_by_name(vfb_sxp, "xauthority", ""),
965 document))
966 vfb.appendChild(self.mk_other_config(
967 "opengl", get_child_by_name(vfb_sxp, "opengl", "1"),
968 document))
970 return vfb
972 def extract_pcis(self, pcis_sxp, document):
974 pcis = []
976 for pci_sxp in pcis_sxp:
977 for dev_sxp in sxp.children(pci_sxp, "dev"):
978 pci = document.createElement("pci")
980 pci.attributes["domain"] \
981 = get_child_by_name(dev_sxp, "domain", "0")
982 pci.attributes["bus"] \
983 = get_child_by_name(dev_sxp, "bus", "0")
984 pci.attributes["slot"] \
985 = get_child_by_name(dev_sxp, "slot", "0")
986 pci.attributes["func"] \
987 = get_child_by_name(dev_sxp, "func", "0")
988 pci.attributes["vdevfn"] \
989 = get_child_by_name(dev_sxp, "vdevfn", "0")
990 pci.attributes["key"] \
991 = get_child_by_name(dev_sxp, "key", "0")
992 for opt in pci_opts_list_from_sxp(dev_sxp):
993 pci_opt = document.createElement("pci_opt")
994 pci_opt.attributes["key"] = opt[0]
995 pci_opt.attributes["value"] = opt[1]
996 pci.appendChild(pci_opt)
998 pcis.append(pci)
1000 return pcis
1002 def extract_scsis(self, scsis_sxp, document):
1004 scsis = []
1006 for scsi_sxp in scsis_sxp:
1007 feature_host = sxp.child_value(scsi_sxp, "feature-host")
1008 for dev_sxp in sxp.children(scsi_sxp, "dev"):
1009 scsi = document.createElement("vscsi")
1011 scsi.attributes["feature-host"] \
1012 = feature_host and "True" or "False"
1013 if feature_host:
1014 scsi.attributes["devid"] \
1015 = str(get_child_by_name(dev_sxp, "devid"))
1016 scsis.append(scsi)
1017 break
1018 else:
1019 scsi.attributes["p-dev"] \
1020 = get_child_by_name(dev_sxp, "p-dev")
1021 scsi.attributes["v-dev"] \
1022 = get_child_by_name(dev_sxp, "v-dev")
1023 scsis.append(scsi)
1025 return scsis
1027 def mk_other_config(self, key, value, document):
1028 other_config = document.createElement("other_config")
1029 other_config.attributes["key"] = key
1030 other_config.attributes["value"] = value
1031 return other_config
1033 def extract_consoles(self, image, document):
1034 consoles = []
1036 if int(get_child_by_name(image, "nographic", "1")) == 1:
1037 return consoles
1039 if int(get_child_by_name(image, "vnc", "0")) == 1:
1040 console = document.createElement("console")
1041 console.attributes["protocol"] = "rfb"
1042 console.appendChild(self.mk_other_config(
1043 "type", "vnc",
1044 document))
1045 console.appendChild(self.mk_other_config(
1046 "vncunused", str(get_child_by_name(image, "vncunused", "1")),
1047 document))
1048 console.appendChild(self.mk_other_config(
1049 "vnclisten",
1050 get_child_by_name(image, "vnclisten", "127.0.0.1"),
1051 document))
1052 console.appendChild(self.mk_other_config(
1053 "vncdisplay", str(get_child_by_name(image, "vncdisplay", "0")),
1054 document))
1055 console.appendChild(self.mk_other_config(
1056 "vncpasswd", get_child_by_name(image, "vncpasswd", ""),
1057 document))
1058 consoles.append(console)
1059 if int(get_child_by_name(image, "sdl", "0")) == 1:
1060 console = document.createElement("console")
1061 console.attributes["protocol"] = "rfb"
1062 console.appendChild(self.mk_other_config(
1063 "type", "sdl",
1064 document))
1065 console.appendChild(self.mk_other_config(
1066 "display", get_child_by_name(image, "display", ""),
1067 document))
1068 console.appendChild(self.mk_other_config(
1069 "xauthority", get_child_by_name(image, "xauthority", ""),
1070 document))
1071 console.appendChild(self.mk_other_config(
1072 "opengl", str(get_child_by_name(image, "opengl", "1")),
1073 document))
1074 consoles.append(console)
1076 return consoles
1079 def extract_platform(self, image, document):
1081 platform_keys = [
1082 'acpi',
1083 'apic',
1084 'boot',
1085 'device_model',
1086 'loader',
1087 'fda',
1088 'fdb',
1089 'keymap',
1090 'isa',
1091 'localtime',
1092 'monitor',
1093 'pae',
1094 'rtc_timeoffset',
1095 'serial',
1096 'soundhw',
1097 'stdvga',
1098 'usb',
1099 'usbdevice',
1100 'hpet',
1101 'timer_mode',
1102 'vpt_align',
1103 'viridian',
1104 'vhpt',
1105 'guest_os_type',
1106 'hap',
1107 'oos',
1108 'pci_msitranslate',
1109 'pci_power_mgmt',
1110 'xen_platform_pci',
1111 'tsc_mode'
1112 'description',
1113 'nomigrate'
1116 platform_configs = []
1117 for key in platform_keys:
1118 value = get_child_by_name(image, key, None)
1119 if value is not None:
1120 platform = document.createElement("platform")
1121 platform.attributes["key"] = key
1122 platform.attributes["value"] = str(value)
1123 platform_configs.append(platform)
1125 return platform_configs
1127 def extract_vcpu_params(self, config, document):
1128 vcpu_params = []
1130 vcpu_param = document.createElement("vcpu_param")
1131 vcpu_param.attributes["key"] = "weight"
1132 vcpu_param.attributes["value"] \
1133 = str(get_child_by_name(config, "cpu_weight", 256))
1134 vcpu_params.append(vcpu_param)
1136 vcpu_param = document.createElement("vcpu_param")
1137 vcpu_param.attributes["key"] = "cap"
1138 vcpu_param.attributes["value"] \
1139 = str(get_child_by_name(config, "cpu_cap", 0))
1140 vcpu_params.append(vcpu_param)
1142 cpus = get_child_by_name(config, "cpus", [])
1143 if type(cpus) == list:
1144 vcpu = 0
1145 for cpu in cpus:
1146 if cpu:
1147 vcpu_param = document.createElement("vcpu_param")
1148 vcpu_param.attributes["key"] = "cpumap%i" % vcpu
1149 vcpu_param.attributes["value"] = str(cpu)
1150 vcpu_params.append(vcpu_param)
1151 vcpu = vcpu + 1
1152 else:
1153 for vcpu in range(0, int(get_child_by_name(config, "vcpus", 1))):
1154 vcpu_param = document.createElement("vcpu_param")
1155 vcpu_param.attributes["key"] = "cpumap%i" % vcpu
1156 vcpu_param.attributes["value"] = str(cpus)
1157 vcpu_params.append(vcpu_param)
1159 return vcpu_params
1161 _eths = -1
1163 def getFreshEthDevice(self):
1164 self._eths += 1
1165 return "eth%i" % self._eths