def update_bandwidth_xml(iface, vnicXML, specParams=None): if (specParams and ('inbound' in specParams or 'outbound' in specParams)): oldBandwidth = vmxml.find_first(vnicXML, 'bandwidth', None) newBandwidth = iface.get_bandwidth_xml(specParams, oldBandwidth) if oldBandwidth is not None: vmxml.remove_child(vnicXML, oldBandwidth) vmxml.append_child(vnicXML, newBandwidth)
def test_remove_child(self): top = vmxml.find_first(self._dom, 'topelement') hello = list(vmxml.find_all(top, 'hello')) old = hello[1] vmxml.remove_child(top, old) updated_hello = list(vmxml.find_all(top, 'hello')) hello = hello[:1] + hello[2:] self.assertEqual(updated_hello, hello)
def test_remove_child(self): top = vmxml.find_first(self._dom, 'topelement') hello = list(vmxml.find_all(top, 'hello')) old = hello[1] vmxml.remove_child(top, old) updated_hello = list(vmxml.find_all(top, 'hello')) hello = hello[:1] + hello[2:] self.assertEqual(updated_hello, hello)
def metadata_descriptor(self): md_desc = metadata.Descriptor.from_tree(self._dom) yield md_desc old_md = vmxml.find_first(self._dom, 'metadata', None) if old_md is not None: vmxml.remove_child(self._dom, old_md) md_elem = etree.Element('metadata') vmxml.append_child(self._dom, etree_child=md_elem) vmxml.append_child(md_elem, etree_child=md_desc.to_tree())
def replace_device_xml_with_hooks_xml(dom, vm_id, vm_custom, md_desc=None): """ Process the before_device_create hook point. This means that some device XML snippet may be entirely replaced by the output of one hook. Hook are invoked only if a given device has custom properties. Please note that this explicitely required by the contract of the hook point, so we can't really do better than that. """ if md_desc is None: md_desc = metadata.Descriptor.from_tree(dom) # 'devices' MUST be present, so let's fail loudly if it isn't. devs = vmxml.find_first(dom, 'devices') to_remove = [] to_append = [] for dev_elem in vmxml.children(devs): if dev_elem.tag == vmdevices.hwclass.DISK: # disk devices need special processing, to be done separately continue try: dev_meta = vmdevices.common.dev_meta_from_elem( dev_elem, vm_id, md_desc) except vmdevices.core.SkipDevice: # metadata is optional, so it is ok to just skip devices # with no metadata attached. continue try: dev_custom = dev_meta['custom'] except KeyError: # custom properties are optional, and mostly used for # network devices. It is OK to just go ahead. continue hook_xml = hooks.before_device_create( xmlutils.tostring(dev_elem, pretty=True), vm_custom, dev_custom) to_remove.append(dev_elem) to_append.append(xmlutils.fromstring(hook_xml)) for dev_elem in to_remove: vmxml.remove_child(devs, dev_elem) for dev_elem in to_append: vmxml.append_child(devs, etree_child=dev_elem)
def replace_devices_xml(domxml, devices_xml): devices = vmxml.find_first(domxml, 'devices', None) old_devs = [ dev for dev in vmxml.children(devices) if dev.tag in hwclass.TO_REFRESH ] for old_dev in old_devs: vmxml.remove_child(devices, old_dev) for dev_class in hwclass.TO_REFRESH: for dev in devices_xml[dev_class]: vmxml.append_child(devices, etree_child=dev) return domxml
def replace_devices_xml(domxml, devices_xml): devices = vmxml.find_first(domxml, 'devices', None) refreshable = get_refreshable_device_classes() old_devs = [ dev for dev in vmxml.children(devices) if dev.tag in refreshable ] for old_dev in old_devs: vmxml.remove_child(devices, old_dev) for dev_class in refreshable: for dev in devices_xml[dev_class]: vmxml.append_child(devices, etree_child=dev) return domxml
def replace_disks_xml(dom, disk_devices): """ Replace the XML snippet of all disk devices with fresh configuration obtained from Vdsm. Vdsm initializes its disk device objects from the XML. Vdsm also needs to do some per-host adjustments on the disk devices (e.g. prepare the paths), so we can't avoid this replacement. """ # 'devices' MUST be present, so let's fail loudly if it isn't. devs = vmxml.find_first(dom, 'devices') to_remove = [ dev_elem for dev_elem in vmxml.children(devs) if dev_elem.tag == vmdevices.hwclass.DISK ] for dev_elem in to_remove: vmxml.remove_child(devs, dev_elem) for dev in disk_devices: vmxml.append_child(devs, child=dev.getXML()) return dom
def device(dom, **kwargs): """ Helper context manager to get the metadata of a given device from a libvirt Domain object. Please make sure to check the IMPORTANT WARNING below. Example: let's start with dom.metadata() -> <vm> <device id="dev0"> <foo>bar</foo> </device> <device id="dev1"> <number type="int">42</number> </device> </vm> let's run this code with metadata.device(dom, 'dev0') as dev: buzz = do_some_work(dev['foo']) dev['fizz'] = buzz now we will have dom.metadata() -> <vm> <device id="dev0"> <foo>bar</foo> <fizz>sometimes_buzz</fizz> </device> <device id="dev1"> <number type="int">42</number> </device> </vm> *** IMPORTANT WARNING *** This context manager will provide the client access only to the metadata of one device. Once it is done, it will update only that device, leaving metadata of the other devices, or the VM, unchanged. But under the hood, this context manager will *rewrite all the VM metadata*. You will need to make sure *every* usage of metadata (either per-vm or per-device) on the same libvirt.Domain is protected by one exclusive lock. Synchronization is intentionally not done in this module, it should be done at the same layer who owns the libvirt.Domain object. :param dom: domain to access :type dom: libvirt.Domain kwargs: attributes to match to identify the device; values are expected to be string. """ with _metadata_xml( dom, xmlconstants.METADATA_VM_VDSM_ELEMENT, xmlconstants.METADATA_VM_VDSM_PREFIX, xmlconstants.METADATA_VM_VDSM_URI ) as md: vm_elem = md[0] attrs = kwargs dev_elem = _find_device(vm_elem, attrs) if dev_elem is not None: attrs = dev_elem.attrib.copy() dev_found = True else: dev_found = False dev_elem = ET.Element(_DEVICE, **attrs) metadata_obj = Metadata() content = metadata_obj.load(dev_elem) yield content # we want to completely replace the device metadata - not update # the existing one - to not leave garbage behind if dev_found: vmxml.remove_child(vm_elem, dev_elem) dev_elem = metadata_obj.dump(_DEVICE, **content) dev_elem.attrib.update(attrs) vmxml.append_child(vm_elem, etree_child=dev_elem) md[0] = vm_elem
def device(dom, **kwargs): """ Helper context manager to get the metadata of a given device from a libvirt Domain object. Please make sure to check the IMPORTANT WARNING below. Example: let's start with dom.metadata() -> <vm> <device id="dev0"> <foo>bar</foo> </device> <device id="dev1"> <number type="int">42</number> </device> </vm> let's run this code with metadata.device(dom, 'dev0') as dev: buzz = do_some_work(dev['foo']) dev['fizz'] = buzz now we will have dom.metadata() -> <vm> <device id="dev0"> <foo>bar</foo> <fizz>sometimes_buzz</fizz> </device> <device id="dev1"> <number type="int">42</number> </device> </vm> *** IMPORTANT WARNING *** This context manager will provide the client access only to the metadata of one device. Once it is done, it will update only that device, leaving metadata of the other devices, or the VM, unchanged. But under the hood, this context manager will *rewrite all the VM metadata*. You will need to make sure *every* usage of metadata (either per-vm or per-device) on the same libvirt.Domain is protected by one exclusive lock. Synchronization is intentionally not done in this module, it should be done at the same layer who owns the libvirt.Domain object. :param dom: domain to access :type dom: libvirt.Domain kwargs: attributes to match to identify the device; values are expected to be string. """ with _metadata_xml(dom, xmlconstants.METADATA_VM_VDSM_ELEMENT, xmlconstants.METADATA_VM_VDSM_PREFIX, xmlconstants.METADATA_VM_VDSM_URI) as md: vm_elem = md[0] attrs = kwargs dev_elem = _find_device(vm_elem, attrs) if dev_elem is not None: attrs = dev_elem.attrib.copy() dev_found = True else: dev_found = False dev_elem = ET.Element(_DEVICE, **attrs) metadata_obj = Metadata() content = metadata_obj.load(dev_elem) yield content # we want to completely replace the device metadata - not update # the existing one - to not leave garbage behind if dev_found: vmxml.remove_child(vm_elem, dev_elem) dev_elem = metadata_obj.dump(_DEVICE, **content) dev_elem.attrib.update(attrs) vmxml.append_child(vm_elem, etree_child=dev_elem) md[0] = vm_elem