Merge "Allow compute monitors in different namespaces"

This commit is contained in:
Jenkins 2015-08-31 16:41:35 +00:00 committed by Gerrit Code Review
commit 51e9b20a83
2 changed files with 79 additions and 31 deletions

View File

@ -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)

View File

@ -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))