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.
22 from collections import Counter
23 from rest_framework import status
24 from requests.auth import HTTPBasicAuth
25 from catalog.packages import const
26 from catalog.pub.database.models import VnfPkgSubscriptionModel
27 from catalog.pub.exceptions import VnfPkgSubscriptionException, \
28 VnfPkgDuplicateSubscriptionException, SubscriptionDoesNotExistsException
29 from catalog.pub.utils.values import ignore_case_get
30 from catalog.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT
32 logger = logging.getLogger(__name__)
35 "notificationTypes": "notification_types",
37 "vnfPkgId": "vnf_pkg_id",
38 "operationalState": "operation_states",
39 "usageState": "usage_states"
43 def is_filter_type_equal(new_filter, existing_filter):
44 return Counter(new_filter) == Counter(existing_filter)
47 class CreateSubscription(object):
48 def __init__(self, data):
50 self.filter = ignore_case_get(self.data, "filter", {})
51 self.callback_uri = ignore_case_get(self.data, "callbackUri")
52 self.authentication = ignore_case_get(self.data, "authentication", {})
53 self.notification_types = ignore_case_get(self.filter, "notificationTypes", [])
54 self.operation_states = ignore_case_get(self.filter, "operationalState", [])
55 self.usage_states = ignore_case_get(self.filter, "usageState", [])
56 self.vnfd_id = ignore_case_get(self.filter, "vnfdId", [])
57 self.vnf_pkg_id = ignore_case_get(self.filter, "vnfPkgId", [])
58 self.vnf_products_from_provider = \
59 ignore_case_get(self.filter, "vnfProductsFromProviders", [])
61 def check_callbackuri_connection(self):
62 logger.debug("SubscribeNotification-post::> Sending GET request "
63 "to %s" % self.callback_uri)
65 if self.authentication:
66 if const.BASIC in self.authentication.get("authType", ''):
67 params = self.authentication.get("paramsBasic", {})
68 username = params.get("userName")
69 password = params.get("password")
70 response = requests.get(self.callback_uri, auth=HTTPBasicAuth(username, password), timeout=2,
72 elif const.OAUTH2_CLIENT_CREDENTIALS in self.authentication.get("authType", ''):
79 response = requests.get(self.callback_uri, timeout=2, verify=False)
80 if response.status_code != status.HTTP_204_NO_CONTENT:
81 raise VnfPkgSubscriptionException(
82 "callbackUri %s returns %s status code." % (
88 raise VnfPkgSubscriptionException(
89 "callbackUri %s didn't return 204 status code." % self.callback_uri
93 self.subscription_id = str(uuid.uuid4())
94 self.check_callbackuri_connection()
95 self.check_valid_auth_info()
98 subscription = VnfPkgSubscriptionModel.objects.get(
99 subscription_id=self.subscription_id
102 return subscription.toDict()
104 def check_valid_auth_info(self):
105 logger.debug("SubscribeNotification--post::> Validating Auth "
106 "details if provided")
107 if self.authentication.get("paramsBasic", {}) and const.BASIC not in self.authentication.get("authType"):
108 raise VnfPkgSubscriptionException('Auth type should be ' + const.BASIC)
109 if self.authentication.get("paramsOauth2ClientCredentials", {}) \
110 and const.OAUTH2_CLIENT_CREDENTIALS not in self.authentication.get("authType"):
111 raise VnfPkgSubscriptionException('Auth type should be ' + const.OAUTH2_CLIENT_CREDENTIALS)
113 def check_filter_exists(self, sub):
114 # Check the usage states, operationStates
115 for filter_type in ["operation_states", "usage_states"]:
116 if not is_filter_type_equal(getattr(self, filter_type),
117 ast.literal_eval(getattr(sub, filter_type))):
119 # If all the above types are same then check id filter
120 for id_filter in ["vnfd_id", "vnf_pkg_id"]:
121 if not is_filter_type_equal(getattr(self, id_filter),
122 ast.literal_eval(getattr(sub, id_filter))):
126 def check_valid(self):
128 logger.debug("SubscribeNotification--post::> Checking DB if "
129 "callbackUri already exists")
130 subscriptions = VnfPkgSubscriptionModel.objects.filter(callback_uri=self.callback_uri)
131 for subscription in subscriptions:
132 if self.check_filter_exists(subscription):
133 links = json.loads(subscription.links)
134 logger.error("Subscriptions has already exists with the same callbackUri and filter:%s" % links)
135 raise VnfPkgDuplicateSubscriptionException(
136 "https://%s:%s/%s" % (MSB_SERVICE_IP, MSB_SERVICE_PORT, links["self"]["href"]))
141 logger.debug("SubscribeNotification--post::> Saving the subscription "
142 "%s to the database" % self.subscription_id)
145 "href": os.path.join(const.VNFPKG_SUBSCRIPTION_ROOT_URI, self.subscription_id)
148 VnfPkgSubscriptionModel.objects.create(
149 subscription_id=self.subscription_id,
150 callback_uri=self.callback_uri,
151 notification_types=json.dumps(self.notification_types),
152 auth_info=json.dumps(self.authentication),
153 usage_states=json.dumps(self.usage_states),
154 operation_states=json.dumps(self.operation_states),
155 vnf_products_from_provider=json.dumps(self.vnf_products_from_provider),
156 vnfd_id=json.dumps(self.vnfd_id),
157 vnf_pkg_id=json.dumps(self.vnf_pkg_id),
158 links=json.dumps(links))
159 logger.debug('Create Subscription[%s] success', self.subscription_id)
162 class QuerySubscription(object):
163 def query_multi_subscriptions(self, params):
165 logger.debug("QuerySubscription--get--multi--subscriptions--biz::> Check "
166 "for filter in query params %s" % params)
167 for query, value in list(params.items()):
168 if query in ROOT_FILTERS:
169 query_data[ROOT_FILTERS[query] + '__icontains'] = value
170 # Query the database with filter if the request has fields in request params, else fetch all records
172 subscriptions = VnfPkgSubscriptionModel.objects.filter(**query_data)
174 subscriptions = VnfPkgSubscriptionModel.objects.all()
175 if not subscriptions.exists():
177 return [subscription.toDict() for subscription in subscriptions]
179 def query_single_subscription(self, subscription_id):
180 logger.debug("QuerySingleSubscriptions--get--single--subscription--biz::> "
181 "ID: %s" % subscription_id)
183 subscription = VnfPkgSubscriptionModel.objects.filter(
184 subscription_id=subscription_id)
185 if not subscription.exists():
186 raise SubscriptionDoesNotExistsException("Subscription with ID: %s "
187 "does not exist" % subscription_id)
188 return subscription[0].toDict()
191 class TerminateSubscription(object):
192 def terminate(self, subscription_id):
193 logger.debug("TerminateSubscriptions--delete--biz::> "
194 "ID: %s" % subscription_id)
196 subscription = VnfPkgSubscriptionModel.objects.filter(
197 subscription_id=subscription_id)
198 if not subscription.exists():
199 raise SubscriptionDoesNotExistsException("Subscription with ID: %s "
200 "does not exist" % subscription_id)
201 subscription[0].delete()