114f922c11b2fb262e309aec2d387e60f8f06a72
[modeling/etsicatalog.git] / catalog / packages / biz / notificationsutil.py
1 # Copyright 2019 ZTE Corporation.
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 logging
16 import uuid
17 import requests
18 from rest_framework import status
19 from catalog.packages import const
20 from catalog.pub.database.models import VnfPackageModel, VnfPkgSubscriptionModel, NsdmSubscriptionModel
21 import catalog.pub.utils.timeutil
22 from catalog.pub.utils.values import remove_none_key
23 from catalog.pub.config import config as pub_config
24 import traceback
25 from django.db.models import Q
26 from catalog.packages.serializers.vnf_pkg_notifications import PkgChangeNotificationSerializer, \
27     PkgOnboardingNotificationSerializer
28
29
30 logger = logging.getLogger(__name__)
31
32
33 class NotificationsUtil(object):
34     def __init__(self, notification_type):
35         self.notification_type = notification_type
36         self.notifyserializer = None
37
38     def prepare_notification(self, **kwargs):
39         pass
40
41     def send_notification(self):
42         notification = self.prepare_notification()
43
44         subscriptions_filter = {v + "__contains": notification[k] for k, v in self.filter.items()}
45         subscriptions_filter = remove_none_key(subscriptions_filter)
46         logger.debug('send_notification subscriptions_filter = %s' % subscriptions_filter)
47         q1 = Q()
48         q1.connector = 'OR'
49         for k, v in subscriptions_filter.items():
50             q1.children.append((k, v))
51
52         subscriptions = self.SubscriptionModel.objects.filter(q1)
53         if not subscriptions.exists():
54             logger.info("No subscriptions created for the filter %s" % notification)
55             return
56         logger.info("Start sending notifications")
57         for sub in subscriptions:
58             # set subscription id
59             notification["subscriptionId"] = sub.get_subscription_id()
60             notification['_links']['subscription'] = {
61                 'href': 'http://%s:%s/%s%s' % (pub_config.MSB_SERVICE_IP,
62                                                pub_config.MSB_SERVICE_PORT,
63                                                self.subscription_root_uri,
64                                                notification["subscriptionId"])
65             }
66             callbackuri = sub.callback_uri
67             """
68             auth_info = json.loads(sub.auth_info)
69             if auth_info["authType"] == const.OAUTH2_CLIENT_CREDENTIALS:
70                 pass
71             """
72             if self.notifyserializer:
73                 serialized_data = self.notifyserializer(data=notification)
74                 if not serialized_data.is_valid():
75                     logger.error('Notification Data is invalid:%s.' % serialized_data.errors)
76             self.post_notification(callbackuri, notification)
77
78     def post_notification(self, callbackuri, notification):
79         """
80         params = auth_info.get("paramsBasic", {})
81         username, password = params.get("userName"), params.get("password")
82         logger.info("Sending notification to %s, %s", callbackuri, params)
83         resp = None
84         if username:
85             resp = requests.post(callbackuri,
86                                  data=notification,
87                                  auth=HTTPBasicAuth(username, password))
88         else:
89         """
90
91         try:
92             resp = requests.post(callbackuri, data=notification, headers={'Connection': 'close'})
93             if resp.status_code != status.HTTP_204_NO_CONTENT:
94                 logger.error("Sending notification to %s failed: %s" % (callbackuri, resp.text))
95             else:
96                 logger.info("Sending notification to %s successfully.", callbackuri)
97         except:
98             logger.error("Post notification failed.")
99             logger.error(traceback.format_exc())
100
101
102 class PkgNotifications(NotificationsUtil):
103     def __init__(self, notification_type, vnf_pkg_id, change_type=None, operational_state=None):
104         super(PkgNotifications, self).__init__(notification_type)
105         self.filter = {
106             'vnfdId': 'vnfd_id',
107             'vnfPkgId': 'vnf_pkg_id'
108         }
109         self.vnf_pkg_id = vnf_pkg_id
110         self.change_type = change_type
111         self.operational_state = operational_state
112         self.SubscriptionModel = VnfPkgSubscriptionModel
113         self.subscription_root_uri = const.VNFPKG_SUBSCRIPTION_ROOT_URI
114         if self.notification_type == "VnfPackageChangeNotification":
115             self.notifyserializer = PkgChangeNotificationSerializer
116         else:
117             self.notifyserializer = PkgOnboardingNotificationSerializer
118
119     def prepare_notification(self):
120         logger.info('Start to prepare Pkgnotification')
121
122         vnf_pkg = VnfPackageModel.objects.filter(vnfPackageId=self.vnf_pkg_id)
123         vnfd_id = None
124         if vnf_pkg:
125             vnfd_id = vnf_pkg[0].vnfdId
126         notification_content = {
127             'id': str(uuid.uuid4()),  # shall be the same if sent multiple times due to multiple subscriptions.
128             'notificationType': self.notification_type,
129             # set 'subscriptionId' after filtering for subscribers
130             'timeStamp': catalog.pub.utils.timeutil.now_time(),
131             'vnfPkgId': self.vnf_pkg_id,
132             'vnfdId': vnfd_id,
133             '_links': {
134                 'vnfPackage': {
135                     'href': 'http://%s:%s/%s/vnf_packages/%s' % (pub_config.MSB_SERVICE_IP,
136                                                                  pub_config.MSB_SERVICE_PORT,
137                                                                  const.PKG_URL_PREFIX,
138                                                                  self.vnf_pkg_id)
139                 }
140             }
141         }
142
143         if self.notification_type == "VnfPackageChangeNotification":
144             notification_content['changeType'] = self.change_type
145             notification_content['operationalState'] = self.operational_state
146
147         return notification_content
148
149
150 class NsdNotifications(NotificationsUtil):
151     def __init__(self, notification_type, nsd_info_id, nsd_id, failure_details=None, operational_state=None):
152         super(NsdNotifications, self).__init__(notification_type)
153         self.filter = {
154             'nsdInfoId': 'nsdInfoId',
155             'nsdId': 'nsdId',
156         }
157         self.SubscriptionModel = NsdmSubscriptionModel
158         self.subscription_root_uri = const.NSDM_SUBSCRIPTION_ROOT_URI
159         self.nsd_info_id = nsd_info_id
160         self.nsd_id = nsd_id
161         self.failure_details = failure_details
162         self.operational_state = operational_state
163         # todo:
164         # if self.notification_type == "VnfPackageChangeNotification":
165         #     self.notifyserializer = PkgChangeNotificationSerializer
166         # else:
167         #     self.notifyserializer = PkgOnboardingNotificationSerializer
168
169     def prepare_notification(self):
170         logger.info('Start to prepare Nsdnotification')
171
172         notification_content = {
173             'id': str(uuid.uuid4()),  # shall be the same if sent multiple times due to multiple subscriptions.
174             'notificationType': self.notification_type,
175             # set 'subscriptionId' after filtering for subscribers
176             'timeStamp': catalog.pub.utils.timeutil.now_time(),
177             'nsdInfoId': self.nsd_info_id,
178             'nsdId': self.nsd_id,
179             '_links': {
180                 'nsdInfo': {
181                     'href': 'http://%s:%s/%s/ns_descriptors/%s' % (pub_config.MSB_SERVICE_IP,
182                                                                    pub_config.MSB_SERVICE_PORT,
183                                                                    const.NSD_URL_PREFIX,
184                                                                    self.nsd_info_id)
185                 }
186             }
187         }
188         if self.notification_type == "NsdOnboardingFailureNotification":
189             notification_content['onboardingFailureDetails'] = self.failure_details
190         if self.notification_type == "NsdChangeNotification":
191             notification_content['nsdOperationalState'] = self.operational_state
192         return notification_content
193
194
195 class PnfNotifications(NotificationsUtil):
196     def __init__(self, notification_type, pnfd_info_id, pnfd_id, failure_details=None):
197         super(PnfNotifications, self).__init__(notification_type)
198         self.filter = {
199             'pnfdId': 'pnfdId',
200             'pnfdInfoIds': 'pnfdInfoIds',
201         }
202         self.SubscriptionModel = NsdmSubscriptionModel
203         self.subscription_root_uri = const.NSDM_SUBSCRIPTION_ROOT_URI
204         self.pnfd_info_id = pnfd_info_id
205         self.pnfd_id = pnfd_id
206         self.failure_details = failure_details
207         # todo
208         # if self.notification_type == "VnfPackageChangeNotification":
209         #     self.notifyserializer = PkgChangeNotificationSerializer
210         # else:
211         #     self.notifyserializer = PkgOnboardingNotificationSerializer
212
213     def prepare_notification(self, *args, **kwargs):
214         logger.info('Start to prepare Pnfnotification')
215         notification_content = {
216             'id': str(uuid.uuid4()),  # shall be the same if sent multiple times due to multiple subscriptions.
217             'notificationType': self.notification_type,
218             # set 'subscriptionId' after filtering for subscribers
219             'timeStamp': catalog.pub.utils.timeutil.now_time(),
220             'pnfdInfoIds': self.pnfd_info_id,
221             'pnfdId': self.pnfd_id,
222             '_links': {
223                 'pnfdInfo': {
224                     'href': 'http://%s:%s/%s/pnf_descriptors/%s' % (pub_config.MSB_SERVICE_IP,
225                                                                     pub_config.MSB_SERVICE_PORT,
226                                                                     const.NSD_URL_PREFIX,
227                                                                     self.pnfd_info_id)
228                 }
229             }
230         }
231         if self.notification_type == "PnfdOnboardingFailureNotification":
232             notification_content['onboardingFailureDetails'] = self.failure_details
233         return notification_content