Centralize XML helpers in virtinst/util.py

This commit is contained in:
Cole Robinson
2013-07-12 10:53:30 -04:00
parent 534e613d40
commit 0d5fe93048
13 changed files with 95 additions and 139 deletions

View File

@@ -84,10 +84,10 @@ def supports_pxe(guest):
try:
xml = nic.conn.networkLookupByName(nic.network).XMLDesc(0)
if util.get_xml_path(xml, "/network/ip/dhcp/bootp/@file"):
if util.xpath(xml, "/network/ip/dhcp/bootp/@file"):
return True
forward = util.get_xml_path(xml, "/network/forward/@mode")
forward = util.xpath(xml, "/network/forward/@mode")
if forward and forward != "nat":
return True
except:

View File

@@ -19,8 +19,8 @@
#
from virtinst import Interface
from virtinst import util
from virtManager import util
from virtManager.libvirtobject import vmmLibvirtObject

View File

@@ -17,9 +17,12 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
#
from virtManager import util
import ipaddr
import libxml2
from virtinst import util
from virtManager.libvirtobject import vmmLibvirtObject

View File

@@ -18,12 +18,13 @@
# MA 02110-1301 USA.
#
import virtinst
# pylint: disable=E0611
from gi.repository import GObject
# pylint: enable=E0611
import virtinst
from virtinst.util import xpath
from virtManager import util
from virtManager.libvirtobject import vmmLibvirtObject
from virtManager.storagevol import vmmStorageVolume
@@ -100,14 +101,14 @@ class vmmStoragePool(vmmLibvirtObject):
return self._backend.autostart()
def get_target_path(self):
return util.xpath(self.get_xml(), "/pool/target/path") or ""
return xpath(self.get_xml(), "/pool/target/path") or ""
def get_allocation(self):
return long(util.xpath(self.get_xml(), "/pool/allocation"))
return long(xpath(self.get_xml(), "/pool/allocation"))
def get_available(self):
return long(util.xpath(self.get_xml(), "/pool/available"))
return long(xpath(self.get_xml(), "/pool/available"))
def get_capacity(self):
return long(util.xpath(self.get_xml(), "/pool/capacity"))
return long(xpath(self.get_xml(), "/pool/capacity"))
def get_pretty_allocation(self):
return util.pretty_bytes(self.get_allocation())
@@ -117,7 +118,7 @@ class vmmStoragePool(vmmLibvirtObject):
return util.pretty_bytes(self.get_capacity())
def get_type(self):
return util.xpath(self.get_xml(), "/pool/@type")
return xpath(self.get_xml(), "/pool/@type")
def get_volumes(self):
self.update_volumes()

View File

@@ -18,6 +18,8 @@
# MA 02110-1301 USA.
#
from virtinst.util import xpath
from virtManager import util
from virtManager.libvirtobject import vmmLibvirtObject
@@ -46,15 +48,15 @@ class vmmStorageVolume(vmmLibvirtObject):
self._backend = None
def get_target_path(self):
return util.xpath(self.get_xml(), "/volume/target/path")
return xpath(self.get_xml(), "/volume/target/path")
def get_format(self):
return util.xpath(self.get_xml(), "/volume/target/format/@type")
return xpath(self.get_xml(), "/volume/target/format/@type")
def get_allocation(self):
return long(util.xpath(self.get_xml(), "/volume/allocation"))
return long(xpath(self.get_xml(), "/volume/allocation"))
def get_capacity(self):
return long(util.xpath(self.get_xml(), "/volume/capacity"))
return long(xpath(self.get_xml(), "/volume/capacity"))
def get_pretty_capacity(self):
return util.pretty_bytes(self.get_capacity())
@@ -62,4 +64,4 @@ class vmmStorageVolume(vmmLibvirtObject):
return util.pretty_bytes(self.get_allocation())
def get_type(self):
return util.xpath(self.get_xml(), "/volume/format/@type")
return xpath(self.get_xml(), "/volume/format/@type")

View File

@@ -62,7 +62,7 @@ def host_disk_space(conn):
# FIXME: make sure not inactive?
# FIXME: use a conn specific function after we send pool-added
pool.refresh()
avail = int(util.xpath(pool.get_xml(), "/pool/available"))
avail = int(virtinst.util.xpath(pool.get_xml(), "/pool/available"))
elif not conn.is_remote() and os.path.exists(path):
vfs = os.statvfs(os.path.dirname(path))

View File

@@ -144,28 +144,6 @@ def get_default_path(conn, name, collidelist=None):
return path
def xml_parse_wrapper(xml, parse_func, *args, **kwargs):
"""
Parse the passed xml string into an xpath context, which is passed
to parse_func, along with any extra arguments.
"""
import libxml2
doc = None
ctx = None
ret = None
try:
doc = libxml2.parseDoc(xml)
ctx = doc.xpathNewContext()
ret = parse_func(doc, ctx, *args, **kwargs)
finally:
if ctx is not None:
ctx.xpathFreeContext()
if doc is not None:
doc.freeDoc()
return ret
def browse_local(parent, dialog_name, conn, start_folder=None,
_type=None, dialog_type=None,
confirm_func=None, browse_reason=None,
@@ -308,8 +286,6 @@ def pretty_bytes(val):
else:
return "%2.2f MB" % (val / (1024.0 * 1024.0))
xpath = virtinst.util.get_xml_path
def chkbox_helper(src, getcb, setcb, text1, text2=None,
alwaysrecord=False,

View File

@@ -18,14 +18,15 @@
# MA 02110-1301 USA.
#
import libxml2
import logging
from virtinst import util
import virtconv.formats as formats
import virtconv.vmcfg as vmcfg
import virtconv.diskcfg as diskcfg
import virtconv.netdevcfg as netdevcfg
import logging
# Mapping of ResourceType value to device type
# http://konkretcmpi.org/cim218/CIM_ResourceAllocationSettingData.html
@@ -93,7 +94,6 @@ def node_list(node):
def get_child_content(parent_node, child_name):
for node in node_list(parent_node):
if node.name == child_name:
return node.content
@@ -121,53 +121,6 @@ def convert_alloc_val(ignore, val):
return int(val)
def _xml_wrapper(xml, func):
doc = None
ctx = None
result = None
try:
doc = libxml2.parseDoc(xml)
ctx = doc.xpathNewContext()
register_namespace(ctx)
result = func(ctx)
finally:
if doc:
doc.freeDoc()
if ctx:
ctx.xpathFreeContext()
return result
def get_xml_path(xml, path=None, func=None):
"""
Return the content from the passed xml xpath, or return the result
of a passed function (receives xpathContext as its only arg)
"""
def _get_xml_path(ctx):
result = None
if path:
ret = ctx.xpathEval(path)
if ret is not None:
if type(ret) == list:
if len(ret) >= 1:
# result = ret[0].content
result = ret
else:
result = ret
elif func:
result = func(ctx)
else:
raise ValueError(_("'path' or 'func' is required."))
return result
return _xml_wrapper(xml, _get_xml_path)
def _parse_hw_section(vm, nodes, file_refs, disk_section):
vm.nr_vcpus = 0
disk_buses = {}
@@ -285,7 +238,9 @@ class ovf_parser(formats.parser):
res = False
try:
if xml.count("</Envelope>"):
res = bool(get_xml_path(xml, "/ovf:Envelope"))
res = bool(util.xpath(xml, "/ovf:Envelope",
return_list=True,
register_namespace=register_namespace))
except Exception, e:
logging.debug("Error parsing OVF XML: %s", str(e))
@@ -303,10 +258,12 @@ class ovf_parser(formats.parser):
infile.close()
logging.debug("Importing OVF XML:\n%s", xml)
return _xml_wrapper(xml, ovf_parser._import_file)
return util.xml_parse_wrapper(xml, ovf_parser._import_file,
register_namespace=register_namespace)
@staticmethod
def _import_file(ctx):
def _import_file(doc, ctx):
ignore = doc
def xpath_str(path):
ret = ctx.xpathEval(path)
result = None

View File

@@ -90,8 +90,8 @@ class Cloner(object):
if type(val) is not str:
raise ValueError(_("Original xml must be a string."))
self._original_xml = val
self._original_guest = util.get_xml_path(self.original_xml,
"/domain/name")
self._original_guest = util.xpath(self.original_xml,
"/domain/name")
def get_original_xml(self):
return self._original_xml
original_xml = property(get_original_xml, set_original_xml,

View File

@@ -101,7 +101,7 @@ def _upload_file(conn, meter, destpool, src):
# Build placeholder volume
size = os.path.getsize(src)
basename = os.path.basename(src)
poolpath = util.get_xml_path(destpool.XMLDesc(0), "/pool/target/path")
poolpath = util.xpath(destpool.XMLDesc(0), "/pool/target/path")
name = Storage.StorageVolume.find_free_name(basename,
pool_object=destpool)
if name != basename:

View File

@@ -1005,7 +1005,8 @@ class StorageVolume(StorageObject):
pool_object = StorageVolume.lookup_pool_by_name(pool_object=pool_object,
pool_name=pool_name,
conn=conn)
return StoragePool.get_volume_for_pool(util.get_xml_path(pool_object.XMLDesc(0), "/pool/@type"))
return StoragePool.get_volume_for_pool(util.xpath(
pool_object.XMLDesc(0), "/pool/@type"))
get_volume_for_pool = staticmethod(get_volume_for_pool)
def find_free_name(name, pool_object=None, pool_name=None, conn=None,
@@ -1407,9 +1408,9 @@ class CloneVolume(StorageVolume):
# Populate some basic info
xml = input_vol.XMLDesc(0)
typ = input_vol.info()[0]
cap = int(util.get_xml_path(xml, "/volume/capacity"))
alc = int(util.get_xml_path(xml, "/volume/allocation"))
fmt = util.get_xml_path(xml, "/volume/target/format/@type")
cap = int(util.xpath(xml, "/volume/capacity"))
alc = int(util.xpath(xml, "/volume/allocation"))
fmt = util.xpath(xml, "/volume/target/format/@type")
StorageVolume.__init__(self, conn, name=name, pool=pool,
pool_name=pool.name(),

View File

@@ -114,8 +114,7 @@ def _check_if_pool_source(conn, path):
xml = pool.XMLDesc(0)
for element in ["dir", "device", "adapter"]:
xml_path = util.get_xml_path(xml,
"/pool/source/%s/@path" % element)
xml_path = util.xpath(xml, "/pool/source/%s/@path" % element)
if xml_path == path:
return pool
@@ -626,8 +625,8 @@ class VirtualDisk(VirtualDevice):
if self.vol_object:
retpath = self.vol_object.path()
elif self.vol_install:
retpath = (util.get_xml_path(self.vol_install.pool.XMLDesc(0),
"/pool/target/path") + "/" +
retpath = (util.xpath(self.vol_install.pool.XMLDesc(0),
"/pool/target/path") + "/" +
self.vol_install.name)
return retpath
@@ -1004,15 +1003,15 @@ class VirtualDisk(VirtualDevice):
return
if self.vol_object:
newsize = util.get_xml_path(self.vol_object.XMLDesc(0),
"/volume/capacity")
newsize = util.xpath(self.vol_object.XMLDesc(0),
"/volume/capacity")
try:
newsize = float(newsize) / 1024.0 / 1024.0 / 1024.0
except:
newsize = 0
elif self._pool_object:
newsize = util.get_xml_path(self.vol_object.XMLDesc(0),
"/pool/capacity")
newsize = util.xpath(self.vol_object.XMLDesc(0),
"/pool/capacity")
try:
newsize = float(newsize) / 1024.0 / 1024.0 / 1024.0
except:
@@ -1051,7 +1050,7 @@ class VirtualDisk(VirtualDevice):
for source, source_type in [("dir", self.TYPE_DIR),
("device", self.TYPE_BLOCK),
("adapter", self.TYPE_BLOCK)]:
if util.get_xml_path(xml, "/pool/source/%s/@dev" % source):
if util.xpath(xml, "/pool/source/%s/@dev" % source):
dtype = source_type
break
@@ -1090,7 +1089,7 @@ class VirtualDisk(VirtualDevice):
manual_format=True)
elif self.vol_object:
fmt = util.get_xml_path(self.vol_object.XMLDesc(0),
fmt = util.xpath(self.vol_object.XMLDesc(0),
"/volume/target/format/@type")
if drvname == self.DRIVER_QEMU:
drvtype = _qemu_sanitize_drvtype(self.type, fmt)

View File

@@ -306,6 +306,30 @@ def parse_node_helper(xml, root_name, callback, exec_class=ValueError):
return ret
def xml_parse_wrapper(xml, parse_func, *args, **kwargs):
"""
Parse the passed xml string into an xpath context, which is passed
to parse_func, along with any extra arguments.
"""
doc = None
ctx = None
ret = None
register_namespace = kwargs.pop("register_namespace", None)
try:
doc = libxml2.parseDoc(xml)
ctx = doc.xpathNewContext()
if register_namespace:
register_namespace(ctx)
ret = parse_func(doc, ctx, *args, **kwargs)
finally:
if ctx is not None:
ctx.xpathFreeContext()
if doc is not None:
doc.freeDoc()
return ret
def generate_uuid(conn):
for ignore in range(256):
uuid = randomUUID(conn=conn)
@@ -387,39 +411,32 @@ def xml_escape(xml):
return xml
def get_xml_path(xml, path=None, func=None):
def xpath(xml, path=None, func=None, return_list=False,
register_namespace=None):
"""
Return the content from the passed xml xpath, or return the result
of a passed function (receives xpathContext as its only arg)
"""
doc = None
ctx = None
result = None
def _getter(doc, ctx, path):
ignore = doc
if func:
return func(ctx)
if not path:
raise ValueError("'path' or 'func' is required.")
try:
doc = libxml2.parseDoc(xml)
ctx = doc.xpathNewContext()
if path:
ret = ctx.xpathEval(path)
if ret is not None:
if type(ret) == list:
if len(ret) >= 1:
result = ret[0].content
ret = ctx.xpathEval(path)
if type(ret) is list:
if len(ret) >= 1:
if return_list:
return ret
else:
result = ret
return ret[0].content
else:
ret = None
return ret
elif func:
result = func(ctx)
else:
raise ValueError(_("'path' or 'func' is required."))
finally:
if doc:
doc.freeDoc()
if ctx:
ctx.xpathFreeContext()
return result
return xml_parse_wrapper(xml, _getter, path,
register_namespace=register_namespace)
def lookup_pool_by_path(conn, path):
@@ -434,8 +451,8 @@ def lookup_pool_by_path(conn, path):
return None
def check_pool(pool, path):
xml_path = get_xml_path(pool.get_xml(refresh_if_nec=False),
"/pool/target/path")
xml_path = xpath(pool.get_xml(refresh_if_nec=False),
"/pool/target/path")
if xml_path is not None and os.path.abspath(xml_path) == path:
return pool