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 '
|
help='A list of monitors that can be used for getting '
|
||||||
'compute metrics. You can use the alias/name from '
|
'compute metrics. You can use the alias/name from '
|
||||||
'the setuptools entry points for nova.compute.monitors.* '
|
'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
|
CONF = cfg.CONF
|
||||||
@ -46,39 +51,68 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class MonitorHandler(object):
|
class MonitorHandler(object):
|
||||||
|
|
||||||
def __init__(self, resource_tracker):
|
NAMESPACES = [
|
||||||
self.cpu_monitor_loaded = False
|
'nova.compute.monitors.cpu',
|
||||||
|
]
|
||||||
|
|
||||||
ns = 'nova.compute.monitors.cpu'
|
def __init__(self, resource_tracker):
|
||||||
cpu_plugin_mgr = enabled.EnabledExtensionManager(
|
# 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,
|
namespace=ns,
|
||||||
invoke_on_load=True,
|
invoke_on_load=True,
|
||||||
check_func=self.check_enabled_cpu_monitor,
|
check_func=self.check_enabled_monitor,
|
||||||
invoke_args=(resource_tracker,)
|
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):
|
def check_enabled_monitor(self, ext):
|
||||||
if self.cpu_monitor_loaded is not False:
|
"""Ensures that only one monitor is specified of any type."""
|
||||||
msg = _LW("Excluding CPU monitor %(monitor_name)s. Already "
|
# The extension does not have a namespace attribute, unfortunately,
|
||||||
"loaded %(loaded_cpu_monitor)s.")
|
# 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 % {
|
msg = msg % {
|
||||||
|
'namespace': namespace,
|
||||||
'monitor_name': ext.name,
|
'monitor_name': ext.name,
|
||||||
'loaded_cpu_monitor': self.cpu_monitor_loaded
|
'loaded_monitor': self.type_monitor_loaded[namespace]
|
||||||
}
|
}
|
||||||
LOG.warn(msg)
|
LOG.warn(msg)
|
||||||
return False
|
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
|
# NOTE(jaypipes): We used to only have CPU monitors, so
|
||||||
# monitors are added, change this to check either the base class or
|
# CONF.compute_monitors could contain "virt_driver" without any monitor
|
||||||
# the set of metric names returned to ensure only a single CPU
|
# type namespace. So, to maintain backwards-compatibility with that
|
||||||
# monitor is loaded at any one time.
|
# older way of specifying monitors, we first loop through any values in
|
||||||
if ext.name in CONF.compute_monitors:
|
# CONF.compute_monitors and put any non-namespace'd values into the
|
||||||
self.cpu_monitor_loaded = ext.name
|
# '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
|
return True
|
||||||
msg = _LW("Excluding CPU monitor %(monitor_name)s. Not in the "
|
msg = _LW("Excluding %(namespace)s monitor %(monitor_name)s. "
|
||||||
"list of enabled monitors (CONF.compute_monitors).")
|
"Not in the list of enabled monitors "
|
||||||
|
"(CONF.compute_monitors).")
|
||||||
msg = msg % {
|
msg = msg % {
|
||||||
|
'namespace': namespace,
|
||||||
'monitor_name': ext.name,
|
'monitor_name': ext.name,
|
||||||
}
|
}
|
||||||
LOG.warn(msg)
|
LOG.warn(msg)
|
||||||
|
@ -25,15 +25,29 @@ class MonitorsTestCase(test.NoDBTestCase):
|
|||||||
"""Test case for monitors."""
|
"""Test case for monitors."""
|
||||||
|
|
||||||
@mock.patch('stevedore.enabled.EnabledExtensionManager')
|
@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):
|
class FakeExt(object):
|
||||||
def __init__(self, name):
|
def __init__(self, ept, name):
|
||||||
|
self.entry_point_target = ept
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
# We check to ensure only one CPU monitor is loaded...
|
# 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)
|
handler = monitors.MonitorHandler(None)
|
||||||
ext_cpu_mon1 = FakeExt('cpu_mon1')
|
ext_cpu_mon1 = FakeExt('nova.compute.monitors.cpu.virt_driver:Monitor',
|
||||||
ext_cpu_mon2 = FakeExt('cpu_mon2')
|
'mon1')
|
||||||
self.assertTrue(handler.check_enabled_cpu_monitor(ext_cpu_mon1))
|
ext_cpu_mon2 = FakeExt('nova.compute.monitors.cpu.virt_driver:Monitor',
|
||||||
self.assertFalse(handler.check_enabled_cpu_monitor(ext_cpu_mon2))
|
'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