Esempio n. 1
0
def _dump_device(md_obj, data, node_name=_DEVICE):
    elems = []
    data = utils.picklecopy(data)

    for key in _IGNORED_KEYS:
        data.pop(key, None)

    for key in _DEVICE_SUBKEYS:
        value = data.pop(key, {})
        if not value and key in _NONEMPTY_KEYS:
            # empty elements make no sense
            continue

        if key == _PORT_MIRRORING:
            elems.append(_dump_port_mirroring(md_obj, value))
        elif key == _REPLICA:
            elems.append(_dump_device(md_obj, value, _REPLICA))
        elif key in _LAYERED_KEYS:
            elems.append(
                _dump_layered(md_obj, key, _LAYERED_KEYS[key], value)
            )
        elif key == _SPEC_PARAMS:
            elems.append(_dump_device_spec_params(md_obj, value))
        elif key == _PAYLOAD:
            elems.append(_dump_payload(md_obj, _PAYLOAD, value))
        else:
            elems.append(md_obj.dump(key, **value))

    dev_elem = md_obj.dump(node_name, **data)
    for elem in elems:
        vmxml.append_child(dev_elem, etree_child=elem)
    return dev_elem
Esempio n. 2
0
File: vmtune.py Progetto: EdDev/vdsm
def io_tune_to_dom(tune):
    """
    This method converts the VmDiskDeviceTuneLimits structure from the
    dictionary representation to the XML representation.

    :param tune: Dictionary representation of VmDiskDeviceTuneLimits
    :return: DOM XML of device node filled with values
    """
    device = vmxml.Element("device")

    if "name" in tune and tune["name"]:
        vmxml.set_attr(device, "name", tune["name"])

    if "path" in tune and tune["path"]:
        vmxml.set_attr(device, "path", tune["path"])

    if "maximum" in tune:
        maximum = vmxml.Element("maximum")
        vmxml.append_child(device, maximum)
        io_tune_values_to_dom(tune["maximum"], maximum)

    if "guaranteed" in tune:
        guaranteed = vmxml.Element("guaranteed")
        vmxml.append_child(device, guaranteed)
        io_tune_values_to_dom(tune["guaranteed"], guaranteed)

    return device
Esempio n. 3
0
def extract_device_snippet(device_type, xml_str=None, dom=None):
    if dom is None:
        dom = xmlutils.fromstring(xml_str)
    devs = vmxml.Element('devices')
    for dev in dom.findall('./devices/%s' % device_type):
        vmxml.append_child(devs, etree_child=dev)
    return xmlutils.tostring(devs, pretty=True)
Esempio n. 4
0
def _dump_layered(md_obj, key, subkey, value):
    chain = md_obj.make_element(key)
    for val in value:
        vmxml.append_child(
            chain,
            etree_child=md_obj.dump(subkey, **val)
        )
    return chain
Esempio n. 5
0
 def _build_tree(self, namespace=None, namespace_uri=None):
     metadata_obj = Metadata(namespace, namespace_uri)
     md_elem = metadata_obj.dump(self._name, **self._values)
     for (attrs, data) in self._devices:
         if data:
             dev_elem = _dump_device(metadata_obj, data)
             dev_elem.attrib.update(attrs)
             vmxml.append_child(md_elem, etree_child=dev_elem)
     if self._custom:
         custom_elem = metadata_obj.dump(_CUSTOM, **self._custom)
         vmxml.append_child(md_elem, etree_child=custom_elem)
     return md_elem
Esempio n. 6
0
    def test_disk_ignore_volumeinfo_from_metadata_xml(self):
        xml_snippet = u'''<volumeInfo>
            <path>/rhev/data-center/omitted/for/brevity</path>
            <volType>path</volType>
        </volumeInfo>'''

        root = xmlutils.fromstring(_DISK_DATA.metadata_xml)
        dev = vmxml.find_first(root, 'device')
        vmxml.append_child(dev, etree_child=xmlutils.fromstring(xml_snippet))
        data = _TestData(
            copy.deepcopy(_DISK_DATA.conf), xmlutils.tostring(root))
        self._check_drive_from_metadata_xml(data)
Esempio n. 7
0
 def _build_xml(self, namespace=None, namespace_uri=None):
     metadata_obj = Metadata(namespace, namespace_uri)
     with self._lock:
         md_elem = metadata_obj.dump(self._name, **self._values)
         for (attrs, data) in self._devices:
             if data:
                 dev_elem = _dump_device(metadata_obj, data)
                 dev_elem.attrib.update(attrs)
                 vmxml.append_child(md_elem, etree_child=dev_elem)
         if self._custom:
             custom_elem = metadata_obj.dump(_CUSTOM, **self._custom)
             vmxml.append_child(md_elem, etree_child=custom_elem)
     return vmxml.format_xml(md_elem, pretty=True)
Esempio n. 8
0
def _dump_device_spec_params(md_obj, value):
    payload = value.pop(_VM_PAYLOAD, None)
    if payload is not None:
        # mandatory for vmPayload
        payload_elem = _dump_payload(md_obj, _VM_PAYLOAD, payload)
    else:
        payload_elem = None

    spec_params_elem = md_obj.dump(_SPEC_PARAMS, **value)
    if payload_elem is not None:
        vmxml.append_child(spec_params_elem, etree_child=payload_elem)

    return spec_params_elem
Esempio n. 9
0
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)
Esempio n. 10
0
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
Esempio n. 11
0
def io_tune_list_to_dom(tunables):
    """
    This method converts a list of VmDiskDeviceTuneLimits dictionaries
    to XML representation.

    :param tunables: List of VmDiskDeviceTuneLimits dictionaries
    :return: DOM XML all device nodes
    """
    io_tune = vmxml.Element("ioTune")

    for tune in tunables:
        device = io_tune_to_dom(tune)
        vmxml.append_child(io_tune, device)

    return io_tune
Esempio n. 12
0
File: vmtune.py Progetto: EdDev/vdsm
def io_tune_list_to_dom(tunables):
    """
    This method converts a list of VmDiskDeviceTuneLimits dictionaries
    to XML representation.

    :param tunables: List of VmDiskDeviceTuneLimits dictionaries
    :return: DOM XML all device nodes
    """
    io_tune = vmxml.Element("ioTune")

    for tune in tunables:
        device = io_tune_to_dom(tune)
        vmxml.append_child(io_tune, device)

    return io_tune
Esempio n. 13
0
def _dump_device_spec_params(md_obj, value):
    # ignore if present, never serialize it: we should read the
    # IO tune settings from the libvirt domain XML
    value.pop(_IO_TUNE, None)
    payload = value.pop(_VM_PAYLOAD, None)
    if payload is not None:
        # mandatory for vmPayload
        payload_elem = _dump_payload(md_obj, _VM_PAYLOAD, payload)
    else:
        payload_elem = None

    spec_params_elem = md_obj.dump(_SPEC_PARAMS, **value)
    if payload_elem is not None:
        vmxml.append_child(spec_params_elem, etree_child=payload_elem)

    return spec_params_elem
Esempio n. 14
0
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
Esempio n. 15
0
def _dump_device_spec_params(md_obj, value):
    # ignore if present, never serialize it: we should read the
    # IO tune settings from the libvirt domain XML
    value.pop(_IO_TUNE, None)
    payload = value.pop(_VM_PAYLOAD, None)
    if payload is not None:
        # mandatory for vmPayload
        payload_elem = _dump_payload(md_obj, _VM_PAYLOAD, payload)
    else:
        payload_elem = None

    spec_params_elem = md_obj.dump(_SPEC_PARAMS, **value)
    if payload_elem is not None:
        vmxml.append_child(spec_params_elem, etree_child=payload_elem)

    return spec_params_elem
Esempio n. 16
0
File: vmtune.py Progetto: EdDev/vdsm
def io_tune_values_to_dom(values, dom):
    """
    Create a DOM representation of the passed iotune values and
    attach it to the dom object in the form of nodes.

    :param values: Dictionary mapping iotune key to its value
    :param dom: XML DOM object to attach the result to
    """
    ops = ("total", "read", "write")
    units = ("bytes", "iops")

    for op, unit in itertools.product(ops, units):
        name = op + "_" + unit + "_sec"
        if name in values and values[name] >= 0:
            el = vmxml.Element(name)
            el.appendTextNode(str(values[name]))
            vmxml.append_child(dom, el)
Esempio n. 17
0
def io_tune_values_to_dom(values, dom):
    """
    Create a DOM representation of the passed iotune values and
    attach it to the dom object in the form of nodes.

    :param values: Dictionary mapping iotune key to its value
    :param dom: XML DOM object to attach the result to
    """
    ops = ("total", "read", "write")
    units = ("bytes", "iops")

    for op, unit in itertools.product(ops, units):
        name = op + "_" + unit + "_sec"
        if name in values and values[name] >= 0:
            el = vmxml.Element(name)
            el.appendTextNode(str(values[name]))
            vmxml.append_child(dom, el)
Esempio n. 18
0
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
Esempio n. 19
0
 def test_append_child_etree(self):
     empty = vmxml.find_first(self._dom, 'empty')
     vmxml.append_child(empty, etree_child=vmxml.parse_xml('<new/>'))
     self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None))
     empty = vmxml.find_first(self._dom, 'empty')
     self.assertIsNotNone(vmxml.find_first(empty, 'new', None))
Esempio n. 20
0
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
Esempio n. 21
0
def _dump_layered(md_obj, key, subkey, value):
    chain = md_obj.make_element(key)
    for val in value:
        vmxml.append_child(chain, etree_child=md_obj.dump(subkey, **val))
    return chain
Esempio n. 22
0
 def test_append_child_etree(self):
     empty = vmxml.find_first(self._dom, 'empty')
     vmxml.append_child(empty, etree_child=xmlutils.fromstring('<new/>'))
     self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None))
     empty = vmxml.find_first(self._dom, 'empty')
     self.assertIsNotNone(vmxml.find_first(empty, 'new', None))
Esempio n. 23
0
 def test_append_child(self):
     empty = vmxml.find_first(self._dom, 'empty')
     vmxml.append_child(empty, vmxml.Element('new'))
     self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None))
     empty = vmxml.find_first(self._dom, 'empty')
     self.assertIsNotNone(vmxml.find_first(empty, 'new', None))
Esempio n. 24
0
 def test_append_child_too_many_args(self):
     empty = vmxml.find_first(self._dom, 'empty')
     with pytest.raises(RuntimeError):
         vmxml.append_child(empty, vmxml.Element('new'),
                            xmlutils.fromstring('<new/>'))
Esempio n. 25
0
 def test_append_child_noargs(self):
     empty = vmxml.find_first(self._dom, 'empty')
     with pytest.raises(RuntimeError):
         vmxml.append_child(empty)
Esempio n. 26
0
 def test_append_child(self):
     empty = vmxml.find_first(self._dom, 'empty')
     vmxml.append_child(empty, vmxml.Element('new'))
     assert vmxml.find_first(self._dom, 'new', None) is not None
     empty = vmxml.find_first(self._dom, 'empty')
     assert vmxml.find_first(empty, 'new', None) is not None
Esempio n. 27
0
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
Esempio n. 28
0
 def test_append_child(self):
     empty = vmxml.find_first(self._dom, 'empty')
     vmxml.append_child(empty, vmxml.Element('new'))
     self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None))
     empty = vmxml.find_first(self._dom, 'empty')
     self.assertIsNotNone(vmxml.find_first(empty, 'new', None))
Esempio n. 29
0
 def test_append_child_etree(self):
     empty = vmxml.find_first(self._dom, 'empty')
     vmxml.append_child(empty, etree_child=vmxml.parse_xml('<new/>'))
     self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None))
     empty = vmxml.find_first(self._dom, 'empty')
     self.assertIsNotNone(vmxml.find_first(empty, 'new', None))