connection: Handle nodedev polling too

And cleanup up a bunch of nodedev functions as a result
This commit is contained in:
Cole Robinson 2014-09-20 11:30:24 -04:00
parent 8cd4958a19
commit dd67c48233
6 changed files with 82 additions and 63 deletions

View File

@ -79,11 +79,15 @@ def openconn(uri):
_conn_cache[uri]["vms"] = conn._fetch_all_guests_cached()
_conn_cache[uri]["pools"] = conn._fetch_all_pools_cached()
_conn_cache[uri]["vols"] = conn._fetch_all_vols_cached()
_conn_cache[uri]["nodedevs"] = conn._fetch_all_nodedevs_cached()
cache = _conn_cache[uri].copy()
def cb_fetch_all_guests():
return cache["vms"]
def cb_fetch_all_nodedevs():
return cache["nodedevs"]
def cb_fetch_all_pools():
if "pools" not in cache:
cache["pools"] = conn._fetch_all_pools_cached()
@ -102,6 +106,7 @@ def openconn(uri):
conn.cb_fetch_all_guests = cb_fetch_all_guests
conn.cb_fetch_all_pools = cb_fetch_all_pools
conn.cb_fetch_all_vols = cb_fetch_all_vols
conn.cb_fetch_all_nodedevs = cb_fetch_all_nodedevs
conn.cb_clear_cache = cb_clear_cache
return conn

View File

@ -164,6 +164,9 @@ class vmmConnection(vmmGObject):
self._backend.cb_fetch_all_pools = (
lambda: [obj.get_xmlobj(refresh_if_nec=False)
for obj in self._pools.values()])
self._backend.cb_fetch_all_nodedevs = (
lambda: [obj.get_xmlobj(refresh_if_nec=False)
for obj in self._nodedevs.values()])
def fetch_all_vols():
ret = []

View File

@ -2057,7 +2057,7 @@ class ParserHostdev(VirtCLIParser):
def set_name_cb(opts, inst, cliname, val):
ignore = opts
ignore = cliname
val = NodeDevice.lookupNodeName(inst.conn, val)
val = NodeDevice.lookupNodedevFromString(inst.conn, val)
inst.set_from_nodedev(val)
self.set_param(None, "name", setter_cb=set_name_cb)

View File

@ -28,6 +28,7 @@ from . import util
from . import capabilities as CapabilitiesParser
from .cli import VirtOptionString
from .guest import Guest
from .nodedev import NodeDevice
from .storage import StoragePool, StorageVolume
_virtinst_uri_magic = "__virtinst_test__"
@ -96,6 +97,7 @@ class VirtualConnection(object):
self.cb_fetch_all_guests = None
self.cb_fetch_all_pools = None
self.cb_fetch_all_vols = None
self.cb_fetch_all_nodedevs = None
self.cb_clear_cache = None
@ -162,9 +164,27 @@ class VirtualConnection(object):
self._uri = self._libvirtconn.getURI()
self._urisplits = util.uri_split(self._uri)
def set_keep_alive(self, interval, count):
if hasattr(self._libvirtconn, "setKeepAlive"):
self._libvirtconn.setKeepAlive(interval, count)
####################
# Polling routines #
####################
_FETCH_KEY_GUESTS = "vms"
_FETCH_KEY_POOLS = "pools"
_FETCH_KEY_VOLS = "vols"
_FETCH_KEY_NODEDEVS = "nodedevs"
def clear_cache(self, pools=False):
if self.cb_clear_cache:
self.cb_clear_cache(pools=pools) # pylint: disable=not-callable
return
if pools:
self._fetch_cache.pop(self._FETCH_KEY_POOLS, None)
def _fetch_all_guests_cached(self):
key = self._FETCH_KEY_GUESTS
@ -200,10 +220,6 @@ class VirtualConnection(object):
self._fetch_cache[key] = ret
return ret
def set_keep_alive(self, interval, count):
if hasattr(self._libvirtconn, "setKeepAlive"):
self._libvirtconn.setKeepAlive(interval, count)
def fetch_all_pools(self):
"""
Returns a list of StoragePool objects
@ -242,13 +258,26 @@ class VirtualConnection(object):
return self.cb_fetch_all_vols() # pylint: disable=not-callable
return self._fetch_all_vols_cached()
def clear_cache(self, pools=False):
if self.cb_clear_cache:
self.cb_clear_cache(pools=pools) # pylint: disable=not-callable
return
def _fetch_all_nodedevs_cached(self):
key = self._FETCH_KEY_NODEDEVS
if key in self._fetch_cache:
return self._fetch_cache[key]
if pools:
self._fetch_cache.pop(self._FETCH_KEY_POOLS, None)
ignore, ignore, ret = pollhelpers.fetch_nodedevs(
self, {}, lambda obj, ignore: obj)
ret = [NodeDevice.parse(weakref.ref(self), obj.XMLDesc(0))
for obj in ret.values()]
if self.cache_object_fetch:
self._fetch_cache[key] = ret
return ret
def fetch_all_nodedevs(self):
"""
Returns a list of NodeDevice() objects
"""
if self.cb_fetch_all_nodedevs:
return self.cb_fetch_all_nodedevs() # pylint: disable=not-callable
return self._fetch_all_nodedevs_cached()
#########################

View File

@ -53,8 +53,13 @@ class VirtualHostDevice(VirtualDevice):
self.device = nodedev.device
elif nodedev.device_type == nodedev.CAPABILITY_TYPE_NET:
parentnode = nodedev.lookupNodeName(self.conn, nodedev.parent)
self.set_from_nodedev(parentnode, use_full_usb=use_full_usb)
founddev = None
for checkdev in self.conn.fetch_all_nodedevs():
if checkdev.name == nodedev.parent:
founddev = checkdev
break
self.set_from_nodedev(founddev, use_full_usb=use_full_usb)
else:
raise ValueError("Unknown node device type %s" % nodedev)

View File

@ -19,8 +19,6 @@
import logging
import libvirt
from .xmlbuilder import XMLBuilder
from .xmlbuilder import XMLProperty as _XMLProperty
@ -29,18 +27,6 @@ class XMLProperty(_XMLProperty):
_track = False
def _lookupNodeName(conn, name):
try:
nodedev = conn.nodeDeviceLookupByName(name)
except libvirt.libvirtError, e:
raise libvirt.libvirtError(
_("Did not find node device '%s': %s" %
(name, str(e))))
xml = nodedev.XMLDesc(0)
return NodeDevice.parse(conn, xml)
def _intify(val, do_hex=False):
try:
if do_hex:
@ -73,7 +59,7 @@ class NodeDevice(XMLBuilder):
HOSTDEV_ADDR_TYPE_USB_VENPRO) = range(1, 5)
@staticmethod
def lookupNodeName(conn, name):
def lookupNodedevFromString(conn, idstring):
"""
Convert the passed libvirt node device name to a NodeDevice
instance, with proper error reporting. If the name is name is not
@ -81,8 +67,11 @@ class NodeDevice(XMLBuilder):
devAddressToNodeDev
@param conn: libvirt.virConnect instance to perform the lookup on
@param name: libvirt node device name to lookup, or address for
_devAddressToNodedev
@param idstring: libvirt node device name to lookup, or address
of the form:
- bus.addr (ex. 001.003 for a usb device)
- vendor:product (ex. 0x1234:0x5678 for a usb device
- (domain:)bus:slot.func (ex. 00:10.0 for a pci device)
@rtype: L{NodeDevice} instance
"""
@ -90,15 +79,19 @@ class NodeDevice(XMLBuilder):
raise ValueError(_("Connection does not support host device "
"enumeration."))
try:
return _lookupNodeName(conn, name)
except libvirt.libvirtError, e:
try:
_isAddressStr(name)
except:
raise e
# First try and see if this is a libvirt nodedev name
for nodedev in conn.fetch_all_nodedevs():
if nodedev.name == idstring:
return nodedev
try:
return _AddressStringToNodedev(conn, idstring)
except:
logging.debug("Error looking up nodedev from idstring=%s",
idstring, exc_info=True)
raise RuntimeError(_("Did not find node device matching '%s'" %
idstring))
return _devAddressToNodedev(conn, name)
@staticmethod
def parse(conn, xml):
@ -346,7 +339,7 @@ class SCSIBus(NodeDevice):
wwpn = XMLProperty("./capability/capability[@type='fc_host']/wwpn")
def _isAddressStr(addrstr):
def _isAddressString(addrstr):
cmp_func = None
addr_type = None
@ -401,40 +394,24 @@ def _isAddressStr(addrstr):
else:
raise RuntimeError("Unknown address type")
except:
logging.exception("Error parsing node device string.")
logging.debug("Error parsing node device string.", exc_info=True)
raise
return cmp_func, devtype, addr_type
def _devAddressToNodedev(conn, addrstr):
"""
Look up the passed host device address string as a libvirt node device,
parse its xml, and return a NodeDevice instance.
@param conn: libvirt.virConnect instance to perform the lookup on
@param addrstr: host device string to parse and lookup
- bus.addr (ex. 001.003 for a usb device)
- vendor:product (ex. 0x1234:0x5678 for a usb device
- (domain:)bus:slot.func (ex. 00:10.0 for a pci device)
@param addrstr: C{str}
"""
try:
ret = _isAddressStr(addrstr)
except:
raise ValueError(_("Could not determine format of '%s'") % addrstr)
cmp_func, devtype, addr_type = ret
def _AddressStringToNodedev(conn, addrstr):
cmp_func, devtype, addr_type = _isAddressString(addrstr)
# Iterate over node devices and compare
count = 0
nodedev = None
nodenames = conn.listDevices(devtype, 0)
for name in nodenames:
tmpnode = _lookupNodeName(conn, name)
if cmp_func(tmpnode):
nodedev = tmpnode
for xmlobj in conn.fetch_all_nodedevs():
if xmlobj.device_type != devtype:
continue
if cmp_func(xmlobj):
nodedev = xmlobj
count += 1
if count == 1: