xmlbuilder: Simplify global XML vars
Just have classes specify a root XML path, and figure out root name, indentation, and dumpxml path from there.
This commit is contained in:
parent
43d15d67ac
commit
7411776c9a
|
@ -27,9 +27,8 @@ class CPUFeature(XMLBuilder):
|
||||||
|
|
||||||
POLICIES = ["force", "require", "optional", "disable", "forbid"]
|
POLICIES = ["force", "require", "optional", "disable", "forbid"]
|
||||||
|
|
||||||
|
_XML_ROOT_XPATH = "/domain/cpu/feature"
|
||||||
_XML_PROP_ORDER = ["_xmlname", "policy"]
|
_XML_PROP_ORDER = ["_xmlname", "policy"]
|
||||||
_XML_ROOT_NAME = "cpu"
|
|
||||||
_XML_INDENT = 4
|
|
||||||
|
|
||||||
def __init__(self, conn, name, parsexml=None, parsexmlnode=None):
|
def __init__(self, conn, name, parsexml=None, parsexmlnode=None):
|
||||||
XMLBuilder.__init__(self, conn, parsexml, parsexmlnode)
|
XMLBuilder.__init__(self, conn, parsexml, parsexmlnode)
|
||||||
|
@ -60,9 +59,7 @@ class CPU(XMLBuilder):
|
||||||
|
|
||||||
MATCHS = ["minimum", "exact", "strict"]
|
MATCHS = ["minimum", "exact", "strict"]
|
||||||
|
|
||||||
_dumpxml_xpath = "/domain/cpu"
|
_XML_ROOT_XPATH = "/domain/cpu"
|
||||||
_XML_ROOT_NAME = "cpu"
|
|
||||||
_XML_INDENT = 2
|
|
||||||
_XML_PROP_ORDER = ["mode", "match", "model", "vendor",
|
_XML_PROP_ORDER = ["mode", "match", "model", "vendor",
|
||||||
"sockets", "cores", "threads", "_features"]
|
"sockets", "cores", "threads", "_features"]
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,6 @@ from virtinst.xmlbuilder import XMLBuilder, XMLProperty
|
||||||
|
|
||||||
|
|
||||||
class Clock(XMLBuilder):
|
class Clock(XMLBuilder):
|
||||||
_dumpxml_xpath = "/domain/clock"
|
_XML_ROOT_XPATH = "/domain/clock"
|
||||||
_XML_INDENT = 2
|
|
||||||
_XML_ROOT_NAME = "clock"
|
|
||||||
|
|
||||||
offset = XMLProperty(xpath="./clock/@offset")
|
offset = XMLProperty(xpath="./clock/@offset")
|
||||||
|
|
|
@ -24,9 +24,7 @@ class DomainFeatures(XMLBuilder):
|
||||||
"""
|
"""
|
||||||
Class for generating <features> XML
|
Class for generating <features> XML
|
||||||
"""
|
"""
|
||||||
_dumpxml_xpath = "/domain/features"
|
_XML_ROOT_XPATH = "/domain/features"
|
||||||
_XML_ROOT_NAME = "features"
|
|
||||||
_XML_INDENT = 2
|
|
||||||
_XML_PROP_ORDER = ["acpi", "apic", "pae"]
|
_XML_PROP_ORDER = ["acpi", "apic", "pae"]
|
||||||
|
|
||||||
acpi = XMLProperty(xpath="./features/acpi", is_tri=True)
|
acpi = XMLProperty(xpath="./features/acpi", is_tri=True)
|
||||||
|
|
|
@ -95,9 +95,7 @@ class DomainNumatune(XMLBuilder):
|
||||||
|
|
||||||
MEMORY_MODES = ["interleave", "strict", "preferred"]
|
MEMORY_MODES = ["interleave", "strict", "preferred"]
|
||||||
|
|
||||||
_dumpxml_xpath = "/domain/numatune"
|
_XML_ROOT_XPATH = "/domain/numatune"
|
||||||
_XML_ROOT_NAME = "numatune"
|
|
||||||
_XML_INDENT = 2
|
|
||||||
_XML_PROP_ORDER = ["memory_mode", "memory_nodeset"]
|
_XML_PROP_ORDER = ["memory_mode", "memory_nodeset"]
|
||||||
|
|
||||||
memory_nodeset = XMLProperty(xpath="./numatune/memory/@nodeset")
|
memory_nodeset = XMLProperty(xpath="./numatune/memory/@nodeset")
|
||||||
|
|
|
@ -161,8 +161,7 @@ class Guest(XMLBuilder):
|
||||||
return cpustr
|
return cpustr
|
||||||
|
|
||||||
|
|
||||||
_XML_ROOT_NAME = "domain"
|
_XML_ROOT_XPATH = "/domain"
|
||||||
_XML_INDENT = 0
|
|
||||||
_XML_PROP_ORDER = ["type", "name", "uuid", "description",
|
_XML_PROP_ORDER = ["type", "name", "uuid", "description",
|
||||||
"maxmemory", "memory", "hugepage", "vcpus", "curvcpus",
|
"maxmemory", "memory", "hugepage", "vcpus", "curvcpus",
|
||||||
"numatune", "bootloader", "os", "features", "cpu", "clock",
|
"numatune", "bootloader", "os", "features", "cpu", "clock",
|
||||||
|
|
|
@ -38,9 +38,7 @@ class Seclabel(XMLBuilder):
|
||||||
MODEL_NONE = "none"
|
MODEL_NONE = "none"
|
||||||
MODELS = [MODEL_SELINUX, MODEL_DAC, MODEL_NONE]
|
MODELS = [MODEL_SELINUX, MODEL_DAC, MODEL_NONE]
|
||||||
|
|
||||||
_dumpxml_xpath = "/domain/seclabel"
|
_XML_ROOT_XPATH = "/domain/seclabel"
|
||||||
_XML_ROOT_NAME = "seclabel"
|
|
||||||
_XML_INDENT = 2
|
|
||||||
_XML_PROP_ORDER = ["type", "model", "relabel", "label", "imagelabel"]
|
_XML_PROP_ORDER = ["type", "model", "relabel", "label", "imagelabel"]
|
||||||
|
|
||||||
def _guess_secmodel(self):
|
def _guess_secmodel(self):
|
||||||
|
|
|
@ -75,7 +75,6 @@ class VirtualDevice(XMLBuilder):
|
||||||
|
|
||||||
# General device type (disk, interface, etc.)
|
# General device type (disk, interface, etc.)
|
||||||
virtual_device_type = None
|
virtual_device_type = None
|
||||||
_XML_INDENT = 4
|
|
||||||
|
|
||||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||||
"""
|
"""
|
||||||
|
@ -83,8 +82,9 @@ class VirtualDevice(XMLBuilder):
|
||||||
|
|
||||||
@param conn: libvirt connection to validate device against
|
@param conn: libvirt connection to validate device against
|
||||||
"""
|
"""
|
||||||
|
self._XML_ROOT_XPATH = "/domain/devices/%s" % self.virtual_device_type
|
||||||
|
|
||||||
XMLBuilder.__init__(self, conn, parsexml, parsexmlnode)
|
XMLBuilder.__init__(self, conn, parsexml, parsexmlnode)
|
||||||
self._XML_ROOT_NAME = self.virtual_device_type
|
|
||||||
|
|
||||||
self.alias = VirtualDeviceAlias(conn, parsexmlnode=parsexmlnode)
|
self.alias = VirtualDeviceAlias(conn, parsexmlnode=parsexmlnode)
|
||||||
self.address = VirtualDeviceAddress(conn, parsexmlnode=parsexmlnode)
|
self.address = VirtualDeviceAddress(conn, parsexmlnode=parsexmlnode)
|
||||||
|
@ -111,9 +111,7 @@ class VirtualDevice(XMLBuilder):
|
||||||
|
|
||||||
|
|
||||||
class VirtualDeviceAlias(XMLBuilder):
|
class VirtualDeviceAlias(XMLBuilder):
|
||||||
_XML_ROOT_NAME = "alias"
|
_XML_ROOT_XPATH = "/domain/devices/device/alias"
|
||||||
_XML_INDENT = 0
|
|
||||||
|
|
||||||
name = XMLProperty(xpath="./alias/@name")
|
name = XMLProperty(xpath="./alias/@name")
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,8 +134,7 @@ class VirtualDeviceAddress(XMLBuilder):
|
||||||
ADDRESS_TYPE_VIRTIO_SERIAL, ADDRESS_TYPE_CCID,
|
ADDRESS_TYPE_VIRTIO_SERIAL, ADDRESS_TYPE_CCID,
|
||||||
ADDRESS_TYPE_SPAPR_VIO]
|
ADDRESS_TYPE_SPAPR_VIO]
|
||||||
|
|
||||||
_XML_ROOT_NAME = "address"
|
_XML_ROOT_XPATH = "/domain/devices/device/address"
|
||||||
_XML_INDENT = 0
|
|
||||||
_XML_PROP_ORDER = ["type", "domain", "bus", "slot", "function"]
|
_XML_PROP_ORDER = ["type", "domain", "bus", "slot", "function"]
|
||||||
|
|
||||||
def set_addrstr(self, addrstr):
|
def set_addrstr(self, addrstr):
|
||||||
|
|
|
@ -53,6 +53,8 @@ def _random_mac(conn):
|
||||||
|
|
||||||
|
|
||||||
class VirtualPort(XMLBuilder):
|
class VirtualPort(XMLBuilder):
|
||||||
|
_XML_ROOT_XPATH = "/domain/devices/interface/virtualport"
|
||||||
|
|
||||||
type = XMLProperty(xpath="./virtualport/@type")
|
type = XMLProperty(xpath="./virtualport/@type")
|
||||||
managerid = XMLProperty(xpath="./virtualport/parameters/@managerid",
|
managerid = XMLProperty(xpath="./virtualport/parameters/@managerid",
|
||||||
is_int=True)
|
is_int=True)
|
||||||
|
|
|
@ -39,15 +39,11 @@ class OSXML(XMLBuilder):
|
||||||
def is_container(self):
|
def is_container(self):
|
||||||
return self.os_type == "exe"
|
return self.os_type == "exe"
|
||||||
|
|
||||||
_dumpxml_xpath = "/domain/os"
|
_XML_ROOT_XPATH = "/domain/os"
|
||||||
_XML_ROOT_NAME = "os"
|
|
||||||
_XML_INDENT = 2
|
|
||||||
_XML_PROP_ORDER = ["arch", "os_type", "loader",
|
_XML_PROP_ORDER = ["arch", "os_type", "loader",
|
||||||
"kernel", "initrd", "kernel_args",
|
"kernel", "initrd", "kernel_args",
|
||||||
"bootorder"]
|
"bootorder"]
|
||||||
|
|
||||||
type = property(lambda s: s.snarf)
|
|
||||||
|
|
||||||
enable_bootmenu = XMLProperty(xpath="./os/bootmenu/@enable", is_yesno=True)
|
enable_bootmenu = XMLProperty(xpath="./os/bootmenu/@enable", is_yesno=True)
|
||||||
bootorder = XMLProperty(xpath="./os/boot/@dev", is_multi=True)
|
bootorder = XMLProperty(xpath="./os/boot/@dev", is_multi=True)
|
||||||
|
|
||||||
|
|
|
@ -574,14 +574,8 @@ class XMLBuilder(object):
|
||||||
# consistent with what the test suite expects.
|
# consistent with what the test suite expects.
|
||||||
_XML_PROP_ORDER = []
|
_XML_PROP_ORDER = []
|
||||||
|
|
||||||
# Root element name of this function, used to populate a default
|
# Absolute xpath this object is rooted at
|
||||||
# _get_xml_config
|
_XML_ROOT_XPATH = None
|
||||||
_XML_ROOT_NAME = None
|
|
||||||
|
|
||||||
# Integer indentation level for generated XML.
|
|
||||||
_XML_INDENT = None
|
|
||||||
|
|
||||||
_dumpxml_xpath = "."
|
|
||||||
|
|
||||||
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
def __init__(self, conn, parsexml=None, parsexmlnode=None):
|
||||||
"""
|
"""
|
||||||
|
@ -595,7 +589,15 @@ class XMLBuilder(object):
|
||||||
"""
|
"""
|
||||||
self.conn = conn
|
self.conn = conn
|
||||||
|
|
||||||
|
xpath = self._XML_ROOT_XPATH
|
||||||
|
if xpath is None or not xpath.startswith("/"):
|
||||||
|
raise RuntimeError("xpath=%s must start with /" % xpath)
|
||||||
|
|
||||||
|
self._xml_root_name = xpath.split("/")[-1]
|
||||||
|
self._xml_indent = (xpath.count("/") - 1) * 2
|
||||||
|
self._xml_dump_xpath = xpath
|
||||||
self._xml_root_xpath = ""
|
self._xml_root_xpath = ""
|
||||||
|
|
||||||
self._xml_node = None
|
self._xml_node = None
|
||||||
self._xml_ctx = None
|
self._xml_ctx = None
|
||||||
self._xml_root_doc = None
|
self._xml_root_doc = None
|
||||||
|
@ -640,7 +642,7 @@ class XMLBuilder(object):
|
||||||
def get_xml_config(self):
|
def get_xml_config(self):
|
||||||
data = self._prepare_get_xml()
|
data = self._prepare_get_xml()
|
||||||
try:
|
try:
|
||||||
return self._do_get_xml_config(self._dumpxml_xpath)
|
return self._do_get_xml_config()
|
||||||
finally:
|
finally:
|
||||||
self._finish_get_xml(data)
|
self._finish_get_xml(data)
|
||||||
|
|
||||||
|
@ -648,7 +650,7 @@ class XMLBuilder(object):
|
||||||
for prop in self.all_xml_props().values():
|
for prop in self.all_xml_props().values():
|
||||||
prop._clear(self)
|
prop._clear(self)
|
||||||
|
|
||||||
def _do_get_xml_config(self, dumpxml_xpath):
|
def _do_get_xml_config(self):
|
||||||
"""
|
"""
|
||||||
Construct and return object xml
|
Construct and return object xml
|
||||||
|
|
||||||
|
@ -656,22 +658,21 @@ class XMLBuilder(object):
|
||||||
@rtype: str
|
@rtype: str
|
||||||
"""
|
"""
|
||||||
if self._xml_ctx:
|
if self._xml_ctx:
|
||||||
node = _get_xpath_node(self._xml_ctx, dumpxml_xpath)
|
node = _get_xpath_node(self._xml_ctx, self._xml_dump_xpath)
|
||||||
if not node:
|
if not node:
|
||||||
ret = ""
|
ret = ""
|
||||||
else:
|
else:
|
||||||
ret = _sanitize_libxml_xml(node.serialize())
|
ret = _sanitize_libxml_xml(node.serialize())
|
||||||
else:
|
else:
|
||||||
xmlstub = self._make_xml_stub(fail=False)
|
xmlstub = self._make_xml_stub()
|
||||||
ret = self._make_xml_stub(fail=True)
|
if xmlstub is None:
|
||||||
if ret is None:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
ret = self._add_parse_bits(ret)
|
ret = self._add_parse_bits(xmlstub)
|
||||||
if ret == xmlstub:
|
if ret == xmlstub:
|
||||||
ret = ""
|
ret = ""
|
||||||
|
|
||||||
if self._XML_ROOT_NAME == "domain" and not ret.endswith("\n"):
|
if ret and self._xml_root_name == "domain" and not ret.endswith("\n"):
|
||||||
ret += "\n"
|
ret += "\n"
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -704,18 +705,8 @@ class XMLBuilder(object):
|
||||||
# Internal XML parsers #
|
# Internal XML parsers #
|
||||||
########################
|
########################
|
||||||
|
|
||||||
def _make_xml_stub(self, fail=True):
|
def _make_xml_stub(self):
|
||||||
if self._XML_ROOT_NAME is None:
|
return _indent("<%s/>" % (self._xml_root_name), self._xml_indent)
|
||||||
if not fail:
|
|
||||||
return None
|
|
||||||
raise RuntimeError("Must specify _XML_ROOT_NAME.")
|
|
||||||
if self._XML_INDENT is None:
|
|
||||||
if not fail:
|
|
||||||
return None
|
|
||||||
raise RuntimeError("Must specify _XML_INDENT.")
|
|
||||||
if self._XML_ROOT_NAME == "":
|
|
||||||
return ""
|
|
||||||
return _indent("<%s/>" % (self._XML_ROOT_NAME), self._XML_INDENT)
|
|
||||||
|
|
||||||
def _add_child(self, parent_xpath, dev):
|
def _add_child(self, parent_xpath, dev):
|
||||||
"""
|
"""
|
||||||
|
@ -742,6 +733,7 @@ class XMLBuilder(object):
|
||||||
doc = libxml2.parseDoc(xml)
|
doc = libxml2.parseDoc(xml)
|
||||||
self._xml_root_doc = _DocCleanupWrapper(doc)
|
self._xml_root_doc = _DocCleanupWrapper(doc)
|
||||||
self._xml_node = doc.children
|
self._xml_node = doc.children
|
||||||
|
self._xml_dump_xpath = "."
|
||||||
|
|
||||||
# This just stores a reference to our root doc wrapper in
|
# This just stores a reference to our root doc wrapper in
|
||||||
# the root node, so when the node goes away it triggers
|
# the root node, so when the node goes away it triggers
|
||||||
|
@ -749,6 +741,7 @@ class XMLBuilder(object):
|
||||||
self._xml_node.virtinst_root_doc = self._xml_root_doc
|
self._xml_node.virtinst_root_doc = self._xml_root_doc
|
||||||
else:
|
else:
|
||||||
self._xml_node = node
|
self._xml_node = node
|
||||||
|
self._xml_dump_xpath = self._XML_ROOT_XPATH
|
||||||
|
|
||||||
self._set_xml_context()
|
self._set_xml_context()
|
||||||
|
|
||||||
|
@ -804,8 +797,7 @@ class XMLBuilder(object):
|
||||||
obj._xml_root_xpath = self._xml_root_xpath
|
obj._xml_root_xpath = self._xml_root_xpath
|
||||||
obj._add_parse_bits(xml=None, node=self._xml_node)
|
obj._add_parse_bits(xml=None, node=self._xml_node)
|
||||||
|
|
||||||
xml = self._do_get_xml_config(".").strip("\n")
|
return _indent(self._do_get_xml_config(), indent)
|
||||||
return _indent(xml, indent)
|
|
||||||
|
|
||||||
def _add_parse_bits(self, xml, node=None):
|
def _add_parse_bits(self, xml, node=None):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue