diff --git a/virtinst/guest.py b/virtinst/guest.py index f9525a33d..74d33973d 100644 --- a/virtinst/guest.py +++ b/virtinst/guest.py @@ -54,6 +54,7 @@ from .pm import PM from .seclabel import Seclabel from .sysinfo import SYSInfo from .xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty +from .xmlnsqemu import XMLNSQemu class Guest(XMLBuilder): @@ -188,6 +189,7 @@ class Guest(XMLBuilder): validate_cb=lambda s, v: util.validate_uuid(v), default_cb=_get_default_uuid) + id = XMLProperty("./@id", is_int=True) type = XMLProperty("./@type", default_cb=lambda s: "xen") bootloader = XMLProperty("./bootloader") @@ -214,6 +216,8 @@ class Guest(XMLBuilder): resource = XMLChildProperty(DomainResource, is_single=True) sysinfo = XMLChildProperty(SYSInfo, is_single=True) + xmlns_qemu = XMLChildProperty(XMLNSQemu, is_single=True) + ############################### # Distro detection properties # diff --git a/virtinst/xmlbuilder.py b/virtinst/xmlbuilder.py index 97c1e42d3..4c7fe7904 100644 --- a/virtinst/xmlbuilder.py +++ b/virtinst/xmlbuilder.py @@ -42,6 +42,10 @@ _seenprops = [] # top relavtive node in certain cases _top_node = None +_namespaces = { + "qemu": "http://libvirt.org/schemas/domain/qemu/1.0", +} + class _DocCleanupWrapper(object): def __init__(self, doc): @@ -64,6 +68,7 @@ def _make_xml_context(node): doc = node.doc ctx = _CtxCleanupWrapper(doc.xpathNewContext()) ctx.setContextNode(node) + ctx.xpathRegisterNs("qemu", _namespaces["qemu"]) return ctx @@ -98,6 +103,13 @@ def _get_xpath_node(ctx, xpath): return (node and node[0] or None) +def _add_namespace(node, nsname): + for ns in util.listify(node.nsDefs()): + if ns.name == nsname: + return ns + return node.newNs(_namespaces[nsname], nsname) + + def _add_pretty_child(parentnode, newnode): """ Add 'newnode' as a child of 'parentnode', but try to preserve @@ -206,10 +218,17 @@ def _build_xpath_node(ctx, xpath): # Remove conditional xpath elements for node creation. We preserved # them up until this point since it was needed for proper xpath # lookup, but they aren't valid syntax when creating the node - if nodename.count("["): + if "[" in nodename: nodename = nodename[:nodename.index("[")] + nsname = None + if ":" in nodename: + nsname, nodename = nodename.split(":") + newnode = libxml2.newNode(nodename) + if nsname: + ns = _add_namespace(ctx.contextNode(), nsname) + newnode.setNs(ns) return _add_pretty_child(parentnode, newnode), parentpath @@ -719,7 +738,12 @@ class _XMLState(object): def make_xml_stub(self): - return "<%s/>" % self._root_name + ret = "<%s" % self._root_name + if ":" in self._root_name: + ns = self._root_name.split(":")[0] + ret += " xmlns:%s='%s'" % (ns, _namespaces[ns]) + ret += "/>" + return ret def set_relative_object_xpath(self, xpath): self._relative_object_xpath = xpath or "" @@ -835,7 +859,7 @@ class XMLBuilder(object): for child_class in xmlprop.child_classes: prop_path = xmlprop.get_prop_xpath(self, child_class) - nodecount = int(self._xmlstate.xml_node.xpathEval( + nodecount = int(self._xmlstate.xml_ctx.xpathEval( "count(%s)" % self.fix_relative_xpath(prop_path))) for idx in range(nodecount): idxstr = "[%d]" % (idx + 1) diff --git a/virtinst/xmlnsqemu.py b/virtinst/xmlnsqemu.py new file mode 100644 index 000000000..28259bf20 --- /dev/null +++ b/virtinst/xmlnsqemu.py @@ -0,0 +1,52 @@ +# Copyright 2017 Red Hat, Inc. +# Cole Robinson +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. + +from .xmlbuilder import XMLBuilder, XMLChildProperty, XMLProperty + + +class _XMLNSQemuArg(XMLBuilder): + _XML_ROOT_NAME = "qemu:arg" + + value = XMLProperty("./@value") + + +class _XMLNSQemuEnv(XMLBuilder): + _XML_ROOT_NAME = "qemu:env" + + name = XMLProperty("./@name") + value = XMLProperty("./@value") + + +class XMLNSQemu(XMLBuilder): + """ + Class for generating XML + """ + _XML_ROOT_NAME = "qemu:commandline" + + args = XMLChildProperty(_XMLNSQemuArg) + def add_arg(self, value): + arg = _XMLNSQemuArg(conn=self.conn) + arg.value = value + self.add_child(arg) + + envs = XMLChildProperty(_XMLNSQemuEnv) + def add_env(self, name, value): + env = _XMLNSQemuEnv(conn=self.conn) + env.name = name + env.value = value + self.add_child(env)