Merge "Improve plugin flexibility"
This commit is contained in:
commit
0b0e175ed5
|
@ -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