Merge "Allow compute monitors in different namespaces"
This commit is contained in:
commit
51e9b20a83
@ -36,7 +36,12 @@ compute_monitors_opts = [
|
||||
help='A list of monitors that can be used for getting '
|
||||
'compute metrics. You can use the alias/name from '
|
||||
'the setuptools entry points for nova.compute.monitors.* '
|
||||
'namespaces.'),
|
||||
'namespaces. If no namespace is supplied, the "cpu." '
|
||||
'namespace is assumed for backwards-compatibility. '
|
||||
'An example value that would enable both the CPU and '
|
||||
'NUMA memory bandwidth monitors that used the virt '
|
||||
'driver variant: '
|
||||
'["cpu.virt_driver", "numa_mem_bw.virt_driver"]'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -46,39 +51,68 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
class MonitorHandler(object):
|
||||
|
||||
def __init__(self, resource_tracker):
|
||||
self.cpu_monitor_loaded = False
|
||||
NAMESPACES = [
|
||||
'nova.compute.monitors.cpu',
|
||||
]
|
||||
|
||||
ns = 'nova.compute.monitors.cpu'
|
||||
cpu_plugin_mgr = enabled.EnabledExtensionManager(
|
||||
def __init__(self, resource_tracker):
|
||||
# Dictionary keyed by the monitor type namespace. Value is the
|
||||
# first loaded monitor of that namespace or False.
|
||||
self.type_monitor_loaded = {ns: False for ns in self.NAMESPACES}
|
||||
|
||||
self.monitors = []
|
||||
for ns in self.NAMESPACES:
|
||||
plugin_mgr = enabled.EnabledExtensionManager(
|
||||
namespace=ns,
|
||||
invoke_on_load=True,
|
||||
check_func=self.check_enabled_cpu_monitor,
|
||||
check_func=self.check_enabled_monitor,
|
||||
invoke_args=(resource_tracker,)
|
||||
)
|
||||
self.monitors = [obj.obj for obj in cpu_plugin_mgr]
|
||||
self.monitors += [ext.obj for ext in plugin_mgr]
|
||||
|
||||
def check_enabled_cpu_monitor(self, ext):
|
||||
if self.cpu_monitor_loaded is not False:
|
||||
msg = _LW("Excluding CPU monitor %(monitor_name)s. Already "
|
||||
"loaded %(loaded_cpu_monitor)s.")
|
||||
def check_enabled_monitor(self, ext):
|
||||
"""Ensures that only one monitor is specified of any type."""
|
||||
# The extension does not have a namespace attribute, unfortunately,
|
||||
# but we can get the namespace by examining the first part of the
|
||||
# entry_point_target attribute, which looks like this:
|
||||
# 'nova.compute.monitors.cpu.virt_driver:Monitor'
|
||||
ept = ext.entry_point_target
|
||||
ept_parts = ept.split(':')
|
||||
namespace_parts = ept_parts[0].split('.')
|
||||
namespace = '.'.join(namespace_parts[0:-1])
|
||||
if self.type_monitor_loaded[namespace] is not False:
|
||||
msg = _LW("Excluding %(namespace)s monitor %(monitor_name)s. "
|
||||
"Already loaded %(loaded_monitor)s.")
|
||||
msg = msg % {
|
||||
'namespace': namespace,
|
||||
'monitor_name': ext.name,
|
||||
'loaded_cpu_monitor': self.cpu_monitor_loaded
|
||||
'loaded_monitor': self.type_monitor_loaded[namespace]
|
||||
}
|
||||
LOG.warn(msg)
|
||||
return False
|
||||
# TODO(jaypipes): Right now, we only have CPU monitors, so we don't
|
||||
# need to check if the plugin is a CPU monitor or not. Once non-CPU
|
||||
# monitors are added, change this to check either the base class or
|
||||
# the set of metric names returned to ensure only a single CPU
|
||||
# monitor is loaded at any one time.
|
||||
if ext.name in CONF.compute_monitors:
|
||||
self.cpu_monitor_loaded = ext.name
|
||||
|
||||
# NOTE(jaypipes): We used to only have CPU monitors, so
|
||||
# CONF.compute_monitors could contain "virt_driver" without any monitor
|
||||
# type namespace. So, to maintain backwards-compatibility with that
|
||||
# older way of specifying monitors, we first loop through any values in
|
||||
# CONF.compute_monitors and put any non-namespace'd values into the
|
||||
# 'cpu' namespace.
|
||||
cfg_monitors = ['cpu.' + cfg if '.' not in cfg else cfg
|
||||
for cfg in CONF.compute_monitors]
|
||||
# NOTE(jaypipes): Append 'nova.compute.monitors.' to any monitor value
|
||||
# that doesn't have it to allow CONF.compute_monitors to use shortened
|
||||
# namespaces (like 'cpu.' instead of 'nova.compute.monitors.cpu.')
|
||||
cfg_monitors = ['nova.compute.monitors.' + cfg
|
||||
if 'nova.compute.monitors.' not in cfg else cfg
|
||||
for cfg in cfg_monitors]
|
||||
if namespace + '.' + ext.name in cfg_monitors:
|
||||
self.type_monitor_loaded[namespace] = ext.name
|
||||
return True
|
||||
msg = _LW("Excluding CPU monitor %(monitor_name)s. Not in the "
|
||||
"list of enabled monitors (CONF.compute_monitors).")
|
||||
msg = _LW("Excluding %(namespace)s monitor %(monitor_name)s. "
|
||||
"Not in the list of enabled monitors "
|
||||
"(CONF.compute_monitors).")
|
||||
msg = msg % {
|
||||
'namespace': namespace,
|
||||
'monitor_name': ext.name,
|
||||
}
|
||||
LOG.warn(msg)
|
||||
|
@ -25,15 +25,29 @@ class MonitorsTestCase(test.NoDBTestCase):
|
||||
"""Test case for monitors."""
|
||||
|
||||
@mock.patch('stevedore.enabled.EnabledExtensionManager')
|
||||
def test_check_enabled_cpu_monitor(self, _mock_ext_manager):
|
||||
def test_check_enabled_monitor(self, _mock_ext_manager):
|
||||
class FakeExt(object):
|
||||
def __init__(self, name):
|
||||
def __init__(self, ept, name):
|
||||
self.entry_point_target = ept
|
||||
self.name = name
|
||||
|
||||
# We check to ensure only one CPU monitor is loaded...
|
||||
self.flags(compute_monitors=['cpu_mon1', 'cpu_mon2'])
|
||||
self.flags(compute_monitors=['mon1', 'mon2'])
|
||||
handler = monitors.MonitorHandler(None)
|
||||
ext_cpu_mon1 = FakeExt('cpu_mon1')
|
||||
ext_cpu_mon2 = FakeExt('cpu_mon2')
|
||||
self.assertTrue(handler.check_enabled_cpu_monitor(ext_cpu_mon1))
|
||||
self.assertFalse(handler.check_enabled_cpu_monitor(ext_cpu_mon2))
|
||||
ext_cpu_mon1 = FakeExt('nova.compute.monitors.cpu.virt_driver:Monitor',
|
||||
'mon1')
|
||||
ext_cpu_mon2 = FakeExt('nova.compute.monitors.cpu.virt_driver:Monitor',
|
||||
'mon2')
|
||||
self.assertTrue(handler.check_enabled_monitor(ext_cpu_mon1))
|
||||
self.assertFalse(handler.check_enabled_monitor(ext_cpu_mon2))
|
||||
|
||||
# We check to ensure that the auto-prefixing of the CPU
|
||||
# namespace is handled properly...
|
||||
self.flags(compute_monitors=['cpu.mon1', 'mon2'])
|
||||
handler = monitors.MonitorHandler(None)
|
||||
ext_cpu_mon1 = FakeExt('nova.compute.monitors.cpu.virt_driver:Monitor',
|
||||
'mon1')
|
||||
ext_cpu_mon2 = FakeExt('nova.compute.monitors.cpu.virt_driver:Monitor',
|
||||
'mon2')
|
||||
self.assertTrue(handler.check_enabled_monitor(ext_cpu_mon1))
|
||||
self.assertFalse(handler.check_enabled_monitor(ext_cpu_mon2))
|
||||
|
Loading…
Reference in New Issue
Block a user