From 9067a2b70d4b763b015aeb3d3efc925fc6cf3f07 Mon Sep 17 00:00:00 2001 From: "Zhang Rong(Jon)" Date: Thu, 13 Jun 2024 23:37:57 +0800 Subject: [PATCH] Update DeploymentManagerInfo attributes The April train release introduced a new spec to expand three attributes of the DeploymentManager. This commit implements these changes, adding the new attributes to the DeploymentManager. Test Plan: 1.Verified that the deployment manager list includes the new attributes by default. 2.Verified that fetching a specific deployment manager responds as expected. Issue-ID: INF-468 Change-Id: I372f01fca970243d4b6421121b469786d5480e61 Signed-off-by: Zhang Rong(Jon) --- o2app/entrypoints/redis_eventconsumer.py | 19 +++++++++++----- o2ims/adapter/clients/fault_client.py | 8 +++---- o2ims/adapter/clients/ocloud_client.py | 20 ++++++++--------- o2ims/adapter/clients/ocloud_sa_client.py | 14 ++++++------ o2ims/domain/alarm_obj.py | 3 ++- o2ims/domain/ocloud.py | 2 ++ o2ims/service/command/notify_handler.py | 32 ++++++++++++++++++++++++++- o2ims/views/ocloud_dto.py | 36 ++++++++++++++++++++----------- 8 files changed, 93 insertions(+), 41 deletions(-) diff --git a/o2app/entrypoints/redis_eventconsumer.py b/o2app/entrypoints/redis_eventconsumer.py index db39daa..8098d04 100644 --- a/o2app/entrypoints/redis_eventconsumer.py +++ b/o2app/entrypoints/redis_eventconsumer.py @@ -23,7 +23,8 @@ from o2common.config import config from o2common.helper import o2logging from o2dms.domain import commands from o2ims.domain import commands as imscmd -from o2ims.domain.subscription_obj import Message2SMO, RegistrationMessage +from o2ims.domain.subscription_obj import Message2SMO, RegistrationMessage, \ + NotificationEventEnum from o2ims.domain.alarm_obj import AlarmEvent2SMO logger = o2logging.get_logger(__name__) @@ -125,9 +126,17 @@ def handle_changed(m, bus): datastr = m['data'] data = json.loads(datastr) logger.info('OcloudChanged with cmd:{}'.format(data)) - cmd = imscmd.Register2SMO(data=RegistrationMessage( - id=data['id'], eventtype=data['notificationEventType'], - updatetime=data['updatetime'])) + if data['notificationEventType'] == NotificationEventEnum.CREATE: + cmd = imscmd.Register2SMO(data=RegistrationMessage( + id=data['id'], eventtype=data['notificationEventType'], + updatetime=data['updatetime'])) + elif data['notificationEventType'] == NotificationEventEnum.MODIFY: + ref = apibase + inventory_api_version + cmd = imscmd.PubMessage2SMO(data=Message2SMO( + id=data['id'], ref=ref, + eventtype=data['notificationEventType'], + updatetime=data['updatetime']), + type='OCloud') bus.handle(cmd) elif channel == 'AlarmEventChanged': datastr = m['data'] @@ -145,7 +154,7 @@ def handle_changed(m, bus): data = json.loads(datastr) logger.info('AlarmEventPurged with cmd:{}'.format(data)) cmd = imscmd.PurgeAlarmEvent(data=AlarmEvent2SMO( - id=data['id'], eventtype=data['notificationEventType'], + id=data['id'], ref="", eventtype=data['notificationEventType'], updatetime=data['updatetime'])) bus.handle(cmd) else: diff --git a/o2ims/adapter/clients/fault_client.py b/o2ims/adapter/clients/fault_client.py index 74abe57..616a4ca 100644 --- a/o2ims/adapter/clients/fault_client.py +++ b/o2ims/adapter/clients/fault_client.py @@ -263,7 +263,7 @@ class StxFaultClientImp(object): self._suppression_converter(event))) return suppression_list - @ staticmethod + @staticmethod def _alarmconverter(alarm): selected_keys = [ 'alarm_id', 'alarm_state', 'entity_type_id', 'entity_instance_id', @@ -285,7 +285,7 @@ class StxFaultClientImp(object): uuid.NAMESPACE_URL, alarm.probable_cause))) return alarm - @ staticmethod + @staticmethod def _eventconverter(event, clear=False): selected_keys = [ 'event_log_id', 'state', 'entity_type_id', @@ -308,7 +308,7 @@ class StxFaultClientImp(object): uuid.NAMESPACE_URL, event.probable_cause))) return event - @ staticmethod + @staticmethod def _suppression_converter(event, clear=False): selected_keys = [ 'alarm_id', 'description', 'suppression_status', @@ -329,7 +329,7 @@ class StxFaultClientImp(object): setattr(event, 'timestamp', None) return event - @ staticmethod + @staticmethod def _alarmeventhasher(event, state=''): # The event model and the alarm model have different parameter name # of the state. alarm model is alarm_state, event model is state. diff --git a/o2ims/adapter/clients/ocloud_client.py b/o2ims/adapter/clients/ocloud_client.py index 5a7b3fb..f601bbc 100644 --- a/o2ims/adapter/clients/ocloud_client.py +++ b/o2ims/adapter/clients/ocloud_client.py @@ -591,12 +591,12 @@ class StxClientImp(object): 'more than one system exists in the account.') return isystems[0] - @ staticmethod + @staticmethod def _respoolconverter(res_pool): setattr(res_pool, 'name', res_pool.region_name) return res_pool - @ staticmethod + @staticmethod def _hostconverter(host): selected_keys = [ "hostname", "personality", "id", "mgmt_ip", "mgmt_mac", @@ -612,7 +612,7 @@ class StxClientImp(object): setattr(host, 'name', host.hostname) return host - @ staticmethod + @staticmethod def _labelconverter(label): selected_keys = [ "uuid", "label_key", "label_value", "host_uuid" @@ -628,7 +628,7 @@ class StxClientImp(object): setattr(label, 'created_at', None) return label - @ staticmethod + @staticmethod def _cpuconverter(cpu): selected_keys = [ "cpu", "core", "thread", "allocated_function", "numa_node", @@ -642,7 +642,7 @@ class StxClientImp(object): '-', 1)[0] + '-cpu-'+str(cpu.cpu)) return cpu - @ staticmethod + @staticmethod def _memconverter(mem): selected_keys = [ "memtotal_mib", "memavail_mib", "vm_hugepages_use_1G", @@ -660,7 +660,7 @@ class StxClientImp(object): '-mem-node-'+str(mem.numa_node)) return mem - @ staticmethod + @staticmethod def _ethconverter(eth): selected_keys = [ "name", "namedisplay", "dev_id", "pdevice", "capabilities", @@ -678,7 +678,7 @@ class StxClientImp(object): setattr(eth, 'created_at', None) return eth - @ staticmethod + @staticmethod def _ifconverter(ifs): selected_keys = [ "ifname", "iftype", "imac", "vlan_id", "imtu", @@ -694,7 +694,7 @@ class StxClientImp(object): setattr(ifs, 'created_at', None) return ifs - @ staticmethod + @staticmethod def _devconverter(dev): selected_keys = [ "name", "pdevice", "pciaddr", "pvendor_id", "pvendor", @@ -708,7 +708,7 @@ class StxClientImp(object): setattr(dev, 'name', dev.host_uuid.split('-', 1)[0] + '-'+dev.name) return dev - @ staticmethod + @staticmethod def _k8sconverter(cluster): setattr(cluster, 'name', cluster.cloud_name + '.' + cluster.cluster_name) @@ -721,7 +721,7 @@ class StxClientImp(object): cluster.name + '/' + str(cluster.uuid)) return cluster - @ staticmethod + @staticmethod def _k8shasher(cluster): return str(hash((cluster.cluster_name, cluster.cloud_name, cluster.cluster_api_endpoint, cluster.admin_user, diff --git a/o2ims/adapter/clients/ocloud_sa_client.py b/o2ims/adapter/clients/ocloud_sa_client.py index 81ba817..aacb6be 100644 --- a/o2ims/adapter/clients/ocloud_sa_client.py +++ b/o2ims/adapter/clients/ocloud_sa_client.py @@ -270,38 +270,38 @@ class StxSaClientImp(object): 'more than one system exists in the account.') return isystems[0] - @ staticmethod + @staticmethod def _hostconverter(host): setattr(host, 'name', host.hostname) return host - @ staticmethod + @staticmethod def _cpuconverter(cpu): setattr(cpu, 'name', cpu.ihost_uuid.split( '-', 1)[0] + '-cpu-'+str(cpu.cpu)) return cpu - @ staticmethod + @staticmethod def _memconverter(mem): setattr(mem, 'name', mem.ihost_uuid.split('-', 1)[0] + '-mem-node-'+str(mem.numa_node)) return mem - @ staticmethod + @staticmethod def _ethconverter(eth): setattr(eth, 'name', eth.host_uuid.split('-', 1)[0] + '-'+eth.name) setattr(eth, 'updated_at', None) setattr(eth, 'created_at', None) return eth - @ staticmethod + @staticmethod def _ifconverter(ifs): setattr(ifs, 'name', ifs.ihost_uuid.split('-', 1)[0] + '-'+ifs.ifname) setattr(ifs, 'updated_at', None) setattr(ifs, 'created_at', None) return ifs - @ staticmethod + @staticmethod def _k8sconverter(cluster): setattr(cluster, 'name', cluster.cluster_name) setattr(cluster, 'uuid', @@ -313,7 +313,7 @@ class StxSaClientImp(object): cluster.name + '/' + str(cluster.uuid)) return cluster - @ staticmethod + @staticmethod def _k8shasher(cluster): return str(hash((cluster.cluster_name, cluster.cluster_api_endpoint, cluster.admin_user))) diff --git a/o2ims/domain/alarm_obj.py b/o2ims/domain/alarm_obj.py index 800c6d7..c0f9f17 100644 --- a/o2ims/domain/alarm_obj.py +++ b/o2ims/domain/alarm_obj.py @@ -178,9 +178,10 @@ class AlarmNotificationEventEnum(str, Enum): class AlarmEvent2SMO(Serializer): def __init__(self, eventtype: AlarmNotificationEventEnum, - id: str, updatetime: str) -> None: + id: str, ref: str, updatetime: str) -> None: self.notificationEventType = eventtype self.id = id + self.objectRef = ref self.updatetime = updatetime diff --git a/o2ims/domain/ocloud.py b/o2ims/domain/ocloud.py index ce46e96..23e9122 100644 --- a/o2ims/domain/ocloud.py +++ b/o2ims/domain/ocloud.py @@ -66,6 +66,8 @@ class DeploymentManager(InfrastructureInventoryObject, AgRoot, Serializer): if 'capabilities' in d and d['capabilities'] != '': d['capabilities'] = json.loads(d['capabilities']) + if 'capacity' in d and d['capacity'] != '': + d['capacity'] = json.loads(d['capacity']) return d def get_notification_dict(self): diff --git a/o2ims/service/command/notify_handler.py b/o2ims/service/command/notify_handler.py index 88a0e90..6fd0bb2 100644 --- a/o2ims/service/command/notify_handler.py +++ b/o2ims/service/command/notify_handler.py @@ -48,6 +48,8 @@ def notify_change_to_smo( _notify_dms(uow, notifications, cmd.data) elif msg_type == 'Resource': _notify_resource(uow, notifications, cmd.data) + elif msg_type == 'OCloud': + _notify_ocloud(uow, notifications, cmd.data) def __get_object_type_and_value(sub_filter): @@ -61,7 +63,6 @@ def __get_object_type_and_value(sub_filter): def handle_filter(filter: str, f_type: str): - print(filter) if not filter: return @@ -189,6 +190,35 @@ def _notify_dms(uow, notifications, data): .format(sub_data['subscriptionId'], data.id)) +def _notify_ocloud(uow, notifications, data): + with uow: + ocloud = uow.oclouds.get(data.id) + if ocloud is None: + logger.warning( + 'oCloud {} does not exists.'.format(data.id)) + return + + ocloud_dict = ocloud.get_notification_dict() + + subs = uow.subscriptions.list() + for sub in subs: + sub_data = sub.serialize() + logger.debug('Subscription: {}'.format(sub_data['subscriptionId'])) + filters = handle_filter( + sub_data['filter'], 'CloudInfo') + logger.debug(f'filters: {filters}, sub_data: {sub_data}') + + if not filters or filters[0] == 0 or check_filters( + filters, sub_data, uow.oclouds, + ocloud.Ocloud, + ocloud.Ocloud.oCloudId, data.id): + callback_smo(notifications, sub, data, ocloud_dict) + continue + + logger.info('Subscription {} filter hit, skip Cloud {}.' + .format(sub_data['subscriptionId'], data.id)) + + def _notify_resource(uow, notifications, data): with uow: resource = uow.resources.get(data.id) diff --git a/o2ims/views/ocloud_dto.py b/o2ims/views/ocloud_dto.py index f283ca0..7d1b8f6 100644 --- a/o2ims/views/ocloud_dto.py +++ b/o2ims/views/ocloud_dto.py @@ -89,11 +89,11 @@ class OcloudDTO: # 'smoRegistrationService': fields.String 'extensions': fields.String( example='', - description='These are unspecified (not standardized) ' +\ - 'properties (keys) which are tailored by the vendor ' +\ + description='These are unspecified (not standardized) ' + + 'properties (keys) which are tailored by the vendor ' + 'to extend the information provided about the O-Cloud.'), }, - mask='{oCloudId,globalCloudId,globalcloudId,name,description,' +\ + mask='{oCloudId,globalCloudId,globalcloudId,name,description,' + 'serviceUri}' ) @@ -264,9 +264,9 @@ class ResourcePoolDTO: # 'resources': fields.String, 'extensions': fields.String( example='', - description='List of metadata key-value pairs ' +\ - 'used to associate meaningful metadata to ' +\ - 'the related resource pool.') + description=('List of metadata key-value pairs ' + 'used to associate meaningful metadata to ' + 'the related resource pool.')) }, mask='{resourcePoolId,oCloudId,globalLocationId,name,description}' ) @@ -367,6 +367,14 @@ class DeploymentManagerDTO: 'the Deployment Manager'), }) + capacity = api_ims_inventory_v1.model( + "DeploymentManagerCapacity", { + 'OS': fields.String( + example='low_latency', + description='Show the OS capacity of ' + + 'the Deployment Manager'), + }) + deployment_manager_list = api_ims_inventory_v1.model( "DeploymentManagerListDto", { @@ -389,11 +397,12 @@ class DeploymentManagerDTO: example='https://128.224.115.51:6443', description='The fully qualified URI to a Deployment ' + 'Management server for O2dms.'), + # Comment for the future implementation # 'deploymentManagementServiceEndpoint': fields.String( # attribute='serviceUri'), - # 'supportedLocations': fields.String, + 'supportedLocations': fields.String, 'capabilities': fields.Nested(capabilities, True, True), - # 'capacity': fields.String, + 'capacity': fields.Nested(capacity, True, True), 'profileSupportList': fields.List( fields.String, example=['native_k8sapi'], @@ -405,8 +414,8 @@ class DeploymentManagerDTO: 'associate meaningful metadata to the related Deployment ' + 'Manager'), }, - mask='{deploymentManagerId,name,description,oCloudId,serviceUri,' + \ - 'profileSupportList}' + mask='{deploymentManagerId,name,description,oCloudId,serviceUri,' + + 'supportedLocations,capabilities,capacity,profileSupportList}' ) profile = api_ims_inventory_v1.model("DeploymentManagerGetDtoProfile", { @@ -480,12 +489,13 @@ class DeploymentManagerDTO: 'Management server for O2dms.'), # 'deploymentManagementServiceEndpoint': fields.String( # attribute='serviceUri'), - # 'supportedLocations': fields.String, + 'supportedLocations': fields.String, 'capabilities': fields.Nested(capabilities, True, True), - # 'capacity': fields.String, + 'capacity': fields.Nested(capacity, True, True), 'extensions': fields.Nested(extensions, True, True) }, - mask='{deploymentManagerId,name,description,oCloudId,serviceUri,' +\ + mask='{deploymentManagerId,name,description,oCloudId,serviceUri,' + + 'supportedLocations,capabilities,capacity,' + 'extensions{profileName,profileData}}' ) -- 2.16.6