1 # Copyright (C) 2019 Verizon. All Rights Reserved
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.
19 from collections import Counter
22 from rest_framework import status
24 from catalog.packages import const
25 from catalog.pub.database.models import NsdmSubscriptionModel
26 from catalog.pub.exceptions import CatalogException, \
27 NsdmBadRequestException, NsdmDuplicateSubscriptionException, SubscriptionDoesNotExistsException
28 from catalog.pub.utils.values import ignore_case_get
29 from catalog.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT
31 logger = logging.getLogger(__name__)
33 PARAMSBASICKEYS = ["userName", "password"]
35 PARAMSOAUTH2CLIENTCREDENTIALSKEYS = ["clientId", "clientPassword",
39 def is_filter_type_equal(new_filter, existing_filter):
40 return Counter(list(set(new_filter))) == Counter(existing_filter)
43 class NsdmSubscription:
48 def query_single_subscription(self, subscription_id):
49 logger.debug("Start Query Subscription... ")
51 NsdmSubscriptionModel.objects.filter(
52 subscriptionid=subscription_id)
53 if not subscription.exists():
54 raise SubscriptionDoesNotExistsException(
55 "Subscription(%s) doesn't exist" % subscription_id)
56 logger.debug("Subscription found... ")
57 return self.fill_resp_data(subscription[0])
59 def delete_single_subscription(self, subscription_id):
60 logger.debug("Start Delete Subscription... ")
62 NsdmSubscriptionModel.objects.filter(
63 subscriptionid=subscription_id)
64 if not subscription.exists():
65 raise SubscriptionDoesNotExistsException(
66 "Subscription(%s) doesn't exist" % subscription_id)
68 logger.debug("Deleted Subscription... ")
70 def query_multi_subscriptions(self, query_params):
71 self.params = query_params
73 logger.debug("Start QueryMultiSubscriptions get --> "
74 "Check for filters in query params" % self.params)
75 for query, value in list(self.params.items()):
76 if query in const.NSDM_NOTIFICATION_FILTERS and value:
77 query_data[query + '__icontains'] = json.dumps(list(set(value)))
78 # Query the database with filter if the request
79 # has fields in request params, else fetch all records
81 subscriptions = NsdmSubscriptionModel.objects.filter(**query_data)
83 subscriptions = NsdmSubscriptionModel.objects.all()
84 if not subscriptions.exists():
85 raise SubscriptionDoesNotExistsException("Subscriptions doesn't exist")
86 return [self.fill_resp_data(subscription)
87 for subscription in subscriptions]
89 def check_callbackuri_connection(self):
90 logger.debug("Create Subscription --> Test Callback URI --"
91 "Sending GET request to %s" % self.callback_uri)
93 response = requests.get(self.callback_uri, timeout=2, verify=False)
94 if response.status_code != status.HTTP_204_NO_CONTENT:
95 raise CatalogException("callbackUri %s returns %s status "
96 "code." % (self.callback_uri,
97 response.status_code))
99 raise CatalogException("callbackUri %s didn't return 204 status"
100 "code." % self.callback_uri)
102 def fill_resp_data(self, subscription):
103 subscription_filter = dict()
104 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
105 if subscription.__dict__[filter_type]:
106 subscription_filter[filter_type] = \
107 ast.literal_eval(subscription.__dict__[filter_type])
109 'id': subscription.subscriptionid,
110 'callbackUri': subscription.callback_uri,
111 'filter': subscription_filter,
112 '_links': json.loads(subscription.links)
116 def create(self, data):
117 logger.debug("Start Create Subscription... ")
118 self.filter = ignore_case_get(data, "filter", {})
119 self.callback_uri = ignore_case_get(data, "callbackUri")
120 self.authentication = ignore_case_get(data, "authentication", {})
121 self.subscription_id = str(uuid.uuid4())
122 self.check_callbackuri_connection()
123 self.check_valid_auth_info()
124 self.check_filter_types()
128 NsdmSubscriptionModel.objects.get(
129 subscriptionid=self.subscription_id)
130 return self.fill_resp_data(subscription)
132 def check_filter_types(self):
133 # Check if both nsdId and nsdInfoId
134 # or pnfdId and pnfdInfoId are present
135 logger.debug("Create Subscription --> Validating Filters... ")
137 self.filter.get("nsdId", "") and \
138 self.filter.get("nsdInfoId", ""):
139 raise NsdmBadRequestException("Notification Filter should contain"
140 " either nsdId or nsdInfoId")
142 self.filter.get("pnfdId", "") and \
143 self.filter.get("pnfdInfoIds", ""):
144 raise NsdmBadRequestException("Notification Filter should contain"
145 " either pnfdId or pnfdInfoIds")
147 def check_valid_auth_info(self):
148 logger.debug("Create Subscription --> Validating Auth "
149 "details if provided... ")
150 if self.authentication.get("paramsBasic", {}) and \
151 const.BASIC not in self.authentication.get("authType", ''):
152 raise NsdmBadRequestException('Auth type should be ' + const.BASIC)
153 if self.authentication.get("paramsOauth2ClientCredentials", {}) and \
154 const.OAUTH2_CLIENT_CREDENTIALS not in \
155 self.authentication.get("authType", ''):
156 raise NsdmBadRequestException('Auth type should '
157 'be ' + const.OAUTH2_CLIENT_CREDENTIALS)
158 if const.BASIC in self.authentication.get("authType", '') and \
159 "paramsBasic" in list(self.authentication.keys()) and \
160 not is_filter_type_equal(PARAMSBASICKEYS, list(
161 self.authentication.get("paramsBasic").keys())):
162 raise NsdmBadRequestException('userName and password needed '
163 'for ' + const.BASIC)
164 if const.OAUTH2_CLIENT_CREDENTIALS in \
165 self.authentication.get("authType", '') and \
166 "paramsOauth2ClientCredentials" in \
167 list(self.authentication.keys()) and \
168 not is_filter_type_equal(PARAMSOAUTH2CLIENTCREDENTIALSKEYS, list(
169 self.authentication.get("paramsOauth2ClientCredentials").keys())):
170 raise NsdmBadRequestException('clientId, clientPassword and '
171 'tokenEndpoint required '
172 'for ' + const.OAUTH2_CLIENT_CREDENTIALS)
174 def check_filter_exists(self, subscription):
175 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
176 if not is_filter_type_equal(self.filter.get(filter_type, []),
178 getattr(subscription,
183 def check_valid(self):
184 logger.debug("Create Subscription --> Checking DB if "
185 "same subscription has already existed... ")
187 NsdmSubscriptionModel.objects.filter(
188 callback_uri=self.callback_uri)
190 for subscription in subscriptions:
191 if self.check_filter_exists(subscription):
192 links = json.loads(subscription.links)
194 "Subscription has already existed with the "
195 "same callbackUri and filter:%s" % links)
196 raise NsdmDuplicateSubscriptionException(
197 "https://%s:%s/%s" % (MSB_SERVICE_IP, MSB_SERVICE_PORT, links["self"]["href"]))
200 logger.debug("Create Subscription --> Saving the subscription "
201 "%s to the database" % self.subscription_id)
205 const.NSDM_SUBSCRIPTION_ROOT_URI + self.subscription_id
208 subscription_save_db = {
209 "subscriptionid": self.subscription_id,
210 "callback_uri": self.callback_uri,
211 "auth_info": json.dumps(self.authentication),
212 "links": json.dumps(links)
214 for filter_type in const.NSDM_NOTIFICATION_FILTERS:
216 subscription_save_db[filter_type] = json.dumps(
217 list(set(self.filter.get(filter_type, []))))
218 NsdmSubscriptionModel.objects.create(**subscription_save_db)
219 logger.debug('Create Subscription[%s] success', self.subscription_id)