mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
Centralize XML helpers in virtinst/util.py
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#
|
||||
|
||||
from virtinst import Interface
|
||||
from virtinst import util
|
||||
|
||||
from virtManager import util
|
||||
from virtManager.libvirtobject import vmmLibvirtObject
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user