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