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}',
83 def update_subscription_status(self):
84 """ Updates the status of subscription in subscription table """
86 SubscriptionModel.query.filter(
87 SubscriptionModel.subscription_name == self.subscriptionName)\
88 .update({SubscriptionModel.status: self.administrativeState},
89 synchronize_session='evaluate')
92 except Exception as e:
93 logger.error(f'Failed to update status of subscription: {self.subscriptionName}: {e}',
96 def prepare_subscription_event(self, nf, app_conf):
97 """Prepare the sub event for publishing
100 nf (NetworkFunction): the AAI nf.
101 app_conf (AppConfig): the application configuration.
104 dict: the Subscription event to be published.
107 clean_sub = {k: v for k, v in self.__dict__.items() if k != 'nfFilter'}
108 sub_event = {'nfName': nf.nf_name, 'blueprintName': nf.sdnc_model_name,
109 'blueprintVersion': nf.sdnc_model_version,
110 'policyName': app_conf.operational_policy_name,
111 'changeType': 'DELETE'
112 if self.administrativeState == AdministrativeState.LOCKED.value
113 else 'CREATE', 'closedLoopControlName': app_conf.control_loop_name,
114 'subscription': clean_sub}
116 except Exception as e:
117 logger.error(f'Failed to prep Sub event for xNF {nf.nf_name}: {e}', exc_info=True)
120 def add_network_function_to_subscription(self, nf, sub_model):
121 """ Associates a network function to a Subscription
124 sub_model(SubscriptionModel): The SubscriptionModel from the DB.
125 nf(NetworkFunction): A NetworkFunction object.
128 current_nf = nf.create()
129 existing_entry = NfSubRelationalModel.query.filter(
130 NfSubRelationalModel.subscription_name == self.subscriptionName,
131 NfSubRelationalModel.nf_name == current_nf.nf_name).one_or_none()
132 if existing_entry is None:
133 new_nf_sub = NfSubRelationalModel(self.subscriptionName,
134 nf.nf_name, SubNfState.PENDING_CREATE.value)
135 sub_model.nfs.append(new_nf_sub)
136 db.session.add(sub_model)
138 logger.info(f'Network function {current_nf.nf_name} added to Subscription '
139 f'{self.subscriptionName}')
140 except Exception as e:
141 logger.error(f'Failed to add nf {nf.nf_name} to subscription '
142 f'{self.subscriptionName}: {e}', exc_info=True)
143 logger.debug(f'Subscription {self.subscriptionName} now contains these XNFs:'
144 f'{[nf.nf_name for nf.nf_name in self.get_network_functions()]}')
147 """ Retrieves a SubscriptionModel object
150 SubscriptionModel object else None
152 return SubscriptionModel.query.filter(
153 SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
155 def get_local_sub_admin_state(self):
156 """ Retrieves the subscription admin state
159 str: The admin state of the SubscriptionModel
161 sub_model = SubscriptionModel.query.filter(
162 SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()
163 return sub_model.status
167 """ Retrieves a list of subscriptions
170 list(SubscriptionModel): Subscriptions list else empty
172 return SubscriptionModel.query.all()
174 def activate_subscription(self, nfs, mr_pub, app_conf):
175 logger.info(f'Activate subscription initiated for {self.subscriptionName}.')
177 existing_nfs = self.get_network_functions()
178 sub_model = self.get()
179 for nf in set(nfs + existing_nfs):
180 logger.info(f'Publishing event to activate '
181 f'Sub: {self.subscriptionName} for the nf: {nf.nf_name}')
182 mr_pub.publish_subscription_event_data(self, nf, app_conf)
183 self.add_network_function_to_subscription(nf, sub_model)
184 self.update_sub_nf_status(self.subscriptionName, SubNfState.PENDING_CREATE.value,
186 except Exception as err:
187 raise Exception(f'Error publishing activation event to MR: {err}')
189 def deactivate_subscription(self, mr_pub, app_conf):
191 nfs = self.get_network_functions()
193 logger.info(f'Deactivate subscription initiated for {self.subscriptionName}.')
195 mr_pub.publish_subscription_event_data(self, nf, app_conf)
196 logger.debug(f'Publishing Event to deactivate '
197 f'Sub: {self.subscriptionName} for the nf: {nf.nf_name}')
198 self.update_sub_nf_status(self.subscriptionName,
199 SubNfState.PENDING_DELETE.value,
201 except Exception as err:
202 raise Exception(f'Error publishing deactivation event to MR: {err}')
205 def get_all_nfs_subscription_relations():
206 """ Retrieves all network function to subscription relations
209 list(NfSubRelationalModel): NetworkFunctions per Subscription list else empty
211 nf_per_subscriptions = NfSubRelationalModel.query.all()
212 return nf_per_subscriptions
215 def update_sub_nf_status(subscription_name, status, nf_name):
216 """ Updates the status of the subscription for a particular nf
219 subscription_name (str): The subscription name
220 nf_name (str): The network function name
221 status (str): Status of the subscription
224 NfSubRelationalModel.query.filter(
225 NfSubRelationalModel.subscription_name == subscription_name,
226 NfSubRelationalModel.nf_name == nf_name). \
227 update({NfSubRelationalModel.nf_sub_status: status}, synchronize_session='evaluate')
229 except Exception as e:
230 logger.error(f'Failed to update status of nf: {nf_name} for subscription: '
231 f'{subscription_name}: {e}', exc_info=True)
233 def get_network_functions(self):
234 nf_sub_relationships = NfSubRelationalModel.query.filter(
235 NfSubRelationalModel.subscription_name == self.subscriptionName)
237 for nf_sub_entry in nf_sub_relationships:
238 nf_model_object = NetworkFunctionModel.query.filter(
239 NetworkFunctionModel.nf_name == nf_sub_entry.nf_name).one_or_none()
240 nfs.append(nf_model_object.to_nf())