[PMSH] Update filter
[dcaegen2/services.git] / components / pm-subscription-handler / pmsh_service / mod / subscription.py
index fdc1394..9e721c5 100755 (executable)
@@ -15,6 +15,7 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 # ============LICENSE_END=====================================================
+import json
 from enum import Enum
 
 from mod import db, logger
@@ -34,6 +35,7 @@ class AdministrativeState(Enum):
     UNLOCKED = 'UNLOCKED'
     LOCKING = 'LOCKING'
     LOCKED = 'LOCKED'
+    FILTERING = 'FILTERING'
 
 
 subscription_nf_states = {
@@ -48,6 +50,10 @@ subscription_nf_states = {
     AdministrativeState.LOCKING.value: {
         'success': SubNfState.DELETED,
         'failed': SubNfState.DELETE_FAILED
+    },
+    AdministrativeState.FILTERING.value: {
+        'success': SubNfState.DELETED,
+        'failed': SubNfState.DELETE_FAILED
     }
 }
 
@@ -61,6 +67,27 @@ def _get_nf_objects(nf_sub_relationships):
     return nfs
 
 
+def get_nfs_for_creation_and_deletion(existing_nfs, new_nfs, action, mrpub, app_conf):
+    """ Finds new/old nfs for creation/deletion from subscription    """
+    for existing_nf in existing_nfs:
+        _compare_nfs(action, app_conf, existing_nf, mrpub, new_nfs)
+
+
+def _compare_nfs(action, app_conf, existing_nf, mrpub, new_nfs):
+    """ Compares old nfs list to existing nfs list"""
+    for new_nf in new_nfs:
+        if existing_nf.nf_name != new_nf.nf_name:
+            _apply_action_to_nfs(action, app_conf, existing_nf, mrpub, new_nf)
+
+
+def _apply_action_to_nfs(action, app_conf, existing_nf, mrpub, new_nf):
+    """ Performs create/delete of nf from subscription as required"""
+    if action == 'create':
+        app_conf.subscription.create_subscription_on_nfs([new_nf], mrpub, app_conf)
+    elif action == 'delete':
+        app_conf.subscription.delete_subscription_from_nfs([existing_nf], mrpub, app_conf)
+
+
 class Subscription:
     def __init__(self, **kwargs):
         self.subscriptionName = kwargs.get('subscriptionName')
@@ -83,30 +110,58 @@ class Subscription:
         Returns:
             Subscription object
         """
+        existing_subscription = (SubscriptionModel.query.filter(
+            SubscriptionModel.subscription_name == self.subscriptionName).one_or_none())
+        if existing_subscription is None:
+            return self.create_new_sub()
+        else:
+            if existing_subscription.nfFilter and \
+                    self._filter_diff(existing_subscription.nfFilter) and \
+                    existing_subscription.status == AdministrativeState.UNLOCKED.value:
+                return self.update_existing_sub(existing_subscription)
+
+    def update_existing_sub(self, existing_subscription):
+        """Update subscription status
+
+        Args:
+            existing_subscription: the current subscription
+
+        Returns:
+            Subscription: updated subscription
+        """
+        self.administrativeState = \
+            AdministrativeState.FILTERING.value
+        self.nfFilter = existing_subscription.nfFilter
+        self.update_subscription_status()
+        logger.debug(f'Subscription {self.subscriptionName} already exists,'
+                     f' returning this subscription..')
+        return existing_subscription
+
+    def create_new_sub(self):
         try:
-            existing_subscription = (SubscriptionModel.query.filter(
-                SubscriptionModel.subscription_name == self.subscriptionName).one_or_none())
-            if existing_subscription is None:
-                new_subscription = SubscriptionModel(subscription_name=self.subscriptionName,
-                                                     status=AdministrativeState.LOCKED.value)
-                db.session.add(new_subscription)
-                db.session.commit()
-                return new_subscription
-            else:
-                logger.debug(f'Subscription {self.subscriptionName} already exists,'
-                             f' returning this subscription..')
-                return existing_subscription
+            new_subscription = SubscriptionModel(subscription_name=self.subscriptionName,
+                                                 nfFilter=self.nfFilter,
+                                                 status=AdministrativeState.LOCKED.value)
+            db.session.add(new_subscription)
+            db.session.commit()
+            return new_subscription
         except Exception as e:
             logger.error(f'Failed to create subscription {self.subscriptionName} in the DB: {e}',
                          exc_info=True)
         finally:
             db.session.remove()
 
+    def _filter_diff(self, existing_subscription_filter):
+        existing_subscription_filter, nf_filter = \
+            json.dumps(existing_subscription_filter, sort_keys=True), \
+            json.dumps(self.nfFilter, sort_keys=True)
+        return existing_subscription_filter != nf_filter
+
     def update_subscription_status(self):
         """ Updates the status of subscription in subscription table """
         try:
             SubscriptionModel.query.filter(
-                SubscriptionModel.subscription_name == self.subscriptionName)\
+                SubscriptionModel.subscription_name == self.subscriptionName) \
                 .update({SubscriptionModel.status: self.administrativeState},
                         synchronize_session='evaluate')
 
@@ -117,6 +172,21 @@ class Subscription:
         finally:
             db.session.remove()
 
+    def update_subscription_filter(self):
+        """ Updates the filter of subscription in subscription table """
+        try:
+            SubscriptionModel.query.filter(
+                SubscriptionModel.subscription_name == self.subscriptionName) \
+                .update({SubscriptionModel.nfFilter: self.nfFilter},
+                        synchronize_session='evaluate')
+
+            db.session.commit()
+        except Exception as e:
+            logger.error(f'Failed to update status of subscription: {self.subscriptionName}: {e}',
+                         exc_info=True)
+        finally:
+            db.session.remove()
+
     def prepare_subscription_event(self, nf, app_conf):
         """Prepare the sub event for publishing
 
@@ -128,13 +198,14 @@ class Subscription:
             dict: the Subscription event to be published.
         """
         try:
-            clean_sub = {k: v for k, v in self.__dict__.items() if k != 'nfFilter'}
+            clean_sub = {k: v for k, v in self.__dict__.items()
+                         if k != 'nfFilter' and k != 'current_filter'}
             if self.administrativeState == AdministrativeState.LOCKING.value:
                 change_type = 'DELETE'
             else:
                 change_type = 'CREATE'
             sub_event = {'nfName': nf.nf_name,
-                         'ipv4Address': nf.ip_address,
+                         'ipAddress': nf.ip_address,
                          'blueprintName': nf.sdnc_model_name,
                          'blueprintVersion': nf.sdnc_model_version,
                          'policyName': app_conf.operational_policy_name,