guest: Add support for qemu cli passthrough

This is for xml like:

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  ...
  </devices>
  <qemu:commandline>
    <qemu:arg value='-newarg'/>
    <qemu:env name='QEMU_ENV' value='VAL'/>
  </qemu:commandline>
</domain>

Requires some extensions to the xmlbuilder infrastructure
This commit is contained in:
Cole Robinson 2017-03-05 17:12:50 -05:00
parent e7e9369989
commit 22b6becd5d
3 changed files with 83 additions and 3 deletions

View File

@ -54,6 +54,7 @@ from .pm import PM
from .seclabel import Seclabel from .seclabel import Seclabel
from .sysinfo import SYSInfo from .sysinfo import SYSInfo
from .xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty from .xmlbuilder import XMLBuilder, XMLProperty, XMLChildProperty
from .xmlnsqemu import XMLNSQemu
class Guest(XMLBuilder): class Guest(XMLBuilder):
@ -188,6 +189,7 @@ class Guest(XMLBuilder):
validate_cb=lambda s, v: util.validate_uuid(v), validate_cb=lambda s, v: util.validate_uuid(v),
default_cb=_get_default_uuid) default_cb=_get_default_uuid)
id = XMLProperty("./@id", is_int=True) id = XMLProperty("./@id", is_int=True)
type = XMLProperty("./@type", default_cb=lambda s: "xen") type = XMLProperty("./@type", default_cb=lambda s: "xen")
bootloader = XMLProperty("./bootloader") bootloader = XMLProperty("./bootloader")
@ -214,6 +216,8 @@ class Guest(XMLBuilder):
resource = XMLChildProperty(DomainResource, is_single=True) resource = XMLChildProperty(DomainResource, is_single=True)
sysinfo = XMLChildProperty(SYSInfo, is_single=True) sysinfo = XMLChildProperty(SYSInfo, is_single=True)
xmlns_qemu = XMLChildProperty(XMLNSQemu, is_single=True)
############################### ###############################
# Distro detection properties # # Distro detection properties #

View File

@ -42,6 +42,10 @@ _seenprops = []
# top relavtive node in certain cases # top relavtive node in certain cases
_top_node = None _top_node = None
_namespaces = {
"qemu": "http://libvirt.org/schemas/domain/qemu/1.0",
}
class _DocCleanupWrapper(object): class _DocCleanupWrapper(object):
def __init__(self, doc): def __init__(self, doc):
@ -64,6 +68,7 @@ def _make_xml_context(node):
doc = node.doc doc = node.doc
ctx = _CtxCleanupWrapper(doc.xpathNewContext()) ctx = _CtxCleanupWrapper(doc.xpathNewContext())
ctx.setContextNode(node) ctx.setContextNode(node)
ctx.xpathRegisterNs("qemu", _namespaces["qemu"])
return ctx return ctx
@ -98,6 +103,13 @@ def _get_xpath_node(ctx, xpath):
return (node and node[0] or None) 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): def _add_pretty_child(parentnode, newnode):
""" """
Add 'newnode' as a child of 'parentnode', but try to preserve 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 # Remove conditional xpath elements for node creation. We preserved
# them up until this point since it was needed for proper xpath # them up until this point since it was needed for proper xpath
# lookup, but they aren't valid syntax when creating the node # lookup, but they aren't valid syntax when creating the node
if nodename.count("["): if "[" in nodename:
nodename = nodename[:nodename.index("[")] nodename = nodename[:nodename.index("[")]
nsname = None
if ":" in nodename:
nsname, nodename = nodename.split(":")
newnode = libxml2.newNode(nodename) newnode = libxml2.newNode(nodename)
if nsname:
ns = _add_namespace(ctx.contextNode(), nsname)
newnode.setNs(ns)
return _add_pretty_child(parentnode, newnode), parentpath return _add_pretty_child(parentnode, newnode), parentpath
@ -719,7 +738,12 @@ class _XMLState(object):
def make_xml_stub(self): 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): def set_relative_object_xpath(self, xpath):
self._relative_object_xpath = xpath or "" self._relative_object_xpath = xpath or ""
@ -835,7 +859,7 @@ class XMLBuilder(object):
for child_class in xmlprop.child_classes: for child_class in xmlprop.child_classes:
prop_path = xmlprop.get_prop_xpath(self, child_class) 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))) "count(%s)" % self.fix_relative_xpath(prop_path)))
for idx in range(nodecount): for idx in range(nodecount):
idxstr = "[%d]" % (idx + 1) idxstr = "[%d]" % (idx + 1)

52
virtinst/xmlnsqemu.py Normal file
View File

@ -0,0 +1,52 @@
# Copyright 2017 Red Hat, Inc.
# Cole Robinson <crobinso@redhat.com>
#
# 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 <qemu:commandline> 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)