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