1 # Copyright (c) 2019, ZTE Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
20 from collections import Counter
22 from rest_framework import status
24 from lcm.ns.enum import NOTIFICATION_TYPE, AUTH_TYPE
25 from lcm.pub.database.models import SubscriptionModel
26 from lcm.pub.exceptions import NSLCMException, SeeOtherException
27 from lcm.pub.utils.values import ignore_case_get
28 from lcm.ns import const
30 logger = logging.getLogger(__name__)
33 def is_filter_type_equal(new_filter, existing_filter):
34 return Counter(new_filter) == Counter(existing_filter)
40 "lcm_opname_impacting_nscomponent",
41 "lcm_opoccstatus_impacting_nscomponent",
55 class CreateSubscription:
57 def __init__(self, data):
59 self.filter = ignore_case_get(self.data, "filter", {})
60 self.callback_uri = ignore_case_get(self.data, "callbackUri")
61 self.authentication = ignore_case_get(self.data, "authentication", {})
62 self.notification_types = ignore_case_get(self.filter, "notificationTypes", [])
63 self.operation_types = ignore_case_get(self.filter, "operationTypes", [])
64 self.operation_states = ignore_case_get(self.filter, "notificationStates", [])
65 self.ns_component_types = ignore_case_get(self.filter, "nsComponentTypes", [])
66 self.lcm_opname_impacting_nscomponent = ignore_case_get(
68 "lcmOpNameImpactingNsComponent",
71 self.lcm_opoccstatus_impacting_nscomponent = ignore_case_get(
73 "lcmOpOccStatusImpactingNsComponent",
76 self.ns_filter = ignore_case_get(
78 "nsInstanceSubscriptionFilter",
82 def check_callback_uri(self):
83 logger.debug("SubscribeNotification-post::> Sending GET request to %s" % self.callback_uri)
85 response = requests.get(self.callback_uri, timeout=2)
86 if response.status_code != status.HTTP_204_NO_CONTENT:
87 raise NSLCMException("callbackUri %s returns %s status code." % (
92 raise NSLCMException("callbackUri %s didn't return 204 status code." % self.callback_uri)
95 self.subscription_id = str(uuid.uuid4())
96 # self.check_callback_uri()
97 self.check_valid_auth_info()
98 self.check_filter_types()
101 subscription = SubscriptionModel.objects.get(subscription_id=self.subscription_id)
104 def check_filter_types(self):
105 logger.debug("SubscribeNotification--post::> Validating operationTypes and operationStates if exists")
106 occ_notification = NOTIFICATION_TYPE.NSLCM_OPERATION_OCCURRENCE_NOTIFICATION
107 if self.operation_types and occ_notification not in self.notification_types:
108 except_message = "If you are setting operationTypes, notificationTypes must be %s"
109 raise NSLCMException(except_message % occ_notification)
110 if self.operation_states and occ_notification not in self.notification_types:
111 except_message = "If you are setting operationStates, notificationTypes must be %s"
112 raise NSLCMException(except_message % occ_notification)
114 def check_valid_auth_info(self):
115 logger.debug("SubscribeNotification--post::> Validating Auth details if provided")
116 auth_type = self.authentication.get("authType")
117 params_basic = self.authentication.get("paramsBasic")
118 params_oauth2 = self.authentication.get("paramsOauth2ClientCredentials")
119 if params_basic and AUTH_TYPE.BASIC not in auth_type:
120 raise NSLCMException('Auth type should be ' + AUTH_TYPE.BASIC)
121 if params_oauth2 and AUTH_TYPE.OAUTH2_CLIENT_CREDENTIALS not in auth_type:
122 raise NSLCMException('Auth type should be ' + AUTH_TYPE.OAUTH2_CLIENT_CREDENTIALS)
124 def check_filter_exists(self, sub):
125 # Check the notificationTypes, operationTypes, operationStates
126 for filter_type in FILTER_TYPE:
127 if not is_filter_type_equal(
128 getattr(self, filter_type),
129 ast.literal_eval(getattr(sub, filter_type))
132 # If all the above types are same then check ns instance filters
133 ns_filter = json.loads(sub.ns_instance_filter)
134 for ns_filter_type in NS_FILTER_TYPE:
135 if not is_filter_type_equal(
136 self.ns_filter.get(ns_filter_type, []),
137 ns_filter.get(ns_filter_type, [])
142 def check_valid(self):
143 logger.debug("SubscribeNotification--post::> Checking DB if callbackUri already exists")
144 subscriptions = SubscriptionModel.objects.filter(callback_uri=self.callback_uri)
145 if not subscriptions.exists():
147 for subscription in subscriptions:
148 if self.check_filter_exists(subscription):
149 raise SeeOtherException("Already Subscription exists with the same callbackUri and filter")
153 logger.debug("SubscribeNotification--post::> Saving the subscription(%s) to the database" % self.subscription_id)
156 "href": const.SUBSCRIPTION_ROOT_URI % self.subscription_id
159 SubscriptionModel.objects.create(
160 subscription_id=self.subscription_id,
161 callback_uri=self.callback_uri,
162 auth_info=self.authentication,
163 notification_types=json.dumps(self.notification_types),
164 operation_types=json.dumps(self.operation_types),
165 operation_states=json.dumps(self.operation_states),
166 ns_instance_filter=json.dumps(self.ns_filter),
167 ns_component_types=json.dumps(self.ns_component_types),
168 lcm_opname_impacting_nscomponent=json.dumps(self.lcm_opname_impacting_nscomponent),
169 lcm_opoccstatus_impacting_nscomponent=json.dumps(self.lcm_opoccstatus_impacting_nscomponent),
170 links=json.dumps(links))
171 logger.debug('Create Subscription[%s] success', self.subscription_id)