Improve plugin flexibility
The monitoring plugin such as prometheus plugin or fault notification have been modified to be replaceable according to the configuration. Therefore, operators can use their original monitoring functions without changing tacker source code. Implements: blueprint support-auto-lcm Implements: blueprint support-autoheal-queue Change-Id: Ifcdf12c4be2d307c78b38703fe6db4e5aac236ea
This commit is contained in:
parent
a97899864c
commit
c297b4300d
|
@ -118,17 +118,17 @@ The ``additionalParams`` must be set when using FaultNotification.
|
|||
- Cardinality
|
||||
- Description
|
||||
* - additionalParams
|
||||
- 0..1
|
||||
- KeyValuePairs (inlined)
|
||||
- 0..1
|
||||
- Additional input parameters for the instantiation process,
|
||||
specific to the VNF being instantiated.
|
||||
* - >ServerNotifierUri
|
||||
- 1
|
||||
- String
|
||||
- 1
|
||||
- Base Uri for ServerNotifier.
|
||||
* - >ServerNotifierFaultID
|
||||
- 1..N
|
||||
- String
|
||||
- 1..N
|
||||
- List of string that indicates which type of alarms to detect.
|
||||
|
||||
The value of ``ServerNotifierUri`` and ``ServerNotifierFaultID`` are stored
|
||||
|
@ -162,6 +162,28 @@ whether AutoHealing should be performed. In case of performing
|
|||
AutoHealing, VMs are deleted and created via Heat. The client is
|
||||
no need to handle healing.
|
||||
|
||||
Using Vendor Specific Plugin
|
||||
----------------------------
|
||||
|
||||
ServerNotification plugin can be replaced with a vendor specific function.
|
||||
To replace a plugin, change the configurations below.
|
||||
The replaced class must be a subclass of
|
||||
tacker.sol_refactored.common.monitoring_plugin_base.MonitoringPlugin.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 40 40 40
|
||||
|
||||
* - Configuration
|
||||
- Default
|
||||
- Description
|
||||
* - ``CONF.server_notification.server_notification_package``
|
||||
- tacker.sol_refactored.common.server_notification
|
||||
- Package name for server notification.
|
||||
* - ``CONF.server_notification.server_notification_class``
|
||||
- ServerNotification
|
||||
- Class name for server notification.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
|
|
|
@ -334,3 +334,37 @@ rule file directly. Below is example of alert rule.
|
|||
auto_scale_type: SCALE_OUT,
|
||||
aspect_id: VDU1_aspect
|
||||
annotations:
|
||||
|
||||
Using Vendor Specific Plugin
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Prometheus Plugin can be replaced with a vendor specific function.
|
||||
To replace a plugin, change the configurations below.
|
||||
The replaced class must be a subclass of
|
||||
tacker.sol_refactored.common.monitoring_plugin_base.MonitoringPlugin.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 40 40 40
|
||||
|
||||
* - Configuration
|
||||
- Default
|
||||
- Description
|
||||
* - ``CONF.prometheus_plugin.performance_management_package``
|
||||
- tacker.sol_refactored.common.prometheus_plugin
|
||||
- Package name for performance management.
|
||||
* - ``CONF.prometheus_plugin.performance_management_class``
|
||||
- PrometheusPluginPm
|
||||
- Class name for performance management.
|
||||
* - ``CONF.prometheus_plugin.fault_management_package``
|
||||
- tacker.sol_refactored.common.prometheus_plugin
|
||||
- Package name for fault management.
|
||||
* - ``CONF.prometheus_plugin.fault_management_class``
|
||||
- PrometheusPluginFm
|
||||
- Class name for fault management.
|
||||
* - ``CONF.prometheus_plugin.auto_scaling_package``
|
||||
- tacker.sol_refactored.common.prometheus_plugin
|
||||
- Package name for auto scaling.
|
||||
* - ``CONF.prometheus_plugin.auto_scaling_class``
|
||||
- PrometheusPluginAutoScaling
|
||||
- Class name for auto scaling.
|
||||
|
|
|
@ -116,18 +116,51 @@ PROMETHEUS_PLUGIN_OPTS = [
|
|||
cfg.BoolOpt('performance_management',
|
||||
default=False,
|
||||
help=_('Enable prometheus plugin performance management')),
|
||||
|
||||
cfg.IntOpt('reporting_period_margin',
|
||||
default=1,
|
||||
help=_('Some margin time for PM jos\'s reportingPeriod')),
|
||||
|
||||
cfg.BoolOpt('fault_management',
|
||||
default=False,
|
||||
help=_('Enable prometheus plugin fault management')),
|
||||
|
||||
cfg.BoolOpt('auto_scaling',
|
||||
default=False,
|
||||
help=_('Enable prometheus plugin autoscaling')),
|
||||
cfg.StrOpt('performance_management_package',
|
||||
default='tacker.sol_refactored.common.prometheus_plugin',
|
||||
help=_('Package name for performance management. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
cfg.StrOpt('performance_management_class',
|
||||
default='PrometheusPluginPm',
|
||||
help=_('Class name for performance management. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
cfg.StrOpt('fault_management_package',
|
||||
default='tacker.sol_refactored.common.prometheus_plugin',
|
||||
help=_('Package name for fault management. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
cfg.StrOpt('fault_management_class',
|
||||
default='PrometheusPluginFm',
|
||||
help=_('Class name for fault management. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
cfg.StrOpt('auto_scaling_package',
|
||||
default='tacker.sol_refactored.common.prometheus_plugin',
|
||||
help=_('Package name for auto scaling. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
cfg.StrOpt('auto_scaling_class',
|
||||
default='PrometheusPluginAutoScaling',
|
||||
help=_('Class name for auto scaling. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
]
|
||||
|
||||
CONF.register_opts(PROMETHEUS_PLUGIN_OPTS, 'prometheus_plugin')
|
||||
|
@ -136,7 +169,6 @@ SERVER_NOTIFICATION_OPTS = [
|
|||
cfg.BoolOpt('server_notification',
|
||||
default=False,
|
||||
help=_('Enable server notification autohealing')),
|
||||
|
||||
cfg.StrOpt('uri_path_prefix',
|
||||
default='/server_notification',
|
||||
help=_('Uri path prefix string for server notification. '
|
||||
|
@ -147,6 +179,18 @@ SERVER_NOTIFICATION_OPTS = [
|
|||
default=20,
|
||||
help=_('Timeout (second) of packing for multiple '
|
||||
'server notification.')),
|
||||
cfg.StrOpt('server_notification_package',
|
||||
default='tacker.sol_refactored.common.server_notification',
|
||||
help=_('Package name for server notification. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
cfg.StrOpt('server_notification_class',
|
||||
default='ServerNotification',
|
||||
help=_('Class name for server notification. '
|
||||
'This configuration is changed in case of replacing '
|
||||
'the original function with a vendor specific '
|
||||
'function.')),
|
||||
]
|
||||
|
||||
CONF.register_opts(SERVER_NOTIFICATION_OPTS, 'server_notification')
|
||||
|
|
|
@ -416,6 +416,11 @@ class ResourcesOtherOperationInProgress(SolHttpError409):
|
|||
"is in progress.")
|
||||
|
||||
|
||||
# plugin base
|
||||
class MonitoringPluginClassError(SolHttpError503):
|
||||
message = _("%(class_name)s is not a subclass of MonitoringPlugin.")
|
||||
|
||||
|
||||
# prometheus plugin
|
||||
class PrometheusPluginNotEnabled(SolHttpError404):
|
||||
message = _("%(name)s API is not enabled.")
|
||||
|
|
|
@ -14,29 +14,20 @@
|
|||
# under the License.
|
||||
|
||||
from importlib import import_module
|
||||
from oslo_log import log as logging
|
||||
|
||||
module_and_class = {
|
||||
'stub':
|
||||
('tacker.sol_refactored.common.monitoring_plugin_base',
|
||||
'MonitoringPluginStub'),
|
||||
'pm_event':
|
||||
('tacker.sol_refactored.common.prometheus_plugin',
|
||||
'PrometheusPluginPm'),
|
||||
'alert':
|
||||
('tacker.sol_refactored.common.prometheus_plugin',
|
||||
'PrometheusPluginFm'),
|
||||
'auto_healing':
|
||||
('tacker.sol_refactored.common.prometheus_plugin',
|
||||
'PrometheusPluginAutoScaling'),
|
||||
'server_notification':
|
||||
('tacker.sol_refactored.common.server_notification',
|
||||
'ServerNotification'),
|
||||
}
|
||||
from tacker.sol_refactored.common import exceptions as sol_ex
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_class(short_name):
|
||||
module = import_module(module_and_class[short_name][0])
|
||||
return getattr(module, module_and_class[short_name][1])
|
||||
def get_class(package_name, class_name):
|
||||
module = import_module(package_name)
|
||||
_class = getattr(module, class_name)
|
||||
if not issubclass(_class, MonitoringPlugin):
|
||||
LOG.error(f"Loading plugin failed: {package_name}.{class_name}.")
|
||||
raise sol_ex.MonitoringPluginClassError(class_name=class_name)
|
||||
return _class
|
||||
|
||||
|
||||
class MonitoringPlugin():
|
||||
|
|
|
@ -398,7 +398,7 @@ class PrometheusPluginPm(PrometheusPlugin, mon_base.MonitoringPlugin):
|
|||
collection_period))
|
||||
return rules
|
||||
|
||||
def get_compute_resouce_by_sub_obj(self, vnf_instance, sub_obj):
|
||||
def get_compute_resource_by_sub_obj(self, vnf_instance, sub_obj):
|
||||
inst = vnf_instance
|
||||
if (not inst.obj_attr_is_set('instantiatedVnfInfo') or
|
||||
not inst.instantiatedVnfInfo.obj_attr_is_set(
|
||||
|
@ -440,7 +440,7 @@ class PrometheusPluginPm(PrometheusPlugin, mon_base.MonitoringPlugin):
|
|||
# resource id is like 'test-test1-756757f8f-xcwmt'
|
||||
# obtain 'test-test1' as deployment
|
||||
# obtain 'test' as container
|
||||
compute_resource = self.get_compute_resouce_by_sub_obj(
|
||||
compute_resource = self.get_compute_resource_by_sub_obj(
|
||||
inst, sub_obj)
|
||||
if not compute_resource:
|
||||
continue
|
||||
|
|
|
@ -26,7 +26,9 @@ class PmEventController(prom_wsgi.PrometheusPluginAPIController):
|
|||
if not CONF.prometheus_plugin.performance_management:
|
||||
raise sol_ex.PrometheusPluginNotEnabled(
|
||||
name='Performance management')
|
||||
cls = mon_base.get_class('pm_event')
|
||||
cls = mon_base.get_class(
|
||||
CONF.prometheus_plugin.performance_management_package,
|
||||
CONF.prometheus_plugin.performance_management_class)
|
||||
mon_base.MonitoringPlugin.get_instance(cls).alert(
|
||||
request=request, body=body)
|
||||
return prom_wsgi.PrometheusPluginResponse(204, None)
|
||||
|
@ -37,7 +39,9 @@ class FmAlertController(prom_wsgi.PrometheusPluginAPIController):
|
|||
if not CONF.prometheus_plugin.fault_management:
|
||||
raise sol_ex.PrometheusPluginNotEnabled(
|
||||
name='Fault management')
|
||||
cls = mon_base.get_class('alert')
|
||||
cls = mon_base.get_class(
|
||||
CONF.prometheus_plugin.fault_management_package,
|
||||
CONF.prometheus_plugin.fault_management_class)
|
||||
mon_base.MonitoringPlugin.get_instance(cls).alert(
|
||||
request=request, body=body)
|
||||
return prom_wsgi.PrometheusPluginResponse(204, None)
|
||||
|
@ -48,7 +52,9 @@ class AutoScalingController(prom_wsgi.PrometheusPluginAPIController):
|
|||
if not CONF.prometheus_plugin.auto_scaling:
|
||||
raise sol_ex.PrometheusPluginNotEnabled(
|
||||
name='Auto scaling')
|
||||
cls = mon_base.get_class('auto_healing')
|
||||
cls = mon_base.get_class(
|
||||
CONF.prometheus_plugin.auto_scaling_package,
|
||||
CONF.prometheus_plugin.auto_scaling_class)
|
||||
mon_base.MonitoringPlugin.get_instance(cls).alert(
|
||||
request=request, body=body)
|
||||
return prom_wsgi.PrometheusPluginResponse(204, None)
|
||||
|
|
|
@ -25,7 +25,9 @@ class ServerNotificationController(sn_wsgi.ServerNotificationAPIController):
|
|||
def notify(self, request, vnf_instance_id, server_id, body):
|
||||
if not CONF.server_notification.server_notification:
|
||||
raise sol_ex.ServerNotificationNotEnabled()
|
||||
cls = mon_base.get_class('server_notification')
|
||||
cls = mon_base.get_class(
|
||||
CONF.server_notification.server_notification_package,
|
||||
CONF.server_notification.server_notification_class)
|
||||
mon_base.MonitoringPlugin.get_instance(cls).alert(
|
||||
request=request, vnf_instance_id=vnf_instance_id,
|
||||
server_id=server_id, body=body)
|
||||
|
|
|
@ -116,7 +116,9 @@ class VnfPmControllerV2(sol_wsgi.SolAPIController):
|
|||
self.nfvo_client = nfvo_client.NfvoClient()
|
||||
self.endpoint = CONF.v2_vnfm.endpoint
|
||||
self._pm_job_view = vnfpm_view.PmJobViewBuilder(self.endpoint)
|
||||
cls = plugin.get_class('pm_event')
|
||||
cls = plugin.get_class(
|
||||
CONF.prometheus_plugin.performance_management_package,
|
||||
CONF.prometheus_plugin.performance_management_class)
|
||||
self.plugin = plugin.MonitoringPlugin.get_instance(cls)
|
||||
|
||||
@validator.schema(schema.CreatePmJobRequest_V210, '2.1.0')
|
||||
|
|
|
@ -147,8 +147,6 @@ class ServerNotificationTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
|||
|
||||
# Test notification
|
||||
self.assert_notification_get(callback_url)
|
||||
# check usageState of VNF Package
|
||||
self._check_package_usage(is_nfvo, self.svn_pkg)
|
||||
|
||||
# 1. LCM-Create
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
|
|
|
@ -463,7 +463,7 @@ class TestPrometheusPluginPm(base.TestCase):
|
|||
group='prometheus_plugin', performance_management=True)
|
||||
pp = mon_base.MonitoringPlugin.get_instance(
|
||||
prometheus_plugin.PrometheusPluginPm)
|
||||
# noromal
|
||||
# normal
|
||||
job = objects.PmJobV2.from_dict(_pm_job)
|
||||
pp.delete_job(context=self.context, pm_job=job)
|
||||
# error
|
||||
|
|
|
@ -124,7 +124,7 @@ class TestPrometheusPlugin(db_base.SqlTestCase):
|
|||
self.conductor = conductor_v2.ConductorV2()
|
||||
|
||||
@mock.patch.object(http_client.HttpClient, 'do_request')
|
||||
def test_requst_scale(self, mock_do_request):
|
||||
def test_request_scale(self, mock_do_request):
|
||||
resp = webob.Response()
|
||||
resp.status_code = 202
|
||||
mock_do_request.return_value = resp, {}
|
||||
|
|
|
@ -145,7 +145,7 @@ _body_scale_alert1 = {
|
|||
'fingerprint': '5ef77f1f8a3ecb8d'
|
||||
}
|
||||
|
||||
# fuction_type mismatch
|
||||
# function_type mismatch
|
||||
_body_scale_alert2 = copy.deepcopy(_body_scale_alert1)
|
||||
_body_scale_alert2['labels']['function_type'] = 'vnffm'
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ from unittest import mock
|
|||
|
||||
from tacker import context
|
||||
from tacker.sol_refactored.common import exceptions as sol_ex
|
||||
from tacker.sol_refactored.common import monitoring_plugin_base as mon_base
|
||||
from tacker.sol_refactored.common import server_notification as sn_common
|
||||
from tacker.sol_refactored.common import vnf_instance_utils as inst_utils
|
||||
from tacker.sol_refactored.controller import server_notification
|
||||
|
@ -77,6 +78,31 @@ _body2 = {
|
|||
'error_schema': {}
|
||||
}
|
||||
|
||||
pkg = 'tacker.tests.unit.sol_refactored.controller.test_server_notification'
|
||||
|
||||
|
||||
class VendorSpecificMonitoringPlugin(mon_base.MonitoringPlugin):
|
||||
_instance = None
|
||||
|
||||
@staticmethod
|
||||
def instance():
|
||||
if not VendorSpecificMonitoringPlugin._instance:
|
||||
VendorSpecificMonitoringPlugin()
|
||||
return VendorSpecificMonitoringPlugin._instance
|
||||
|
||||
def __init__(self):
|
||||
if VendorSpecificMonitoringPlugin._instance:
|
||||
raise SystemError(
|
||||
"Not constructor but instance() should be used.")
|
||||
VendorSpecificMonitoringPlugin._instance = self
|
||||
|
||||
def alert(self, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class NotASubClassOfMonitoringPlugin():
|
||||
pass
|
||||
|
||||
|
||||
class TestServerNotification(base.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -105,8 +131,7 @@ class TestServerNotification(base.TestCase):
|
|||
server_id='test_server_id', body=_body)
|
||||
|
||||
@mock.patch.object(inst_utils, 'get_inst')
|
||||
def test_notify(self,
|
||||
mock_inst):
|
||||
def test_notify(self, mock_inst):
|
||||
self.config_fixture.config(
|
||||
group='server_notification', server_notification=True)
|
||||
mock_inst.return_value = objects.VnfInstanceV2.from_dict(_inst1)
|
||||
|
@ -168,3 +193,30 @@ class TestServerNotification(base.TestCase):
|
|||
self.controller.notify, request=self.request,
|
||||
vnf_instance_id='test_id',
|
||||
server_id='test_server_id', body=_body)
|
||||
|
||||
def test_vendor_specific_plugin(self):
|
||||
self.config_fixture.config(
|
||||
group='server_notification', server_notification=True)
|
||||
self.config_fixture.config(
|
||||
group='server_notification', server_notification_package=pkg)
|
||||
self.config_fixture.config(
|
||||
group='server_notification',
|
||||
server_notification_class='VendorSpecificMonitoringPlugin')
|
||||
response = self.controller.notify(
|
||||
request=self.request,
|
||||
vnf_instance_id='test_id',
|
||||
server_id='test_server_id', body=_body)
|
||||
self.assertEqual(204, response.status)
|
||||
|
||||
def test_vendor_specific_plugin_subclass(self):
|
||||
self.config_fixture.config(
|
||||
group='server_notification', server_notification=True)
|
||||
self.config_fixture.config(
|
||||
group='server_notification', server_notification_package=pkg)
|
||||
self.config_fixture.config(
|
||||
group='server_notification',
|
||||
server_notification_class='NotASubClassOfMonitoringPlugin')
|
||||
self.assertRaises(
|
||||
sol_ex.MonitoringPluginClassError, self.controller.notify,
|
||||
request=self.request, vnf_instance_id='test_id',
|
||||
server_id='test_server_id', body=_body)
|
||||
|
|
Loading…
Reference in New Issue