Update DeploymentManagerInfo attributes 62/12962/3
authorZhang Rong(Jon) <rong.zhang@windriver.com>
Thu, 13 Jun 2024 15:37:57 +0000 (23:37 +0800)
committerZhang Rong(Jon) <rong.zhang@windriver.com>
Thu, 20 Jun 2024 04:01:36 +0000 (12:01 +0800)
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) <rong.zhang@windriver.com>
o2app/entrypoints/redis_eventconsumer.py
o2ims/adapter/clients/fault_client.py
o2ims/adapter/clients/ocloud_client.py
o2ims/adapter/clients/ocloud_sa_client.py
o2ims/domain/alarm_obj.py
o2ims/domain/ocloud.py
o2ims/service/command/notify_handler.py
o2ims/views/ocloud_dto.py

index db39daa..8098d04 100644 (file)
@@ -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:
index 74abe57..616a4ca 100644 (file)
@@ -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.
index 5a7b3fb..f601bbc 100644 (file)
@@ -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,
index 81ba817..aacb6be 100644 (file)
@@ -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)))
index 800c6d7..c0f9f17 100644 (file)
@@ -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
 
 
index ce46e96..23e9122 100644 (file)
@@ -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):
index 88a0e90..6fd0bb2 100644 (file)
@@ -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)
index f283ca0..7d1b8f6 100644 (file)
@@ -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}}'
     )