From 7ce998f3da2c7f10d95508ff2f410075ae2a8757 Mon Sep 17 00:00:00 2001 From: garciaale Date: Thu, 3 Dec 2020 18:05:24 -0300 Subject: [PATCH] SOL006 patch for POL Change-Id: Id7bb8f8bb358fcbe8b348617bdb64c224daba5a7 Signed-off-by: garciaale --- osm_policy_module/alarming/service.py | 29 +- osm_policy_module/autoscaling/service.py | 134 +++--- osm_policy_module/common/common_db_client.py | 6 +- osm_policy_module/common/mon_client.py | 2 +- .../tests/integration/test_policy_agent.py | 389 +++++++++--------- .../examples/cirros_vdu_scaling_nsd.yaml | 98 +++-- .../examples/cirros_vdu_scaling_vnfd.yaml | 109 +++++ .../examples/cirros_vdu_scaling_vnfd_1.yaml | 75 ---- .../examples/cirros_vdu_scaling_vnfd_2.yaml | 75 ---- .../tests/unit/utils/test_vnfd_utils.py | 23 +- osm_policy_module/utils/vnfd.py | 19 +- tox.ini | 2 +- 12 files changed, 452 insertions(+), 509 deletions(-) create mode 100644 osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd.yaml delete mode 100644 osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_1.yaml delete mode 100644 osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_2.yaml diff --git a/osm_policy_module/alarming/service.py b/osm_policy_module/alarming/service.py index 0200a71..55fe864 100644 --- a/osm_policy_module/alarming/service.py +++ b/osm_policy_module/alarming/service.py @@ -86,17 +86,18 @@ class AlarmingService: vnf_monitoring_param = next( filter( lambda param: param['id'] == alarm_descriptor['vnf-monitoring-param-ref'], - vnfd['monitoring-param']) + vdu.get('monitoring-parameter', []) + ), + {} ) - metric_name = self._get_metric_name(vnf_monitoring_param, vdur, vnfd) + metric_name = self._get_metric_name(vnf_monitoring_param) alarm_uuid = await self.mon_client.create_alarm( metric_name=metric_name, ns_id=nsr_id, vdu_name=vdur['name'], vnf_member_index=vnfr['member-vnf-index-ref'], threshold=alarm_descriptor['value'], - operation=alarm_descriptor['operation'], - statistic=vnf_monitoring_param['aggregation-type'] + operation=alarm_descriptor['operation'] ) alarm = VnfAlarmRepository.create( alarm_id=alarm_descriptor['alarm-id'], @@ -132,6 +133,7 @@ class AlarmingService: database.db.close() async def delete_orphaned_alarms(self, nsr_id): + # TODO: Review as it seems this code is never called log.info("Deleting orphaned vnf alarms for network service %s", nsr_id) database.db.connect() try: @@ -199,20 +201,7 @@ class AlarmingService: finally: database.db.close() - def _get_metric_name(self, vnf_monitoring_param: dict, vdur: dict, vnfd: dict): - vdu = next( - filter(lambda vdu: vdu['id'] == vdur['vdu-id-ref'], vnfd['vdu']) - ) - if 'vdu-monitoring-param' in vnf_monitoring_param: - vdu_monitoring_param = next(filter( - lambda param: param['id'] == vnf_monitoring_param['vdu-monitoring-param'][ - 'vdu-monitoring-param-ref'], vdu['monitoring-param'])) - nfvi_metric = vdu_monitoring_param['nfvi-metric'] - return nfvi_metric - if 'vdu-metric' in vnf_monitoring_param: - vnf_metric_name = vnf_monitoring_param['vdu-metric']['vdu-metric-name-ref'] - return vnf_metric_name - if 'vnf-metric' in vnf_monitoring_param: - vnf_metric_name = vnf_monitoring_param['vnf-metric']['vnf-metric-name-ref'] - return vnf_metric_name + def _get_metric_name(self, vnf_monitoring_param: dict): + if 'performance-metric' in vnf_monitoring_param: + return vnf_monitoring_param['performance-metric'] raise ValueError('No metric name found for vnf_monitoring_param %s' % vnf_monitoring_param['id']) diff --git a/osm_policy_module/autoscaling/service.py b/osm_policy_module/autoscaling/service.py index b840acb..fb3ecaf 100644 --- a/osm_policy_module/autoscaling/service.py +++ b/osm_policy_module/autoscaling/service.py @@ -26,7 +26,6 @@ import asyncio import datetime import json import logging -from typing import List from osm_policy_module.common.common_db_client import CommonDbClient from osm_policy_module.common.lcm_client import LcmClient @@ -36,7 +35,6 @@ from osm_policy_module.core.config import Config from osm_policy_module.core.database import ScalingGroup, ScalingAlarm, ScalingPolicy, ScalingCriteria, \ ScalingAlarmRepository, ScalingGroupRepository, ScalingPolicyRepository, ScalingCriteriaRepository from osm_policy_module.core.exceptions import VdurNotFound -from osm_policy_module.utils.vnfd import VnfdUtils log = logging.getLogger(__name__) @@ -69,16 +67,21 @@ class AutoscalingService: for vnfr in vnfrs: log.debug("Processing vnfr: %s", vnfr) vnfd = self.db_client.get_vnfd(vnfr['vnfd-id']) - if 'scaling-group-descriptor' not in vnfd: - log.debug("No scaling group present in vnfd") + # TODO: Change for multiple DF support + df = vnfd.get('df', [{}])[0] + if 'scaling-aspect' not in df: + log.debug("No scaling aspect present in vnfd") continue - scaling_groups = vnfd['scaling-group-descriptor'] - vnf_monitoring_params = vnfd['monitoring-param'] - for scaling_group in scaling_groups: + # TODO: Change for multiple instantiation levels support + instantiation_level = df.get('instantiation-level', [{}])[0] + scaling_aspects = df['scaling-aspect'] + all_vnfd_monitoring_params = self._get_all_vnfd_monitoring_params(vnfd) + for scaling_aspect in scaling_aspects: scaling_group_record = self._get_or_create_scaling_group(nsr_id, vnfr['member-vnf-index-ref'], - scaling_group) - for scaling_policy in scaling_group['scaling-policy']: + scaling_aspect) + vdurs = self._get_monitored_vdurs(scaling_aspect, vnfr['vdur']) + for scaling_policy in scaling_aspect.get('scaling-policy', ()): if scaling_policy['scaling-type'] != 'automatic': continue scaling_policy_record = self._get_or_create_scaling_policy(nsr_id, @@ -91,15 +94,11 @@ class AutoscalingService: scaling_criteria, scaling_policy_record ) - vnf_monitoring_param = next( - filter( - lambda param: param['id'] == scaling_criteria[ - 'vnf-monitoring-param-ref' - ], - vnf_monitoring_params) - ) - vdurs = self._get_monitored_vdurs(vnf_monitoring_param, vnfr['vdur'], vnfd) + monitoring_param_ref = scaling_criteria.get('vnf-monitoring-param-ref') + vnf_monitoring_param = all_vnfd_monitoring_params[monitoring_param_ref] + for vdur in vdurs: + vdu_id = vdur['vdu-id-ref'] log.debug("Creating alarm for vdur %s ", vdur) try: ScalingAlarmRepository.get(ScalingAlarm.vdu_name == vdur['name'], @@ -113,17 +112,19 @@ class AutoscalingService: continue except ScalingAlarm.DoesNotExist: pass - metric_name = self._get_metric_name(vnf_monitoring_param, vdur, vnfd) + metric_name = self._get_metric_name(vnf_monitoring_param) db_nsr = self.db_client.get_nsr(nsr_id) nb_scale_op = 0 if db_nsr["_admin"].get("scaling-group"): db_nsr_admin = db_nsr["_admin"]["scaling-group"] for admin_scale_index, admin_scale_info in enumerate(db_nsr_admin): - if admin_scale_info["name"] == scaling_group["name"]: + if admin_scale_info["name"] == scaling_aspect["name"]: nb_scale_op = admin_scale_info.get("nb-scale-op", 0) break - min_instance_count = int(scaling_group["min-instance-count"]) + for vdu_level in instantiation_level.get('vdu-level', ()): + if vdu_level.get('vdu-id') == vdu_id: + min_instance_count = int(vdu_level['number-of-instances']) if nb_scale_op > min_instance_count: alarm_uuid = await self.mon_client.create_alarm( metric_name=metric_name, @@ -131,8 +132,7 @@ class AutoscalingService: vdu_name=vdur['name'], vnf_member_index=vnfr['member-vnf-index-ref'], threshold=scaling_criteria['scale-in-threshold'], - operation=scaling_criteria['scale-in-relational-operation'], - statistic=vnf_monitoring_param['aggregation-type'] + operation=scaling_criteria['scale-in-relational-operation'] ) alarm = ScalingAlarmRepository.create( alarm_uuid=alarm_uuid, @@ -148,8 +148,7 @@ class AutoscalingService: vdu_name=vdur['name'], vnf_member_index=vnfr['member-vnf-index-ref'], threshold=scaling_criteria['scale-out-threshold'], - operation=scaling_criteria['scale-out-relational-operation'], - statistic=vnf_monitoring_param['aggregation-type'] + operation=scaling_criteria['scale-out-relational-operation'] ) alarm = ScalingAlarmRepository.create( alarm_uuid=alarm_uuid, @@ -293,12 +292,28 @@ class AutoscalingService: finally: database.db.close() - def _get_or_create_scaling_group(self, nsr_id: str, vnf_member_index: str, scaling_group: dict): + def _get_all_vnfd_monitoring_params(self, vnfd): + all_monitoring_params = {} + for ivld in vnfd.get("int-virtual-link-desc", ()): + for mp in ivld.get("monitoring-parameters", ()): + all_monitoring_params[mp.get("id")] = mp + + for vdu in vnfd.get("vdu", ()): + for mp in vdu.get("monitoring-parameter", ()): + all_monitoring_params[mp.get("id")] = mp + + for df in vnfd.get("df", ()): + for mp in df.get("monitoring-parameter", ()): + all_monitoring_params[mp.get("id")] = mp + + return all_monitoring_params + + def _get_or_create_scaling_group(self, nsr_id: str, vnf_member_index: str, scaling_aspect: dict): try: scaling_group_record = ScalingGroupRepository.get( ScalingGroup.nsr_id == nsr_id, ScalingGroup.vnf_member_index == vnf_member_index, - ScalingGroup.name == scaling_group['name'] + ScalingGroup.name == scaling_aspect['name'] ) log.debug("Found existing scaling group record in DB...") except ScalingGroup.DoesNotExist: @@ -306,8 +321,8 @@ class AutoscalingService: scaling_group_record = ScalingGroupRepository.create( nsr_id=nsr_id, vnf_member_index=vnf_member_index, - name=scaling_group['name'], - content=json.dumps(scaling_group) + name=scaling_aspect['name'], + content=json.dumps(scaling_aspect) ) log.debug( "Created scaling group record in DB : nsr_id=%s, vnf_member_index=%s, name=%s", @@ -333,11 +348,9 @@ class AutoscalingService: scaling_group=scaling_group_record, ) if 'scale-in-operation-type' in scaling_policy: - scaling_policy_record.scale_in_operation = scaling_policy[ - 'scale-in-operation-type'] + scaling_policy_record.scale_in_operation = scaling_policy['scale-in-operation-type'] if 'scale-out-operation-type' in scaling_policy: - scaling_policy_record.scale_out_operation = scaling_policy[ - 'scale-out-operation-type'] + scaling_policy_record.scale_out_operation = scaling_policy['scale-out-operation-type'] if 'enabled' in scaling_policy: scaling_policy_record.enabled = scaling_policy['enabled'] scaling_policy_record.save() @@ -368,54 +381,21 @@ class AutoscalingService: scaling_criteria_record.scaling_policy.name) return scaling_criteria_record - def _get_monitored_vdurs(self, vnf_monitoring_param: dict, vdurs: List[dict], vnfd: dict): - monitored_vdurs = [] - if 'vdu-monitoring-param' in vnf_monitoring_param: - monitored_vdurs = list( - filter( - lambda vdur: vdur['vdu-id-ref'] == vnf_monitoring_param - ['vdu-monitoring-param'] - ['vdu-ref'], - vdurs - ) - ) - elif 'vdu-metric' in vnf_monitoring_param: - monitored_vdurs = list( - filter( - lambda vdur: vdur['vdu-id-ref'] == vnf_monitoring_param - ['vdu-metric'] - ['vdu-ref'], - vdurs - ) - ) - elif 'vnf-metric' in vnf_monitoring_param: - vdu = VnfdUtils.get_mgmt_vdu(vnfd) - monitored_vdurs = list( - filter( - lambda vdur: vdur['vdu-id-ref'] == vdu['id'], - vdurs - ) - ) - else: + def _get_monitored_vdurs(self, scaling_aspect: dict, vdurs): + all_monitored_vdus = set() + for delta in scaling_aspect.get('aspect-delta-details', {}).get('deltas', ()): + for vdu_delta in delta.get('vdu-delta', ()): + all_monitored_vdus.add(vdu_delta.get('id')) + + monitored_vdurs = list(filter(lambda vdur: vdur['vdu-id-ref'] in all_monitored_vdus, vdurs)) + + if not monitored_vdurs: log.warning( "Scaling criteria is referring to a vnf-monitoring-param that does not " "contain a reference to a vdu or vnf metric.") return monitored_vdurs - def _get_metric_name(self, vnf_monitoring_param: dict, vdur: dict, vnfd: dict): - vdu = next( - filter(lambda vdu: vdu['id'] == vdur['vdu-id-ref'], vnfd['vdu']) - ) - if 'vdu-monitoring-param' in vnf_monitoring_param: - vdu_monitoring_param = next(filter( - lambda param: param['id'] == vnf_monitoring_param['vdu-monitoring-param'][ - 'vdu-monitoring-param-ref'], vdu['monitoring-param'])) - nfvi_metric = vdu_monitoring_param['nfvi-metric'] - return nfvi_metric - if 'vdu-metric' in vnf_monitoring_param: - vnf_metric_name = vnf_monitoring_param['vdu-metric']['vdu-metric-name-ref'] - return vnf_metric_name - if 'vnf-metric' in vnf_monitoring_param: - vnf_metric_name = vnf_monitoring_param['vnf-metric']['vnf-metric-name-ref'] - return vnf_metric_name + def _get_metric_name(self, vnf_monitoring_param: dict): + if 'performance-metric' in vnf_monitoring_param: + return vnf_monitoring_param['performance-metric'] raise ValueError('No metric name found for vnf_monitoring_param %s' % vnf_monitoring_param['id']) diff --git a/osm_policy_module/common/common_db_client.py b/osm_policy_module/common/common_db_client.py index accbbfc..9ec183a 100644 --- a/osm_policy_module/common/common_db_client.py +++ b/osm_policy_module/common/common_db_client.py @@ -43,8 +43,10 @@ class CommonDbClient: return vnfr def get_vnfrs(self, nsr_id: str): - return [self.get_vnfr(nsr_id, member['member-vnf-index']) for member in - self.get_nsr(nsr_id)['nsd']['constituent-vnfd']] + # TODO: Change for multiple DF support + nsr_nsd_df = self.get_nsr(nsr_id)['nsd'].get('df', [{}])[0] + all_nsd_member_vnf_index = [vnf.get('id') for vnf in nsr_nsd_df.get('vnf-profile', [])] + return [self.get_vnfr(nsr_id, member_index) for member_index in all_nsd_member_vnf_index] def get_vnfd(self, vnfd_id: str): vnfr = self.common_db.get_one("vnfds", diff --git a/osm_policy_module/common/mon_client.py b/osm_policy_module/common/mon_client.py index f578462..c83f794 100644 --- a/osm_policy_module/common/mon_client.py +++ b/osm_policy_module/common/mon_client.py @@ -44,7 +44,7 @@ class MonClient: self.loop = loop async def create_alarm(self, metric_name: str, ns_id: str, vdu_name: str, vnf_member_index: str, threshold: int, - statistic: str, operation: str): + operation: str, statistic: str = 'AVERAGE'): cor_id = random.randint(1, 10e7) msg = self._build_create_alarm_payload(cor_id, metric_name, diff --git a/osm_policy_module/tests/integration/test_policy_agent.py b/osm_policy_module/tests/integration/test_policy_agent.py index 1a9dd68..9fe5e2a 100644 --- a/osm_policy_module/tests/integration/test_policy_agent.py +++ b/osm_policy_module/tests/integration/test_policy_agent.py @@ -53,43 +53,7 @@ nsr_record_mock = { "ssh-authorized-key": None, "name-ref": "cirros_ns", "nsd": { - "name": "cirros_vdu_scaling_ns", "_id": "d7c8bd3c-eb39-4514-8847-19f01345524f", - "vld": [ - { - "id": "cirros_nsd_vld1", - "name": "cirros_nsd_vld1", - "type": "ELAN", - "mgmt-network": "true", - "vnfd-connection-point-ref": [ - { - "vnfd-id-ref": "cirros_vdu_scaling_vnf", - "member-vnf-index-ref": 1, - "vnfd-connection-point-ref": "eth0" - }, - { - "vnfd-id-ref": "cirros_vdu_scaling_vnf", - "member-vnf-index-ref": 2, - "vnfd-connection-point-ref": "eth0" - } - ] - } - ], - "vendor": "OSM", - "constituent-vnfd": [ - { - "member-vnf-index": "1", - "vnfd-id-ref": "cirros_vdu_scaling_vnf" - }, - { - "member-vnf-index": "2", - "vnfd-id-ref": "cirros_vdu_scaling_vnf" - } - ], - "version": "1.0", - "id": "cirros_vdu_scaling_ns", - "description": "Simple NS example with a cirros_vdu_scaling_vnf", - "logo": "osm.png", "_admin": { "created": 1535392246.499733, "userDefinedData": { @@ -114,7 +78,40 @@ nsr_record_mock = { "admin" ] }, - "short-name": "cirros_vdu_scaling_ns" + "id": "cirros_vdu_scaling_ns", + "name": "cirros_vdu_scaling_ns", + "description": "Simple NS example with a cirros_vdu_scaling_vnf", + "designer": "OSM", "version": "1.0", + "vnfd-id": ["cirros_vdu_scaling_vnf"], + "df": [{ + "id": "default-df", + "vnf-profile": [ + { + "id": "1", + "vnfd-id": "cirros_vdu_scaling_vnf", + "virtual-link-connectivity": [{ + "virtual-link-profile-id": "cirros_nsd_vld1", + "constituent-cpd-id": [{ + "constituent-base-element-id": "1", + "constituent-cpd-id": "eth0-ext" + }] + }] + }, { + "id": "2", + "vnfd-id": "cirros_vdu_scaling_vnf", + "virtual-link-connectivity": [{ + "virtual-link-profile-id": "cirros_nsd_vld1", + "constituent-cpd-id": [{ + "constituent-base-element-id": "2", + "constituent-cpd-id": "eth0-ext" + }] + }] + } + ] + }], + "virtual-link-desc": [{ + "id": "cirros_nsd_vld1", "mgmt-network": "true" + }] }, "id": "87776f33-b67c-417a-8119-cb08e4098951", "config-status": "configured", @@ -264,163 +261,171 @@ vnfr_record_mocks = [ } ]}] -nsd_record_mock = {'name': 'cirros_vdu_scaling_ns', - 'version': '1.0', - 'short-name': 'cirros_vdu_scaling_ns', - 'logo': 'osm.png', - 'id': 'cirros_vdu_scaling_ns', - 'description': 'Simple NS example with a cirros_vdu_scaling_vnf', - 'vendor': 'OSM', - 'vld': [ - {'name': 'cirros_nsd_vld1', - 'type': 'ELAN', - 'id': 'cirros_nsd_vld1', - 'mgmt-network': 'true', - 'vnfd-connection-point-ref': [ - {'vnfd-id-ref': 'cirros_vdu_scaling_vnf', - 'vnfd-connection-point-ref': 'eth0', - 'member-vnf-index-ref': 1}, - {'vnfd-id-ref': 'cirros_vdu_scaling_vnf', - 'vnfd-connection-point-ref': 'eth0', - 'member-vnf-index-ref': 2}]}], - 'constituent-vnfd': [{'vnfd-id-ref': 'cirros_vdu_scaling_vnf', - 'member-vnf-index': '1'}, - {'vnfd-id-ref': 'cirros_vdu_scaling_vnf', - 'member-vnf-index': '2'}]} +nsd_record_mock = { + 'id': 'cirros_vdu_scaling_ns', + 'name': 'cirros_vdu_scaling_ns', + 'description': 'Simple NS example with a cirros_vdu_scaling_vnf', + 'designer': 'OSM', + 'version': '1.0', + 'vnfd-id': ['cirros_vdu_scaling_vnf'], + 'df': [{ + 'id': 'default-df', + 'vnf-profile': [ + { + 'id': '1', + 'vnfd-id': 'cirros_vdu_scaling_vnf', + 'virtual-link-connectivity': [{ + 'virtual-link-profile-id': 'cirros_nsd_vld1', + 'constituent-cpd-id': [{ + 'constituent-base-element-id': '1', + 'constituent-cpd-id': 'eth0-ext' + }] + }] + }, { + 'id': '2', + 'vnfd-id': 'cirros_vdu_scaling_vnf', + 'virtual-link-connectivity': [{ + 'virtual-link-profile-id': 'cirros_nsd_vld1', + 'constituent-cpd-id': [{ + 'constituent-base-element-id': '2', + 'constituent-cpd-id': 'eth0-ext' + }] + }] + } + ] + }], + 'virtual-link-desc': [{ + 'id': 'cirros_nsd_vld1', + 'mgmt-network': 'true' + }] +} + vnfd_record_mock = { + 'id': 'cirros_vdu_scaling_vnf', "_id": "63f44c41-45ee-456b-b10d-5f08fb1796e0", - "name": "cirros_vdu_scaling_vnf", - "vendor": "OSM", - "vdu": [ - { - "name": "cirros_vnfd-VM", - "monitoring-param": [ - { - "id": "cirros_vnfd-VM_memory_util", - "nfvi-metric": "average_memory_utilization" - } - ], - "vm-flavor": { - "vcpu-count": 1, - "memory-mb": 256, - "storage-gb": 2 - }, - "description": "cirros_vnfd-VM", - "count": 1, - "id": "cirros_vnfd-VM", - "interface": [ - { - "name": "eth0", - "external-connection-point-ref": "eth0", - "type": "EXTERNAL", - "virtual-interface": { - "bandwidth": "0", - "type": "VIRTIO", - "vpci": "0000:00:0a.0" - } - } - ], - "image": "cirros034", - "alarm": [ - { - "value": 20.0000, - "actions": { - "insufficient-data": [ - { - "url": "localhost:9090" - } - ], - "ok": [ - { - "url": "localhost:9090" - } - ], - "alarm": [ - { - "url": "localhost:9090" - } - ] - }, - "alarm-id": "alarm-1", - "operation": "LT", - "vnf-monitoring-param-ref": "cirros_vnf_memory_util" - } - ] + 'product-name': 'cirros_vdu_scaling_vnf', + 'description': 'Simple VNF example with a cirros and a scaling group descriptor', + 'provider': 'OSM', + 'version': '1.0', + 'mgmt-cp': 'eth0-ext', + 'virtual-storage-desc': [{ + 'id': 'cirros_vnfd-VM-storage', + 'size-of-storage': 2 + }], + 'virtual-compute-desc': [{ + 'id': 'cirros_vnfd-VM-compute', + 'virtual-cpu': { + 'num-virtual-cpu': 1 + }, + 'virtual-memory': { + 'size': 0.25 } - ], - "monitoring-param": [ - { - "id": "cirros_vnf_memory_util", - "name": "cirros_vnf_memory_util", - "aggregation-type": "AVERAGE", - "vdu-monitoring-param": { - "vdu-monitoring-param-ref": "cirros_vnfd-VM_memory_util", - "vdu-ref": "cirros_vnfd-VM" + }], + 'sw-image-desc': [{ + 'id': 'cirros034', + 'name': 'cirros034', + 'image': 'cirros034' + }], + 'vdu': [{ + 'id': 'cirros_vnfd-VM', + 'description': 'cirros_vnfd-VM', + 'name': 'cirros_vnfd-VM', + 'alarm': [{ + 'value': 20.0, + 'actions': { + 'insufficient-data': [{ + 'url': 'localhost:9090' + }], + 'ok': [{ + 'url': 'localhost:9090' + }], + 'alarm': [{ + 'url': 'localhost:9090' + }] + }, + 'alarm-id': 'alarm-1', + 'operation': 'LT', + 'vnf-monitoring-param-ref': 'cirros_vnf_memory_util' + }], + 'sw-image-desc': 'cirros034', + 'virtual-compute-desc': 'cirros_vnfd-VM-compute', + 'virtual-storage-desc': ['cirros_vnfd-VM-storage'], + 'int-cpd': [{ + 'id': 'eth0-int', + 'virtual-network-interface-requirement': [{ + 'name': 'eth0', + 'virtual-interface': { + 'bandwidth': '0', + 'type': 'VIRTIO', + 'vpci': '0000:00:0a.0'} + }] + }], + 'monitoring-parameter': [{ + 'id': 'cirros_vnf_memory_util', + 'name': 'cirros_vnf_memory_util', + 'performance-metric': 'average_memory_utilization' + }] + }], + 'df': [{ + 'id': 'default-df', + 'vdu-profile': [{ + 'id': 'cirros_vnfd-VM', + 'min-number-of-instances': 1, + 'max-number-of-instances': 10, + 'vdu-configuration-id': 'cirros_vnfd-VM-vdu-configuration' + }], + 'instantiation-level': [{ + 'id': 'default-instantiation-level', + 'vdu-level': [{ + 'vdu-id': 'cirros_vnfd-VM', + 'number-of-instances': 1}] + }], + 'scaling-aspect': [{ + 'id': 'scale_cirros_vnfd-VM', + 'name': 'scale_cirros_vnfd-VM', + 'max-scale-level': 10, + 'scaling-policy': [{ + 'name': 'auto_memory_util_above_threshold', + 'scaling-type': 'automatic', + 'cooldown-time': 60, + 'threshold-time': 10, + 'scaling-criteria': [{ + 'name': 'group1_memory_util_above_threshold', + 'vnf-monitoring-param-ref': 'cirros_vnf_memory_util', + 'scale-out-threshold': 80, + 'scale-out-relational-operation': 'GT', + 'scale-in-relational-operation': 'LT', + 'scale-in-threshold': 20 + }] + }], + 'aspect-delta-details': { + 'deltas': [{ + 'id': 'scale_cirros_vnfd-VM-delta', + 'vdu-delta': [{ + 'number-of-instances': 1, + 'id': 'cirros_vnfd-VM'}] + }] } - }, - { - "id": "haproxy_users", - "name": "haproxy_users", - "aggregation-type": "AVERAGE", - "vnf-metric": - {"vnf-metric-name-ref": "users"} + }] + }], + 'ext-cpd': [{ + 'id': 'eth0-ext', + 'int-cpd': { + 'vdu-id': 'cirros_vnfd-VM', + 'cpd': 'eth0-int' } - ], - "vdu-configuration": { - "juju": { - "charm": "testmetrics", - "proxy": True + }], + 'vdu-configuration': [{ + 'juju': { + 'charm': 'testmetrics', + 'proxy': True }, - "metrics": { - "name": "users" - } - }, - "description": "Simple VNF example with a cirros and a scaling group descriptor", - "id": "cirros_vdu_scaling_vnf", - "logo": "cirros-64.png", - "version": "1.0", - "connection-point": [ - { - "name": "eth0", - "type": "VPORT" - } - ], - "mgmt-interface": { - "cp": "eth0" - }, - "scaling-group-descriptor": [ - { - "name": "scale_cirros_vnfd-VM", - "min-instance-count": 1, - "vdu": [ - { - "count": 1, - "vdu-id-ref": "cirros_vnfd-VM" - } - ], - "max-instance-count": 10, - "scaling-policy": [ - { - "name": "auto_memory_util_above_threshold", - "scaling-type": "automatic", - "cooldown-time": 60, - "threshold-time": 10, - "scaling-criteria": [ - { - "name": "group1_memory_util_above_threshold", - "vnf-monitoring-param-ref": "cirros_vnf_memory_util", - "scale-out-threshold": 80, - "scale-out-relational-operation": "GT", - "scale-in-relational-operation": "LT", - "scale-in-threshold": 20 - } - ] - } - ] - } - ], - "short-name": "cirros_vdu_scaling_vnf", + 'metrics': [{ + 'name': 'users' + }], + 'id': 'cirros_vnfd-VM-vdu-configuration' + }], "_admin": { "created": 1535392242.6281035, "modified": 1535392242.6281035, @@ -500,28 +505,24 @@ class PolicyModuleAgentTest(unittest.TestCase): create_alarm.assert_any_call(metric_name='average_memory_utilization', ns_id='test_nsr_id', operation='GT', - statistic='AVERAGE', threshold=80, vdu_name='cirros_ns-1-cirros_vnfd-VM-1', vnf_member_index='1') create_alarm.assert_not_called_with(metric_name='average_memory_utilization', ns_id='test_nsr_id', operation='LT', - statistic='AVERAGE', threshold=20, vdu_name='cirros_ns-1-cirros_vnfd-VM-1', vnf_member_index='1') create_alarm.assert_any_call(metric_name='average_memory_utilization', ns_id='test_nsr_id', operation='GT', - statistic='AVERAGE', threshold=80, vdu_name='cirros_ns-2-cirros_vnfd-VM-1', vnf_member_index='2') create_alarm.assert_not_called_with(metric_name='average_memory_utilization', ns_id='test_nsr_id', operation='LT', - statistic='AVERAGE', threshold=20, vdu_name='cirros_ns-2-cirros_vnfd-VM-1', vnf_member_index='2') @@ -558,15 +559,13 @@ class PolicyModuleAgentTest(unittest.TestCase): vdu_name='cirros_ns-1-cirros_vnfd-VM-1', vnf_member_index='1', threshold=20.0, - operation='LT', - statistic='AVERAGE') + operation='LT') create_alarm.assert_any_call(metric_name='average_memory_utilization', ns_id='test_nsr_id', vdu_name='cirros_ns-2-cirros_vnfd-VM-1', vnf_member_index='2', threshold=20.0, - operation='LT', - statistic='AVERAGE') + operation='LT') if __name__ == '__main__': diff --git a/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_nsd.yaml b/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_nsd.yaml index a9e0abd..dd62f1a 100644 --- a/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_nsd.yaml +++ b/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_nsd.yaml @@ -1,42 +1,56 @@ -nsd:nsd-catalog: - nsd: - - id: cirros_vdu_scaling_ns - name: cirros_vdu_scaling_ns - short-name: cirros_vdu_scaling_ns - description: Simple NS example with a cirros_vdu_scaling_vnf - vendor: OSM - version: '1.0' - - # Place the logo as png in icons directory and provide the name here - logo: osm.png - - # Specify the VNFDs that are part of this NSD - constituent-vnfd: - # The member-vnf-index needs to be unique, starting from 1 - # vnfd-id-ref is the id of the VNFD - # Multiple constituent VNFDs can be specified - - member-vnf-index: '1' - vnfd-id-ref: cirros_vdu_scaling_vnf - - member-vnf-index: '2' - vnfd-id-ref: cirros_vdu_scaling_vnf - vld: - # Networks for the VNFs - - id: cirros_nsd_vld1 - name: cirros_nsd_vld1 - type: ELAN - mgmt-network: 'true' - # vim-network-name: - # provider-network: - # segmentation_id: - vnfd-connection-point-ref: - # Specify the constituent VNFs - # member-vnf-index-ref - entry from constituent vnf - # vnfd-id-ref - VNFD id - # vnfd-connection-point-ref - connection point name in the VNFD - - member-vnf-index-ref: 1 - vnfd-id-ref: cirros_vdu_scaling_vnf - # NOTE: Validate the entry below - vnfd-connection-point-ref: eth0 - - member-vnf-index-ref: 2 - vnfd-id-ref: cirros_vdu_scaling_vnf - vnfd-connection-point-ref: eth0 \ No newline at end of file +# -*- coding: utf-8 -*- +# pylint: disable=no-member + +# Copyright 2020 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: agarcia@whitestack.com +## + +nsd: + nsd: + - id: cirros_vdu_scaling_ns + name: cirros_vdu_scaling_ns + description: Simple NS example with a cirros_vdu_scaling_vnf + designer: OSM + version: '1.0' + + df: + - id: default-df + vnf-profile: + - id: '1' + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: '1' + constituent-cpd-id: eth0-ext + virtual-link-profile-id: cirros_nsd_vld1 + vnfd-id: cirros_vdu_scaling_vnf + - id: '2' + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: '2' + constituent-cpd-id: eth0-ext + virtual-link-profile-id: cirros_nsd_vld1 + vnfd-id: cirros_vdu_scaling_vnf + + virtual-link-desc: + - id: cirros_nsd_vld1 + mgmt-network: 'true' + vnfd-id: + - cirros_vdu_scaling_vnf diff --git a/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd.yaml b/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd.yaml new file mode 100644 index 0000000..f924d3e --- /dev/null +++ b/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd.yaml @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +# pylint: disable=no-member + +# Copyright 2020 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: agarcia@whitestack.com +## + +vnfd: + id: cirros_vdu_scaling_vnf + product-name: cirros_vdu_scaling_vnf + description: Simple VNF example with a cirros and a scaling group descriptor + provider: OSM + version: '1.0' + mgmt-cp: eth0-ext + + ext-cpd: + - id: eth0-ext + int-cpd: + cpd: eth0-int + vdu-id: cirros_vnfd-VM + + df: + - id: default-df + instantiation-level: + - id: default-instantiation-level + vdu-level: + - number-of-instances: 1 + vdu-id: cirros_vnfd-VM + scaling-aspect: + - id: scale_cirros_vnfd-VM + name: scale_cirros_vnfd-VM + aspect-delta-details: + deltas: + - id: scale_cirros_vnfd-VM-delta + vdu-delta: + - id: cirros_vnfd-VM + number-of-instances: 1 + max-scale-level: 10 + scaling-policy: + - name: auto_cpu_util_above_threshold + cooldown-time: 60 + scaling-criteria: + - name: group1_cpu_util_above_threshold + scale-in-relational-operation: LT + scale-in-threshold: 20 + scale-out-relational-operation: GT + scale-out-threshold: 80 + vnf-monitoring-param-ref: cirros_vnf_cpu_util + scaling-type: automatic + threshold-time: 10 + vdu-profile: + - id: cirros_vnfd-VM + max-number-of-instances: 10 + min-number-of-instances: 1 + + vdu: + - id: cirros_vnfd-VM + name: cirros_vnfd-VM + description: cirros_vnfd-VM + int-cpd: + - id: eth0-int + virtual-network-interface-requirement: + - name: eth0 + virtual-interface: + bandwidth: '0' + type: VIRTIO + vpci: 0000:00:0a.0 + monitoring-parameter: + - id: cirros_vnf_cpu_util + name: cirros_vnf_cpu_util + performance-metric: cpu_utilization + sw-image-desc: cirros034 + virtual-compute-desc: cirros_vnfd-VM-compute + virtual-storage-desc: + - cirros_vnfd-VM-storage + + sw-image-desc: + - id: cirros034 + name: cirros034 + image: cirros034 + + virtual-compute-desc: + - id: cirros_vnfd-VM-compute + virtual-cpu: + num-virtual-cpu: 1 + virtual-memory: + size: 0.25 + + virtual-storage-desc: + - id: cirros_vnfd-VM-storage + size-of-storage: 2 diff --git a/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_1.yaml b/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_1.yaml deleted file mode 100644 index a626674..0000000 --- a/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_1.yaml +++ /dev/null @@ -1,75 +0,0 @@ -vnfd:vnfd-catalog: - vnfd: - - id: cirros_vdu_scaling_vnf - name: cirros_vdu_scaling_vnf - short-name: cirros_vdu_scaling_vnf - description: Simple VNF example with a cirros and a scaling group descriptor - vendor: OSM - version: '1.0' - # Place the logo as png in icons directory and provide the name here - logo: cirros-64.png - # Management interface - mgmt-interface: - cp: eth0 - # Atleast one VDU need to be specified - vdu: - - id: cirros_vnfd-VM - name: cirros_vnfd-VM - description: cirros_vnfd-VM - count: 1 - - # Flavour of the VM to be instantiated for the VDU - # flavor below can fit into m1.micro - vm-flavor: - vcpu-count: 1 - memory-mb: 256 - storage-gb: 2 - # Image/checksum or image including the full path - image: 'cirros034' - #checksum: - interface: - # Specify the external interfaces - # There can be multiple interfaces defined - - name: eth0 - type: EXTERNAL - virtual-interface: - type: VIRTIO - bandwidth: '0' - vpci: 0000:00:0a.0 - external-connection-point-ref: eth0 - monitoring-param: - - id: "cirros_vnfd-VM_cpu_util" - nfvi-metric: "cpu_utilization" # The associated NFVI metric to be monitored. Id of the metric - #interface-name-ref: reference to interface name, required for some metrics - connection-point: - - name: eth0 - type: VPORT - scaling-group-descriptor: - - name: "scale_cirros_vnfd-VM" - min-instance-count: 1 - max-instance-count: 10 - scaling-policy: - - name: "auto_cpu_util_above_threshold" - scaling-type: "automatic" - threshold-time: 10 - cooldown-time: 60 - scaling-criteria: - - name: "group1_cpu_util_above_threshold" - scale-in-threshold: 20 - scale-in-relational-operation: "LT" - scale-out-threshold: 80 - scale-out-relational-operation: "GT" - vnf-monitoring-param-ref: "cirros_vnf_cpu_util" - vdu: - - vdu-id-ref: cirros_vnfd-VM - count: 1 - # scaling-config-action: # Para utilizar charms - # - trigger: post-scale-out - # vnf-config-primitive-name-ref: - monitoring-param: - - id: "cirros_vnf_cpu_util" - name: "cirros_vnf_cpu_util" - aggregation-type: AVERAGE - vdu-monitoring-param: - vdu-ref: "cirros_vnfd-VM" - vdu-monitoring-param-ref: "cirros_vnfd-VM_cpu_util" \ No newline at end of file diff --git a/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_2.yaml b/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_2.yaml deleted file mode 100644 index 8e0c603..0000000 --- a/osm_policy_module/tests/unit/utils/examples/cirros_vdu_scaling_vnfd_2.yaml +++ /dev/null @@ -1,75 +0,0 @@ -vnfd:vnfd-catalog: - vnfd: - - id: cirros_vdu_scaling_vnf - name: cirros_vdu_scaling_vnf - short-name: cirros_vdu_scaling_vnf - description: Simple VNF example with a cirros and a scaling group descriptor - vendor: OSM - version: '1.0' - # Place the logo as png in icons directory and provide the name here - logo: cirros-64.png - # Management vdu id - mgmt-interface: - vdu-id: cirros_vnfd-VM - # Atleast one VDU need to be specified - vdu: - - id: cirros_vnfd-VM - name: cirros_vnfd-VM - description: cirros_vnfd-VM - count: 1 - - # Flavour of the VM to be instantiated for the VDU - # flavor below can fit into m1.micro - vm-flavor: - vcpu-count: 1 - memory-mb: 256 - storage-gb: 2 - # Image/checksum or image including the full path - image: 'cirros034' - #checksum: - interface: - # Specify the external interfaces - # There can be multiple interfaces defined - - name: eth0 - type: EXTERNAL - virtual-interface: - type: VIRTIO - bandwidth: '0' - vpci: 0000:00:0a.0 - external-connection-point-ref: eth0 - monitoring-param: - - id: "cirros_vnfd-VM_cpu_util" - nfvi-metric: "cpu_utilization" # The associated NFVI metric to be monitored. Id of the metric - #interface-name-ref: reference to interface name, required for some metrics - connection-point: - - name: eth0 - type: VPORT - scaling-group-descriptor: - - name: "scale_cirros_vnfd-VM" - min-instance-count: 1 - max-instance-count: 10 - scaling-policy: - - name: "auto_cpu_util_above_threshold" - scaling-type: "automatic" - threshold-time: 10 - cooldown-time: 60 - scaling-criteria: - - name: "group1_cpu_util_above_threshold" - scale-in-threshold: 20 - scale-in-relational-operation: "LT" - scale-out-threshold: 80 - scale-out-relational-operation: "GT" - vnf-monitoring-param-ref: "cirros_vnf_cpu_util" - vdu: - - vdu-id-ref: cirros_vnfd-VM - count: 1 - # scaling-config-action: # Para utilizar charms - # - trigger: post-scale-out - # vnf-config-primitive-name-ref: - monitoring-param: - - id: "cirros_vnf_cpu_util" - name: "cirros_vnf_cpu_util" - aggregation-type: AVERAGE - vdu-monitoring-param: - vdu-ref: "cirros_vnfd-VM" - vdu-monitoring-param-ref: "cirros_vnfd-VM_cpu_util" \ No newline at end of file diff --git a/osm_policy_module/tests/unit/utils/test_vnfd_utils.py b/osm_policy_module/tests/unit/utils/test_vnfd_utils.py index 5b770dd..049d293 100644 --- a/osm_policy_module/tests/unit/utils/test_vnfd_utils.py +++ b/osm_policy_module/tests/unit/utils/test_vnfd_utils.py @@ -23,23 +23,24 @@ ## import os import unittest - import yaml from osm_policy_module.utils.vnfd import VnfdUtils +from osm_policy_module.core.exceptions import ManagementVduNotFound class VnfdUtilsTest(unittest.TestCase): - def test_get_mgmt_vdu_by_cp(self): - with open( - os.path.join(os.path.dirname(__file__), 'examples/cirros_vdu_scaling_vnfd_1.yaml'), 'r') as file: - vnfd = yaml.safe_load(file)['vnfd:vnfd-catalog']['vnfd'][0] + def test_get_mgmt_vdu_on_valid_descriptor(self): + example_file = os.path.join(os.path.dirname(__file__), 'examples/cirros_vdu_scaling_vnfd.yaml') + with open(example_file, 'r') as file: + vnfd = yaml.safe_load(file)['vnfd'] vdu = VnfdUtils.get_mgmt_vdu(vnfd) self.assertEqual(vdu['id'], 'cirros_vnfd-VM') - def test_get_mgmt_vdu_by_id(self): - with open( - os.path.join(os.path.dirname(__file__), 'examples/cirros_vdu_scaling_vnfd_2.yaml'), 'r') as file: - vnfd = yaml.safe_load(file)['vnfd:vnfd-catalog']['vnfd'][0] - vdu = VnfdUtils.get_mgmt_vdu(vnfd) - self.assertEqual(vdu['id'], 'cirros_vnfd-VM') + def test_get_mgmt_vdu_on_invalid_descriptor(self): + example_file = os.path.join(os.path.dirname(__file__), 'examples/cirros_vdu_scaling_vnfd.yaml') + with open(example_file, 'r') as file: + vnfd = yaml.safe_load(file)['vnfd'] + vnfd['mgmt-cp'] = 'invalid-cp' + with self.assertRaises(ManagementVduNotFound): + VnfdUtils.get_mgmt_vdu(vnfd) diff --git a/osm_policy_module/utils/vnfd.py b/osm_policy_module/utils/vnfd.py index 234d864..0ecbda1 100644 --- a/osm_policy_module/utils/vnfd.py +++ b/osm_policy_module/utils/vnfd.py @@ -28,14 +28,13 @@ class VnfdUtils: @staticmethod def get_mgmt_vdu(vnfd: dict): - if 'cp' in vnfd['mgmt-interface']: - for vdu in vnfd['vdu']: - for interface in vdu['interface']: - if 'external-connection-point-ref' in interface: - if interface['external-connection-point-ref'] == vnfd['mgmt-interface']['cp']: - return vdu - elif 'vdu-id' in vnfd['mgmt-interface']: - for vdu in vnfd['vdu']: - if vdu['id'] == vnfd['mgmt-interface']['vdu-id']: + if 'mgmt-cp' in vnfd: + mgmt_cp = vnfd['mgmt-cp'] + mgmt_cp_vdu_id = None + for cpd in vnfd.get('ext-cpd', ()): + if cpd.get('id') == mgmt_cp: + mgmt_cp_vdu_id = cpd.get('int-cpd', {}).get('vdu-id') + for vdu in vnfd.get('vdu', ()): + if vdu.get('id') == mgmt_cp_vdu_id: return vdu - raise ManagementVduNotFound("Management vdu not founr in vnfd %s", vnfd['id']) + raise ManagementVduNotFound("Management vdu not found in vnfd %s", vnfd['id']) diff --git a/tox.ini b/tox.ini index a8687c6..d3d576e 100644 --- a/tox.ini +++ b/tox.ini @@ -25,7 +25,7 @@ # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. [tox] -envlist = cover, flake8, pylint +envlist = cover, flake8 [testenv] -- 2.17.1