Merge "Improve plugin flexibility"

This commit is contained in:
Zuul 2022-12-01 05:51:11 +00:00 committed by Gerrit Code Review
commit 0b0e175ed5
14 changed files with 197 additions and 41 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, {}

View File

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

View File

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