Coverage for nova/compute/monitors/__init__.py: 95%
29 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
1# Copyright 2013 Intel Corporation.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16"""
17Resource monitor API specification.
18"""
20from oslo_log import log as logging
21from stevedore import enabled
23import nova.conf
25CONF = nova.conf.CONF
26LOG = logging.getLogger(__name__)
29class MonitorHandler(object):
31 NAMESPACES = [
32 'nova.compute.monitors.cpu',
33 ]
35 def __init__(self, resource_tracker):
36 # Dictionary keyed by the monitor type namespace. Value is the
37 # first loaded monitor of that namespace or False.
38 self.type_monitor_loaded = {ns: False for ns in self.NAMESPACES}
40 self.monitors = []
41 for ns in self.NAMESPACES:
42 plugin_mgr = enabled.EnabledExtensionManager(
43 namespace=ns,
44 invoke_on_load=True,
45 check_func=self.check_enabled_monitor,
46 invoke_args=(resource_tracker,)
47 )
48 self.monitors += [ext.obj for ext in plugin_mgr]
50 def check_enabled_monitor(self, ext):
51 """Ensures that only one monitor is specified of any type."""
52 # The extension does not have a namespace attribute, unfortunately,
53 # but we can get the namespace by examining the first part of the
54 # entry_point_target attribute, which looks like this:
55 # 'nova.compute.monitors.cpu.virt_driver:Monitor'
56 ept = ext.entry_point_target
57 ept_parts = ept.split(':')
58 namespace_parts = ept_parts[0].split('.')
59 namespace = '.'.join(namespace_parts[0:-1])
60 if self.type_monitor_loaded[namespace] is not False:
61 LOG.warning("Excluding %(namespace)s monitor "
62 "%(monitor_name)s. Already loaded "
63 "%(loaded_monitor)s.",
64 {'namespace': namespace,
65 'monitor_name': ext.name,
66 'loaded_monitor': self.type_monitor_loaded[namespace]
67 })
68 return False
70 # NOTE(jaypipes): We used to only have CPU monitors, so
71 # CONF.compute_monitors could contain "virt_driver" without any monitor
72 # type namespace. So, to maintain backwards-compatibility with that
73 # older way of specifying monitors, we first loop through any values in
74 # CONF.compute_monitors and put any non-namespace'd values into the
75 # 'cpu' namespace.
76 cfg_monitors = ['cpu.' + cfg if '.' not in cfg else cfg
77 for cfg in CONF.compute_monitors]
78 # NOTE(jaypipes): Append 'nova.compute.monitors.' to any monitor value
79 # that doesn't have it to allow CONF.compute_monitors to use shortened
80 # namespaces (like 'cpu.' instead of 'nova.compute.monitors.cpu.')
81 cfg_monitors = ['nova.compute.monitors.' + cfg
82 if 'nova.compute.monitors.' not in cfg else cfg
83 for cfg in cfg_monitors]
84 if namespace + '.' + ext.name in cfg_monitors:
85 self.type_monitor_loaded[namespace] = ext.name
86 return True
87 # Only log something if compute_monitors is not empty.
88 if CONF.compute_monitors: 88 ↛ 89line 88 didn't jump to line 89 because the condition on line 88 was never true
89 LOG.warning("Excluding %(namespace)s monitor %(monitor_name)s. "
90 "Not in the list of enabled monitors "
91 "(CONF.compute_monitors).",
92 {'namespace': namespace, 'monitor_name': ext.name})
93 return False