1 # ============LICENSE_START===================================================
2 # Copyright (C) 2019-2020 Nordix Foundation.
3 # ============================================================================
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # SPDX-License-Identifier: Apache-2.0
17 # ============LICENSE_END=====================================================
20 from mod import db, logger
21 from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, NetworkFunctionModel
24 class SubNfState(Enum):
25 PENDING_CREATE = 'PENDING_CREATE'
26 CREATE_FAILED = 'CREATE_FAILED'
28 PENDING_DELETE = 'PENDING_DELETE'
29 DELETE_FAILED = 'DELETE_FAILED'
32 class AdministrativeState(Enum):
38 subscription_nf_states = {
39 AdministrativeState.LOCKED.value: {
40 'success': SubNfState.CREATED,
41 'failed': SubNfState.DELETE_FAILED
43 AdministrativeState.UNLOCKED.value: {
44 'success': SubNfState.CREATED,
45 'failed': SubNfState.CREATE_FAILED
51 def __init__(self, **kwargs):
52 self.subscriptionName = kwargs.get('subscriptionName')
53 self.administrativeState = kwargs.get('administrativeState')
54 self.fileBasedGP = kwargs.get('fileBasedGP')
55 self.fileLocation = kwargs.get('fileLocation')
56 self.nfFilter = kwargs.get('nfFilter')
57 self.measurementGroups = kwargs.get('measurementGroups')
61 """ Creates a subscription database entry
67 existing_subscription = (SubscriptionModel.query.filter(
68 SubscriptionModel.subscription_name == self.subscriptionName).one_or_none())
69 if existing_subscription is None:
70 new_subscription = SubscriptionModel(subscription_name=self.subscriptionName,
71 status=AdministrativeState.PENDING.value)
72 db.session.add(new_subscription)
74 return new_subscription
76 logger.debug(f'Subscription {self.subscriptionName} already exists,'
77 f' returning this subscription..')
78 return existing_subscription
79 except Exception as e:
80 logger.error(f'Failed to create subscription {self.subscriptionName} in the DB: {e}',
85 def update_subscription_status(self):
86 """ Updates the status of subscription in subscription table """
88 SubscriptionModel.query.filter(
89 SubscriptionModel.subscription_name == self.subscriptionName)\
90 .update({SubscriptionModel.status: self.administrativeState},
91 synchronize_session='evaluate')
94 except Exception as e:
95 logger.error(f'Failed to update status of subscription: {self.subscriptionName}: {e}',
100 def prepare_subscription_event(self, nf, app_conf):
101 """Prepare the sub event for publishing
104 nf (NetworkFunction): the AAI nf.
105 app_conf (AppConfig): the application configuration.
108 dict: the Subscription event to be published.
111 clean_sub = {k: v for k, v in self.__dict__.items() if k != 'nfFilter'}
112 sub_event = {'nfName': nf.nf_name,
113 'ipv4Address': nf.ip_address,
114 'blueprintName': nf.sdnc_model_name,
115 'blueprintVersion': nf.sdnc_model_version,
116 'policyName': app_conf.operational_policy_name,
117 'changeType': 'DELETE'
118 if self.administrativeState == AdministrativeState.LOCKED.value
119 else 'CREATE', 'closedLoopControlName': app_conf.control_loop_name,
120 'subscription': clean_sub}
122 except Exception as e:
123 logger.error(f'Failed to prep Sub event for xNF {nf.nf_name}: {e}', exc_info=True)
126 def add_network_function_to_subscription(self, nf, sub_model):
127 """ Associates a network function to a Subscription
130 sub_model(SubscriptionModel): The SubscriptionModel from the DB.
131 nf(NetworkFunction): A NetworkFunction object.
134 current_nf = nf.create()
135 existing_entry = NfSubRelationalModel.query.filter(
136 NfSubRelationalModel.subscription_name == self.subscriptionName,
137 NfSubRelationalModel.nf_name == current_nf.nf_name).one_or_none()
138 if existing_entry is None:
139 new_nf_sub = NfSubRelationalModel(self.subscriptionName,
140 nf.nf_name, SubNfState.PENDING_CREATE.value)
141 sub_model.nfs.append(new_nf_sub)
142 db.session.add(sub_model)
144 logger.info(f'Network function {current_nf.nf_name} added to Subscription '
145 f'{self.subscriptionName}')
146 except Exception as e:
147 logger.error(f'Failed to add nf {nf.nf_name} to subscription '
148 f'{self.subscriptionName}: {e}', exc_info=True)
149 logger.debug(f'Subscription {self.subscriptionName} now contains these XNFs:'
150 f'{[nf.nf_name for nf.nf_name in self.get_network_functions()]}')
153 """ Retrieves a SubscriptionModel object
156 SubscriptionModel object else None
158 sub_model = SubscriptionModel.query.filter(
159 SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
162 def get_local_sub_admin_state(self):
163 """ Retrieves the subscription admin state
166 str: The admin state of the SubscriptionModel
168 sub_model = SubscriptionModel.query.filter(
169 SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
171 return sub_model.status
175 """ Retrieves a list of subscriptions
178 list(SubscriptionModel): Subscriptions list else empty
181 sub_models = SubscriptionModel.query.all()
185 def activate_subscription(self, nfs, mr_pub, app_conf):
186 logger.info(f'Activate subscription initiated for {self.subscriptionName}.')
188 existing_nfs = self.get_network_functions()
189 sub_model = self.get()
190 for nf in [new_nf for new_nf in nfs if new_nf not in existing_nfs]:
191 logger.info(f'Publishing event to activate '
192 f'Sub: {self.subscriptionName} for the nf: {nf.nf_name}')
193 mr_pub.publish_subscription_event_data(self, nf, app_conf)
194 self.add_network_function_to_subscription(nf, sub_model)
195 self.update_sub_nf_status(self.subscriptionName, SubNfState.PENDING_CREATE.value,
197 except Exception as err:
198 raise Exception(f'Error publishing activation event to MR: {err}')
200 def deactivate_subscription(self, mr_pub, app_conf):
202 nfs = self.get_network_functions()
204 logger.info(f'Deactivate subscription initiated for {self.subscriptionName}.')
206 mr_pub.publish_subscription_event_data(self, nf, app_conf)
207 logger.debug(f'Publishing Event to deactivate '
208 f'Sub: {self.subscriptionName} for the nf: {nf.nf_name}')
209 self.update_sub_nf_status(self.subscriptionName,
210 SubNfState.PENDING_DELETE.value,
212 except Exception as err:
213 raise Exception(f'Error publishing deactivation event to MR: {err}')
216 def get_all_nfs_subscription_relations():
217 """ Retrieves all network function to subscription relations
220 list(NfSubRelationalModel): NetworkFunctions per Subscription list else empty
222 nf_per_subscriptions = NfSubRelationalModel.query.all()
224 return nf_per_subscriptions
227 def update_sub_nf_status(subscription_name, status, nf_name):
228 """ Updates the status of the subscription for a particular nf
231 subscription_name (str): The subscription name
232 nf_name (str): The network function name
233 status (str): Status of the subscription
236 NfSubRelationalModel.query.filter(
237 NfSubRelationalModel.subscription_name == subscription_name,
238 NfSubRelationalModel.nf_name == nf_name). \
239 update({NfSubRelationalModel.nf_sub_status: status}, synchronize_session='evaluate')
241 except Exception as e:
242 logger.error(f'Failed to update status of nf: {nf_name} for subscription: '
243 f'{subscription_name}: {e}', exc_info=True)
245 def get_network_functions(self):
246 nf_sub_relationships = NfSubRelationalModel.query.filter(
247 NfSubRelationalModel.subscription_name == self.subscriptionName)
249 for nf_sub_entry in nf_sub_relationships:
250 nf_model_object = NetworkFunctionModel.query.filter(
251 NetworkFunctionModel.nf_name == nf_sub_entry.nf_name).one_or_none()
252 nfs.append(nf_model_object.to_nf())