349db0869223fe73fa40bf0fdff50dba8ff55a4a
[modeling/etsicatalog.git] / genericparser / packages / biz / vnf_pkg_subscription.py
1 # Copyright (C) 2019 Verizon. All Rights Reserved
2 #
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
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 import ast
16 import json
17 import logging
18 import os
19 import requests
20 import uuid
21
22 from collections import Counter
23 from rest_framework import status
24
25 from genericparser.packages import const
26 from genericparser.pub.database.models import VnfPkgSubscriptionModel
27 from genericparser.pub.exceptions import VnfPkgSubscriptionException,\
28     VnfPkgDuplicateSubscriptionException, SubscriptionDoesNotExistsException
29 from genericparser.pub.utils.values import ignore_case_get
30
31
32 logger = logging.getLogger(__name__)
33
34 ROOT_FILTERS = {
35     "notificationTypes": "notification_types",
36     "vnfdId": "vnfd_id",
37     "vnfPkgId": "vnf_pkg_id",
38     "operationalState": "operation_states",
39     "usageState": "usage_states"
40 }
41
42
43 def is_filter_type_equal(new_filter, existing_filter):
44     return Counter(new_filter) == Counter(existing_filter)
45
46
47 class CreateSubscription(object):
48
49     def __init__(self, data):
50         self.data = data
51         self.filter = ignore_case_get(self.data, "filters", {})
52         self.callback_uri = ignore_case_get(self.data, "callbackUri")
53         self.authentication = ignore_case_get(self.data, "authentication", {})
54         self.notification_types = ignore_case_get(self.filter, "notificationTypes", [])
55         self.operation_states = ignore_case_get(self.filter, "operationalState", [])
56         self.usage_states = ignore_case_get(self.filter, "usageState", [])
57         self.vnfd_id = ignore_case_get(self.filter, "vnfdId", [])
58         self.vnf_pkg_id = ignore_case_get(self.filter, "vnfPkgId", [])
59         self.vnf_products_from_provider = \
60             ignore_case_get(self.filter, "vnfProductsFromProviders", {})
61
62     def check_callbackuri_connection(self):
63         logger.debug("SubscribeNotification-post::> Sending GET request "
64                      "to %s" % self.callback_uri)
65         try:
66             response = requests.get(self.callback_uri, timeout=2)
67             if response.status_code != status.HTTP_204_NO_CONTENT:
68                 raise VnfPkgSubscriptionException("callbackUri %s returns %s status "
69                                                   "code." % (self.callback_uri, response.status_code))
70         except Exception:
71             raise VnfPkgSubscriptionException("callbackUri %s didn't return 204 status"
72                                               "code." % self.callback_uri)
73
74     def do_biz(self):
75         self.subscription_id = str(uuid.uuid4())
76         self.check_callbackuri_connection()
77         self.check_valid_auth_info()
78         self.check_valid()
79         self.save_db()
80         subscription = VnfPkgSubscriptionModel.objects.get(subscription_id=self.subscription_id)
81         if subscription:
82             return subscription.toDict()
83
84     def check_valid_auth_info(self):
85         logger.debug("SubscribeNotification--post::> Validating Auth "
86                      "details if provided")
87         if self.authentication.get("paramsBasic", {}) and \
88                 const.BASIC not in self.authentication.get("authType"):
89             raise VnfPkgSubscriptionException('Auth type should be ' + const.BASIC)
90         if self.authentication.get("paramsOauth2ClientCredentials", {}) and \
91                 const.OAUTH2_CLIENT_CREDENTIALS not in self.authentication.get("authType"):
92             raise VnfPkgSubscriptionException('Auth type should be ' + const.OAUTH2_CLIENT_CREDENTIALS)
93
94     def check_filter_exists(self, sub):
95         # Check the usage states, operationStates
96         for filter_type in ["operation_states", "usage_states"]:
97             if not is_filter_type_equal(getattr(self, filter_type),
98                                         ast.literal_eval(getattr(sub, filter_type))):
99                 return False
100         # If all the above types are same then check id filters
101         for id_filter in ["vnfd_id", "vnf_pkg_id"]:
102             if not is_filter_type_equal(getattr(self, id_filter),
103                                         ast.literal_eval(getattr(sub, id_filter))):
104                 return False
105         return True
106
107     def check_valid(self):
108         logger.debug("SubscribeNotification--post::> Checking DB if "
109                      "callbackUri already exists")
110         subscriptions = VnfPkgSubscriptionModel.objects.filter(callback_uri=self.callback_uri)
111         if not subscriptions.exists():
112             return True
113         for subscription in subscriptions:
114             if self.check_filter_exists(subscription):
115                 raise VnfPkgDuplicateSubscriptionException(
116                     "Already Subscription (%s) exists with the "
117                     "same callbackUri and filter" % subscription.subscription_id)
118         return True
119
120     def save_db(self):
121         logger.debug("SubscribeNotification--post::> Saving the subscription "
122                      "%s to the database" % self.subscription_id)
123         links = {
124             "self": {
125                 "href": os.path.join(const.VNFPKG_SUBSCRIPTION_ROOT_URI, self.subscription_id)
126             }
127         }
128         VnfPkgSubscriptionModel.objects.create(
129             subscription_id=self.subscription_id,
130             callback_uri=self.callback_uri,
131             notification_types=json.dumps(self.notification_types),
132             auth_info=json.dumps(self.authentication),
133             usage_states=json.dumps(self.usage_states),
134             operation_states=json.dumps(self.operation_states),
135             vnf_products_from_provider=json.dumps(self.vnf_products_from_provider),
136             vnfd_id=json.dumps(self.vnfd_id),
137             vnf_pkg_id=json.dumps(self.vnf_pkg_id),
138             links=json.dumps(links))
139         logger.debug('Create Subscription[%s] success', self.subscription_id)
140
141
142 class QuerySubscription(object):
143
144     def query_multi_subscriptions(self, params):
145         query_data = {}
146         logger.debug("QuerySubscription--get--multi--subscriptions--biz::> Check "
147                      "for filters in query params %s" % params)
148         for query, value in params.iteritems():
149             if query in ROOT_FILTERS:
150                 query_data[ROOT_FILTERS[query] + '__icontains'] = value
151         # Query the database with filters if the request has fields in request params, else fetch all records
152         if query_data:
153             subscriptions = VnfPkgSubscriptionModel.objects.filter(**query_data)
154         else:
155             subscriptions = VnfPkgSubscriptionModel.objects.all()
156         if not subscriptions.exists():
157             return []
158         return [subscription.toDict() for subscription in subscriptions]
159
160     def query_single_subscription(self, subscription_id):
161         logger.debug("QuerySingleSubscriptions--get--single--subscription--biz::> "
162                      "ID: %s" % subscription_id)
163
164         subscription = VnfPkgSubscriptionModel.objects.filter(
165             subscription_id=subscription_id)
166         if not subscription.exists():
167             raise SubscriptionDoesNotExistsException("Subscription with ID: %s "
168                                                      "does not exists" % subscription_id)
169         return subscription[0].toDict()
170
171
172 class TerminateSubscription(object):
173
174     def terminate(self, subscription_id):
175         logger.debug("TerminateSubscriptions--delete--biz::> "
176                      "ID: %s" % subscription_id)
177
178         subscription = VnfPkgSubscriptionModel.objects.filter(
179             subscription_id=subscription_id)
180         if not subscription.exists():
181             raise SubscriptionDoesNotExistsException("Subscription with ID: %s "
182                                                      "does not exists" % subscription_id)
183         subscription[0].delete()