Drop a lot of usage of utility XML functions
This commit is contained in:
parent
e9b8a289b5
commit
a6d92c7001
|
@ -30,7 +30,6 @@ from gi.repository import Gtk
|
|||
import libvirt
|
||||
|
||||
import virtinst
|
||||
from virtinst import util
|
||||
from virtManager import config
|
||||
|
||||
OPTICAL_DEV_PATH = 0
|
||||
|
@ -84,7 +83,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(pool.get_available())
|
||||
|
||||
elif not conn.is_remote() and os.path.exists(path):
|
||||
vfs = os.statvfs(os.path.dirname(path))
|
||||
|
|
|
@ -76,7 +76,7 @@ DEVICE_GRAPHICS = "24"
|
|||
|
||||
|
||||
|
||||
def register_namespace(ctx):
|
||||
def ovf_register_namespace(ctx):
|
||||
ctx.xpathRegisterNs("ovf", "http://schemas.dmtf.org/ovf/envelope/1")
|
||||
ctx.xpathRegisterNs("ovfenv", "http://schemas.dmtf.org/ovf/environment/1")
|
||||
ctx.xpathRegisterNs("rasd", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData")
|
||||
|
@ -101,6 +101,34 @@ def get_child_content(parent_node, child_name):
|
|||
return 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)
|
||||
"""
|
||||
def _getter(doc, ctx, path):
|
||||
ignore = doc
|
||||
if func:
|
||||
return func(ctx)
|
||||
if not path:
|
||||
raise ValueError("'path' or 'func' is required.")
|
||||
|
||||
ret = ctx.xpathEval(path)
|
||||
if type(ret) is list:
|
||||
if len(ret) >= 1:
|
||||
if return_list:
|
||||
return ret
|
||||
else:
|
||||
return ret[0].content
|
||||
else:
|
||||
ret = None
|
||||
return ret
|
||||
|
||||
return util.xml_parse_wrapper(xml, _getter, path,
|
||||
register_namespace=register_namespace)
|
||||
|
||||
|
||||
def convert_alloc_val(ignore, val):
|
||||
# XXX: This is a hack, but should we really have to decode
|
||||
# allocation units = "bytes * 2^20"?
|
||||
|
@ -238,9 +266,8 @@ class ovf_parser(formats.parser):
|
|||
res = False
|
||||
try:
|
||||
if xml.count("</Envelope>"):
|
||||
res = bool(util.xpath(xml, "/ovf:Envelope",
|
||||
return_list=True,
|
||||
register_namespace=register_namespace))
|
||||
res = bool(_xpath(xml, "/ovf:Envelope", return_list=True,
|
||||
register_namespace=ovf_register_namespace))
|
||||
except Exception, e:
|
||||
logging.debug("Error parsing OVF XML: %s", str(e))
|
||||
|
||||
|
@ -259,7 +286,7 @@ class ovf_parser(formats.parser):
|
|||
logging.debug("Importing OVF XML:\n%s", xml)
|
||||
|
||||
return util.xml_parse_wrapper(xml, ovf_parser._import_file,
|
||||
register_namespace=register_namespace)
|
||||
register_namespace=ovf_register_namespace)
|
||||
|
||||
@staticmethod
|
||||
def _import_file(doc, ctx):
|
||||
|
|
|
@ -88,8 +88,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.xpath(self.original_xml,
|
||||
"/domain/name")
|
||||
self._original_guest = Guest(self.conn,
|
||||
parsexml=self._original_xml).name
|
||||
def get_original_xml(self):
|
||||
return self._original_xml
|
||||
original_xml = property(get_original_xml, set_original_xml,
|
||||
|
|
|
@ -66,6 +66,7 @@ class _FetchObjWrapper(object):
|
|||
def __init__(self, backend):
|
||||
self._backend = backend
|
||||
self._xml = None
|
||||
self._xmlobj = None
|
||||
|
||||
def get_xml(self, refresh_if_nec=True):
|
||||
if self._xml is None or refresh_if_nec:
|
||||
|
|
|
@ -24,7 +24,7 @@ import statvfs
|
|||
|
||||
import libvirt
|
||||
|
||||
from virtinst import StorageVolume
|
||||
from virtinst import StoragePool, StorageVolume
|
||||
from virtinst import util
|
||||
|
||||
|
||||
|
@ -38,12 +38,9 @@ def _check_if_pool_source(conn, path):
|
|||
|
||||
def check_pool(poolname, path):
|
||||
pool = conn.storagePoolLookupByName(poolname)
|
||||
xml = pool.XMLDesc(0)
|
||||
|
||||
for element in ["dir", "device", "adapter"]:
|
||||
xml_path = util.xpath(xml, "/pool/source/%s/@path" % element)
|
||||
if xml_path == path:
|
||||
return pool
|
||||
xmlobj = StoragePool(conn, parsexml=pool.XMLDesc(0))
|
||||
if xmlobj.source_path == path:
|
||||
return pool
|
||||
|
||||
running_list = conn.listStoragePools()
|
||||
inactive_list = conn.listDefinedStoragePools()
|
||||
|
@ -87,7 +84,7 @@ def check_if_path_managed(conn, path):
|
|||
|
||||
vol = lookup_vol_by_path()[0]
|
||||
if not vol:
|
||||
pool = util.lookup_pool_by_path(conn, os.path.dirname(path))
|
||||
pool = StoragePool.lookup_pool_by_path(conn, os.path.dirname(path))
|
||||
|
||||
# Is pool running?
|
||||
if pool and pool.info()[0] != libvirt.VIR_STORAGE_POOL_RUNNING:
|
||||
|
@ -225,9 +222,9 @@ class StorageCreator(_StorageBase):
|
|||
|
||||
def _get_path(self):
|
||||
if self._vol_install and not self._path:
|
||||
self._path = (util.xpath(self._vol_install.pool.XMLDesc(0),
|
||||
"/pool/target/path") + "/" +
|
||||
self._vol_install.name)
|
||||
xmlobj = StoragePool(self._conn,
|
||||
parsexml=self._vol_install.pool.XMLDesc(0))
|
||||
self._path = (xmlobj.target_path + "/" + self._vol_install.name)
|
||||
return self._path
|
||||
path = property(_get_path)
|
||||
|
||||
|
@ -475,12 +472,14 @@ class StorageBackend(_StorageBase):
|
|||
|
||||
def _get_pool_xml(self):
|
||||
if self._pool_xml is None:
|
||||
self._pool_xml = self._pool_object.XMLDesc(0)
|
||||
self._pool_xml = StoragePool(self._conn,
|
||||
parsexml=self._pool_object.XMLDesc(0))
|
||||
return self._pool_xml
|
||||
|
||||
def _get_vol_xml(self):
|
||||
if self._vol_xml is None:
|
||||
self._vol_xml = self._vol_object.XMLDesc(0)
|
||||
self._vol_xml = StorageVolume(self._conn,
|
||||
parsexml=self._vol_object.XMLDesc(0))
|
||||
return self._vol_xml
|
||||
|
||||
|
||||
|
@ -504,9 +503,9 @@ class StorageBackend(_StorageBase):
|
|||
if self._size is None:
|
||||
ret = 0
|
||||
if self._vol_object:
|
||||
ret = util.xpath(self._get_vol_xml(), "/volume/capacity")
|
||||
ret = self._get_vol_xml().capacity
|
||||
elif self._pool_object:
|
||||
ret = util.xpath(self._get_pool_xml(), "/pool/capacity")
|
||||
ret = self._get_pool_xml().capacity
|
||||
elif self._path:
|
||||
ignore, ret = util.stat_disk(self.path)
|
||||
self._size = (float(ret) / 1024.0 / 1024.0 / 1024.0)
|
||||
|
@ -539,14 +538,7 @@ class StorageBackend(_StorageBase):
|
|||
self._dev_type = "file"
|
||||
|
||||
elif self._pool_object:
|
||||
xml = self._get_pool_xml()
|
||||
for source, source_type in [
|
||||
("dir", "dir"),
|
||||
("device", "block"),
|
||||
("adapter", "block")]:
|
||||
if util.xpath(xml, "/pool/source/%s/@dev" % source):
|
||||
self._dev_type = source_type
|
||||
break
|
||||
self._dev_type = self._get_pool_xml().get_vm_disk_type()
|
||||
|
||||
elif self._path:
|
||||
if os.path.isdir(self._path):
|
||||
|
@ -562,9 +554,7 @@ class StorageBackend(_StorageBase):
|
|||
|
||||
def get_driver_type(self):
|
||||
if self._vol_object:
|
||||
fmt = util.xpath(self._get_vol_xml(),
|
||||
"/volume/target/format/@type")
|
||||
return fmt
|
||||
return self._get_vol_xml().format
|
||||
return None
|
||||
|
||||
def is_managed(self):
|
||||
|
|
|
@ -68,7 +68,7 @@ def _sanitize_url(url):
|
|||
|
||||
|
||||
def _build_pool(conn, meter, path):
|
||||
pool = util.lookup_pool_by_path(conn, path)
|
||||
pool = StoragePool.lookup_pool_by_path(conn, path)
|
||||
if pool:
|
||||
logging.debug("Existing pool '%s' found for %s", pool.name(), path)
|
||||
pool.refresh(0)
|
||||
|
@ -106,7 +106,9 @@ def _upload_file(conn, meter, destpool, src):
|
|||
# Build placeholder volume
|
||||
size = os.path.getsize(src)
|
||||
basename = os.path.basename(src)
|
||||
poolpath = util.xpath(destpool.XMLDesc(0), "/pool/target/path")
|
||||
xmlobj = StoragePool(conn, parsexml=destpool.XMLDesc(0))
|
||||
poolpath = xmlobj.target_path
|
||||
|
||||
name = StorageVolume.find_free_name(basename, pool_object=destpool)
|
||||
if name != basename:
|
||||
logging.debug("Generated non-colliding volume name %s", name)
|
||||
|
|
|
@ -204,6 +204,31 @@ class StoragePool(_StorageObject):
|
|||
_("Couldn't create default storage pool '%s': %s") %
|
||||
(path, str(e)))
|
||||
|
||||
@staticmethod
|
||||
def lookup_pool_by_path(conn, path):
|
||||
"""
|
||||
Return the first pool with matching matching target path.
|
||||
return the first we find, active or inactive. This iterates over
|
||||
all pools and dumps their xml, so it is NOT quick.
|
||||
Favor running pools over inactive pools.
|
||||
@returns: virStoragePool object if found, None otherwise
|
||||
"""
|
||||
if not conn.check_conn_support(conn.SUPPORT_CONN_STORAGE):
|
||||
return None
|
||||
|
||||
def check_pool(pool, path):
|
||||
xml = pool.get_xml(refresh_if_nec=False)
|
||||
xml_path = StoragePool(conn, parsexml=xml).target_path
|
||||
if xml_path is not None and os.path.abspath(xml_path) == path:
|
||||
return pool
|
||||
|
||||
for pool in conn.fetch_all_pools():
|
||||
p = check_pool(pool, path)
|
||||
if p:
|
||||
return p.get_backend()
|
||||
return None
|
||||
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
_StorageObject.__init__(self, *args, **kwargs)
|
||||
|
@ -349,6 +374,16 @@ class StoragePool(_StorageObject):
|
|||
StoragePool.TYPE_NETFS, StoragePool.TYPE_LOGICAL,
|
||||
StoragePool.TYPE_DISK]
|
||||
|
||||
def get_vm_disk_type(self):
|
||||
"""
|
||||
Return the /disk/@type value if the pool source is used as
|
||||
VirtualDisk path
|
||||
"""
|
||||
xpath = self._source_path_xpath()
|
||||
if "/dir/" in xpath:
|
||||
return "dir"
|
||||
return "block"
|
||||
|
||||
|
||||
##################
|
||||
# Build routines #
|
||||
|
|
|
@ -299,34 +299,6 @@ def xml_parse_wrapper(xml, parse_func, *args, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def set_xml_path(xml, path, newval):
|
||||
"""
|
||||
Set the passed xml xpath to the new value
|
||||
"""
|
||||
def cb(doc, ctx):
|
||||
ret = ctx.xpathEval(path)
|
||||
if ret is not None:
|
||||
if type(ret) == list:
|
||||
if len(ret) == 1:
|
||||
ret[0].setContent(newval)
|
||||
else:
|
||||
ret.setContent(newval)
|
||||
|
||||
return doc.serialize()
|
||||
return xml_parse_wrapper(xml, cb)
|
||||
|
||||
|
||||
def xml_append(orig, new):
|
||||
"""
|
||||
Little function that helps generate consistent xml
|
||||
"""
|
||||
if not new:
|
||||
return orig
|
||||
if orig:
|
||||
orig += "\n"
|
||||
return orig + new
|
||||
|
||||
|
||||
def generate_uuid(conn):
|
||||
for ignore in range(256):
|
||||
uuid = randomUUID(conn=conn)
|
||||
|
@ -408,58 +380,6 @@ def xml_escape(xml):
|
|||
return xml
|
||||
|
||||
|
||||
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)
|
||||
"""
|
||||
def _getter(doc, ctx, path):
|
||||
ignore = doc
|
||||
if func:
|
||||
return func(ctx)
|
||||
if not path:
|
||||
raise ValueError("'path' or 'func' is required.")
|
||||
|
||||
ret = ctx.xpathEval(path)
|
||||
if type(ret) is list:
|
||||
if len(ret) >= 1:
|
||||
if return_list:
|
||||
return ret
|
||||
else:
|
||||
return ret[0].content
|
||||
else:
|
||||
ret = None
|
||||
return ret
|
||||
|
||||
return xml_parse_wrapper(xml, _getter, path,
|
||||
register_namespace=register_namespace)
|
||||
|
||||
|
||||
def lookup_pool_by_path(conn, path):
|
||||
"""
|
||||
Return the first pool with matching matching target path.
|
||||
return the first we find, active or inactive. This iterates over
|
||||
all pools and dumps their xml, so it is NOT quick.
|
||||
Favor running pools over inactive pools.
|
||||
@returns: virStoragePool object if found, None otherwise
|
||||
"""
|
||||
if not conn.check_conn_support(conn.SUPPORT_CONN_STORAGE):
|
||||
return None
|
||||
|
||||
def check_pool(pool, 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
|
||||
|
||||
for pool in conn.fetch_all_pools():
|
||||
p = check_pool(pool, path)
|
||||
if p:
|
||||
return p.get_backend()
|
||||
return None
|
||||
|
||||
|
||||
def uri_split(uri):
|
||||
"""
|
||||
Parse a libvirt hypervisor uri into it's individual parts
|
||||
|
|
Loading…
Reference in New Issue