Merge "Return a meaningful value or raise an excpetion for libvirt"
This commit is contained in:
commit
92ab07fc13
@ -27,7 +27,7 @@ import ceilometer
|
||||
from ceilometer.compute import pollsters
|
||||
from ceilometer.compute.pollsters import util
|
||||
from ceilometer.compute.virt import inspector as virt_inspector
|
||||
from ceilometer.i18n import _
|
||||
from ceilometer.i18n import _, _LW
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer import sample
|
||||
|
||||
@ -119,6 +119,11 @@ class _Base(pollsters.BaseComputePollster):
|
||||
except virt_inspector.InstanceNotFoundException as err:
|
||||
# Instance was deleted while getting samples. Ignore it.
|
||||
LOG.debug(_('Exception while getting samples %s'), err)
|
||||
except virt_inspector.InstanceShutOffException as e:
|
||||
LOG.warn(_LW('Instance %(instance_id)s was shut off while '
|
||||
'getting samples of %(pollster)s: %(exc)s'),
|
||||
{'instance_id': instance.id,
|
||||
'pollster': self.__class__.__name__, 'exc': e})
|
||||
except ceilometer.NotImplementedError:
|
||||
# Selected inspector does not implement this pollster.
|
||||
LOG.debug(_('%(inspector)s does not provide data for '
|
||||
|
@ -16,7 +16,7 @@ import ceilometer
|
||||
from ceilometer.compute import pollsters
|
||||
from ceilometer.compute.pollsters import util
|
||||
from ceilometer.compute.virt import inspector as virt_inspector
|
||||
from ceilometer.i18n import _
|
||||
from ceilometer.i18n import _, _LW
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer import sample
|
||||
|
||||
@ -45,6 +45,16 @@ class MemoryUsagePollster(pollsters.BaseComputePollster):
|
||||
except virt_inspector.InstanceNotFoundException as err:
|
||||
# Instance was deleted while getting samples. Ignore it.
|
||||
LOG.debug(_('Exception while getting samples %s'), err)
|
||||
except virt_inspector.InstanceShutOffException as e:
|
||||
LOG.warn(_LW('Instance %(instance_id)s was shut off while '
|
||||
'getting samples of %(pollster)s: %(exc)s'),
|
||||
{'instance_id': instance.id,
|
||||
'pollster': self.__class__.__name__, 'exc': e})
|
||||
except virt_inspector.NoDataException as e:
|
||||
LOG.warn(_LW('Cannot inspect data of %(pollster)s for '
|
||||
'%(instance_id)s, non-fatal reason: %(exc)s'),
|
||||
{'pollster': self.__class__.__name__,
|
||||
'instance_id': instance.id, 'exc': e})
|
||||
except ceilometer.NotImplementedError:
|
||||
# Selected inspector does not implement this pollster.
|
||||
LOG.debug(_('Obtaining Memory Usage is not implemented for %s'
|
||||
|
@ -26,7 +26,7 @@ from ceilometer.compute import pollsters
|
||||
from ceilometer.compute.pollsters import util
|
||||
from ceilometer.compute import util as compute_util
|
||||
from ceilometer.compute.virt import inspector as virt_inspector
|
||||
from ceilometer.i18n import _
|
||||
from ceilometer.i18n import _, _LW
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer import sample
|
||||
|
||||
@ -107,6 +107,11 @@ class _Base(pollsters.BaseComputePollster):
|
||||
except virt_inspector.InstanceNotFoundException as err:
|
||||
# Instance was deleted while getting samples. Ignore it.
|
||||
LOG.debug(_('Exception while getting samples %s'), err)
|
||||
except virt_inspector.InstanceShutOffException as e:
|
||||
LOG.warn(_LW('Instance %(instance_id)s was shut off while '
|
||||
'getting samples of %(pollster)s: %(exc)s'),
|
||||
{'instance_id': instance.id,
|
||||
'pollster': self.__class__.__name__, 'exc': e})
|
||||
except ceilometer.NotImplementedError:
|
||||
# Selected inspector does not implement this pollster.
|
||||
LOG.debug(_('%(inspector)s does not provide data for '
|
||||
|
@ -143,6 +143,14 @@ class InstanceNotFoundException(InspectorException):
|
||||
pass
|
||||
|
||||
|
||||
class InstanceShutOffException(InspectorException):
|
||||
pass
|
||||
|
||||
|
||||
class NoDataException(InspectorException):
|
||||
pass
|
||||
|
||||
|
||||
# Main virt inspector abstraction layering over the hypervisor API.
|
||||
#
|
||||
class Inspector(object):
|
||||
|
@ -53,7 +53,7 @@ def retry_on_disconnect(function):
|
||||
if (e.get_error_code() == libvirt.VIR_ERR_SYSTEM_ERROR and
|
||||
e.get_error_domain() in (libvirt.VIR_FROM_REMOTE,
|
||||
libvirt.VIR_FROM_RPC)):
|
||||
LOG.debug('Connection to libvirt broken')
|
||||
LOG.debug(_('Connection to libvirt broken'))
|
||||
self.connection = None
|
||||
return function(self, *args, **kwargs)
|
||||
else:
|
||||
@ -78,7 +78,7 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
global libvirt
|
||||
if libvirt is None:
|
||||
libvirt = __import__('libvirt')
|
||||
LOG.debug('Connecting to libvirt: %s', self.uri)
|
||||
LOG.debug(_('Connecting to libvirt: %s'), self.uri)
|
||||
self.connection = libvirt.openReadOnly(self.uri)
|
||||
|
||||
return self.connection
|
||||
@ -96,13 +96,13 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
ex.get_error_domain() in (libvirt.VIR_FROM_REMOTE,
|
||||
libvirt.VIR_FROM_RPC)):
|
||||
raise
|
||||
msg = ("Error from libvirt while looking up instance Name "
|
||||
"%(instance_name)s UUID %(instance_uuid)s: "
|
||||
"[Error Code %(error_code)s] "
|
||||
"%(ex)s" % {'instance_name': instance_name,
|
||||
'instance_uuid': instance.id,
|
||||
'error_code': error_code,
|
||||
'ex': ex})
|
||||
msg = _("Error from libvirt while looking up instance "
|
||||
"<name=%(name)s, id=%(id)>: "
|
||||
"[Error Code %(error_code)s] "
|
||||
"%(ex)s") % {'name': instance_name,
|
||||
'id': instance.id,
|
||||
'error_code': error_code,
|
||||
'ex': ex}
|
||||
raise virt_inspector.InstanceNotFoundException(msg)
|
||||
|
||||
def inspect_cpus(self, instance):
|
||||
@ -110,17 +110,23 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
dom_info = domain.info()
|
||||
return virt_inspector.CPUStats(number=dom_info[3], time=dom_info[4])
|
||||
|
||||
def inspect_vnics(self, instance):
|
||||
def _get_domain_not_shut_off_or_raise(self, instance):
|
||||
instance_name = util.instance_name(instance)
|
||||
domain = self._lookup_by_uuid(instance)
|
||||
|
||||
state = domain.info()[0]
|
||||
if state == libvirt.VIR_DOMAIN_SHUTOFF:
|
||||
LOG.warn(_('Failed to inspect vnics of instance Name '
|
||||
'%(instance_name)s UUID %(instance_uuid)s, '
|
||||
'domain is in state of SHUTOFF'),
|
||||
{'instance_name': instance_name,
|
||||
'instance_uuid': instance.id})
|
||||
return
|
||||
msg = _('Failed to inspect data of instance '
|
||||
'<name=%(name)s, id=%(id)s>, '
|
||||
'domain state is SHUTOFF.') % {
|
||||
'name': instance_name, 'id': instance.id}
|
||||
raise virt_inspector.InstanceShutOffException(msg)
|
||||
|
||||
return domain
|
||||
|
||||
def inspect_vnics(self, instance):
|
||||
domain = self._get_domain_not_shut_off_or_raise(instance)
|
||||
|
||||
tree = etree.fromstring(domain.XMLDesc(0))
|
||||
for iface in tree.findall('devices/interface'):
|
||||
target = iface.find('target')
|
||||
@ -149,16 +155,8 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
yield (interface, stats)
|
||||
|
||||
def inspect_disks(self, instance):
|
||||
instance_name = util.instance_name(instance)
|
||||
domain = self._lookup_by_uuid(instance)
|
||||
state = domain.info()[0]
|
||||
if state == libvirt.VIR_DOMAIN_SHUTOFF:
|
||||
LOG.warn(_('Failed to inspect disks of instance Name '
|
||||
'%(instance_name)s UUID %(instance_uuid)s, '
|
||||
'domain is in state of SHUTOFF'),
|
||||
{'instance_name': instance_name,
|
||||
'instance_uuid': instance.id})
|
||||
return
|
||||
domain = self._get_domain_not_shut_off_or_raise(instance)
|
||||
|
||||
tree = etree.fromstring(domain.XMLDesc(0))
|
||||
for device in filter(
|
||||
bool,
|
||||
@ -175,15 +173,7 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
|
||||
def inspect_memory_usage(self, instance, duration=None):
|
||||
instance_name = util.instance_name(instance)
|
||||
domain = self._lookup_by_uuid(instance)
|
||||
state = domain.info()[0]
|
||||
if state == libvirt.VIR_DOMAIN_SHUTOFF:
|
||||
LOG.warn(_('Failed to inspect memory usage of instance Name '
|
||||
'%(instance_name)s UUID %(instance_uuid)s, '
|
||||
'domain is in state of SHUTOFF'),
|
||||
{'instance_name': instance_name,
|
||||
'instance_uuid': instance.id})
|
||||
return
|
||||
domain = self._get_domain_not_shut_off_or_raise(instance)
|
||||
|
||||
try:
|
||||
memory_stats = domain.memoryStats()
|
||||
@ -196,15 +186,15 @@ class LibvirtInspector(virt_inspector.Inspector):
|
||||
memory_used = memory_used / units.Ki
|
||||
return virt_inspector.MemoryUsageStats(usage=memory_used)
|
||||
else:
|
||||
LOG.warn(_('Failed to inspect memory usage of instance Name '
|
||||
'%(instance_name)s UUID %(instance_uuid)s, '
|
||||
'can not get info from libvirt'),
|
||||
{'instance_name': instance_name,
|
||||
'instance_uuid': instance.id})
|
||||
# memoryStats might launch an exception if the method
|
||||
# is not supported by the underlying hypervisor being
|
||||
# used by libvirt
|
||||
msg = _('Failed to inspect memory usage of instance '
|
||||
'<name=%(name)s, id=%(id)s>, '
|
||||
'can not get info from libvirt.') % {
|
||||
'name': instance_name, 'id': instance.id}
|
||||
raise virt_inspector.NoDataException(msg)
|
||||
# memoryStats might launch an exception if the method is not supported
|
||||
# by the underlying hypervisor being used by libvirt.
|
||||
except libvirt.libvirtError as e:
|
||||
LOG.warn(_('Failed to inspect memory usage of %(instance_uuid)s, '
|
||||
'can not get info from libvirt: %(error)s'),
|
||||
{'instance_uuid': instance.id, 'error': e})
|
||||
msg = _('Failed to inspect memory usage of %(instance_uuid)s, '
|
||||
'can not get info from libvirt: %(error)s') % {
|
||||
'instance_uuid': instance.id, 'error': e}
|
||||
raise virt_inspector.NoDataException(msg)
|
||||
|
@ -31,24 +31,36 @@ class TestMemoryPollster(base.TestPollsterBase):
|
||||
next_value = iter((
|
||||
virt_inspector.MemoryUsageStats(usage=1.0),
|
||||
virt_inspector.MemoryUsageStats(usage=2.0),
|
||||
virt_inspector.NoDataException(),
|
||||
virt_inspector.InstanceShutOffException(),
|
||||
))
|
||||
|
||||
def inspect_memory_usage(instance, duration):
|
||||
return next(next_value)
|
||||
value = next(next_value)
|
||||
if isinstance(value, virt_inspector.MemoryUsageStats):
|
||||
return value
|
||||
else:
|
||||
raise value
|
||||
|
||||
(self.inspector.
|
||||
inspect_memory_usage) = mock.Mock(side_effect=inspect_memory_usage)
|
||||
self.inspector.inspect_memory_usage = mock.Mock(
|
||||
side_effect=inspect_memory_usage)
|
||||
|
||||
mgr = manager.AgentManager()
|
||||
pollster = memory.MemoryUsagePollster()
|
||||
|
||||
def _verify_memory_metering(expected_memory_mb):
|
||||
cache = {}
|
||||
samples = list(pollster.get_samples(mgr, cache, [self.instance]))
|
||||
self.assertEqual(1, len(samples))
|
||||
self.assertEqual(set(['memory.usage']),
|
||||
set([s.name for s in samples]))
|
||||
self.assertEqual(expected_memory_mb, samples[0].volume)
|
||||
@mock.patch('ceilometer.compute.pollsters.memory.LOG')
|
||||
def _verify_memory_metering(expected_count, expected_memory_mb, mylog):
|
||||
samples = list(pollster.get_samples(mgr, {}, [self.instance]))
|
||||
self.assertEqual(expected_count, len(samples))
|
||||
if expected_count > 0:
|
||||
self.assertEqual(set(['memory.usage']),
|
||||
set([s.name for s in samples]))
|
||||
self.assertEqual(expected_memory_mb, samples[0].volume)
|
||||
else:
|
||||
self.assertEqual(1, mylog.warn.call_count)
|
||||
self.assertEqual(0, mylog.exception.call_count)
|
||||
|
||||
_verify_memory_metering(1.0)
|
||||
_verify_memory_metering(2.0)
|
||||
_verify_memory_metering(1, 1.0)
|
||||
_verify_memory_metering(1, 2.0)
|
||||
_verify_memory_metering(0, 0)
|
||||
_verify_memory_metering(0, 0)
|
||||
|
@ -180,8 +180,9 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
mock.patch.object(self.domain, 'info',
|
||||
return_value=(5L, 0L, 0L,
|
||||
2L, 999999L))):
|
||||
interfaces = list(self.inspector.inspect_vnics(self.instance))
|
||||
self.assertEqual([], interfaces)
|
||||
inspect = self.inspector.inspect_vnics
|
||||
self.assertRaises(virt_inspector.InstanceShutOffException,
|
||||
list, inspect(self.instance))
|
||||
|
||||
def test_inspect_disks(self):
|
||||
dom_xml = """
|
||||
@ -228,8 +229,9 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
mock.patch.object(self.domain, 'info',
|
||||
return_value=(5L, 0L, 0L,
|
||||
2L, 999999L))):
|
||||
disks = list(self.inspector.inspect_disks(self.instance))
|
||||
self.assertEqual([], disks)
|
||||
inspect = self.inspector.inspect_disks
|
||||
self.assertRaises(virt_inspector.InstanceShutOffException,
|
||||
list, inspect(self.instance))
|
||||
|
||||
def test_inspect_memory_usage(self):
|
||||
fake_memory_stats = {'available': 51200L, 'unused': 25600L}
|
||||
@ -252,9 +254,9 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
with mock.patch.object(self.domain, 'info',
|
||||
return_value=(5L, 0L, 0L,
|
||||
2L, 999999L)):
|
||||
memory = self.inspector.inspect_memory_usage(
|
||||
self.instance)
|
||||
self.assertIsNone(memory)
|
||||
self.assertRaises(virt_inspector.InstanceShutOffException,
|
||||
self.inspector.inspect_memory_usage,
|
||||
self.instance)
|
||||
|
||||
def test_inspect_memory_usage_with_empty_stats(self):
|
||||
connection = self.inspector.connection
|
||||
@ -265,9 +267,9 @@ class TestLibvirtInspection(base.BaseTestCase):
|
||||
2L, 999999L)):
|
||||
with mock.patch.object(self.domain, 'memoryStats',
|
||||
return_value={}):
|
||||
memory = self.inspector.inspect_memory_usage(
|
||||
self.instance)
|
||||
self.assertIsNone(memory)
|
||||
self.assertRaises(virt_inspector.NoDataException,
|
||||
self.inspector.inspect_memory_usage,
|
||||
self.instance)
|
||||
|
||||
|
||||
class TestLibvirtInspectionWithError(base.BaseTestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user