summaryrefslogtreecommitdiffstats
path: root/lcm/lcm/nf/biz/create_subscription.py
blob: 2b1f606410ca26de6f845a1f2085885ba878f6d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# Copyright (C) 2018 Verizon. All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import ast
import json
import logging
import requests
import uuid

from collections import Counter

from rest_framework import status

from lcm.nf import const
from lcm.pub.database.models import SubscriptionModel
from lcm.pub.exceptions import NFLCMException
from lcm.pub.exceptions import NFLCMExceptionSeeOther
from lcm.pub.utils.values import ignore_case_get
from lcm.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT

logger = logging.getLogger(__name__)


def is_filter_type_equal(new_filter, existing_filter):
    return Counter(new_filter) == Counter(existing_filter)


class CreateSubscription:
    def __init__(self, data):
        self.data = data
        self.filter = ignore_case_get(self.data, "filter", {})
        logger.debug("self.data:%s" % self.data)
        logger.debug("self.filter:%s" % self.filter)
        self.callback_uri = ignore_case_get(self.data, "callbackUri")
        self.authentication = ignore_case_get(self.data, "authentication", {})
        self.notification_types = ignore_case_get(self.filter, "notificationTypes", [])
        self.operation_types = ignore_case_get(self.filter, "operationTypes", [])
        self.operation_states = ignore_case_get(self.filter, "operationStates", [])
        self.vnf_filter = \
            ignore_case_get(self.filter, "vnfInstanceSubscriptionFilter", {})

    def check_callbackuri_connection(self):
        logger.debug("SubscribeNotification-post::> Sending GET request "
                     "to %s" % self.callback_uri)
        try:
            response = requests.get(self.callback_uri, timeout=2)
            if response.status_code != status.HTTP_204_NO_CONTENT:
                raise NFLCMException("callbackUri %s returns %s status "
                                     "code." % (self.callback_uri, response.status_code))
        except Exception:
            raise NFLCMException("callbackUri %s didn't return 204 status"
                                 "code." % self.callback_uri)

    def do_biz(self):
        self.subscription_id = str(uuid.uuid4())
        self.check_callbackuri_connection()
        self.check_valid_auth_info()
        self.check_filter_types()
        self.check_valid()
        self.save_db()
        subscription = SubscriptionModel.objects.get(subscription_id=self.subscription_id)
        return subscription

    def check_filter_types(self):
        logger.debug("SubscribeNotification--post::> Validating "
                     "operationTypes  and operationStates if exists")
        if self.operation_types and \
                const.LCCNNOTIFICATION not in self.notification_types:
            raise NFLCMException("If you are setting operationTypes,"
                                 "then notificationTypes "
                                 "must be " + const.LCCNNOTIFICATION)
        if self.operation_states and \
                const.LCCNNOTIFICATION not in self.notification_types:
            raise NFLCMException("If you are setting operationStates,"
                                 "then notificationTypes "
                                 "must be " + const.LCCNNOTIFICATION)

    def check_valid_auth_info(self):
        logger.debug("SubscribeNotification--post::> Validating Auth "
                     "details if provided")
        if self.authentication.get("paramsBasic", {}) and \
                const.BASIC not in self.authentication.get("authType"):
            raise NFLCMException('Auth type should be ' + const.BASIC)
        if self.authentication.get("paramsOauth2ClientCredentials", {}) and \
                const.OAUTH2_CLIENT_CREDENTIALS not in self.authentication.get("authType"):
            raise NFLCMException('Auth type should be ' + const.OAUTH2_CLIENT_CREDENTIALS)

    def check_filter_exists(self, sub):
        # Check the notificationTypes, operationTypes, operationStates
        for filter_type in ["operation_types",
                            "notification_types", "operation_states"]:
            if not is_filter_type_equal(getattr(self, filter_type),
                                        ast.literal_eval(getattr(sub, filter_type))):
                return False
        # If all the above types are same then check vnf instance filters
        nf_filter = json.loads(sub.vnf_instance_filter)
        for vnf_filter_type in ["vnfdIds", "vnfInstanceIds",
                                "vnfInstanceNames"]:
            if not is_filter_type_equal(self.vnf_filter.get(vnf_filter_type, []),
                                        nf_filter.get(vnf_filter_type, [])):
                return False
        return True

    def check_valid(self):
        logger.debug("SubscribeNotification--post::> Checking DB if "
                     "callbackUri already exists")
        subscriptions = SubscriptionModel.objects.filter(callback_uri=self.callback_uri)
        if not subscriptions.exists():
            return True
        for subscription in subscriptions:
            if self.check_filter_exists(subscription):
                links = json.loads(subscription.links)
                raise NFLCMExceptionSeeOther("http://%s:%s/%s" % (MSB_SERVICE_IP, MSB_SERVICE_PORT, links["self"]["href"]))
        return False

    def save_db(self):
        logger.debug("SubscribeNotification--post::> Saving the subscription "
                     "%s to the database" % self.subscription_id)
        links = {
            "self": {
                "href": const.ROOT_URI + self.subscription_id
            }
        }
        SubscriptionModel.objects.create(subscription_id=self.subscription_id,
                                         callback_uri=self.callback_uri,
                                         auth_info=json.dumps(self.authentication),
                                         notification_types=json.dumps(self.notification_types),
                                         operation_types=json.dumps(self.operation_types),
                                         operation_states=json.dumps(self.operation_states),
                                         vnf_instance_filter=json.dumps(self.vnf_filter),
                                         links=json.dumps(links))
        logger.debug('Create Subscription[%s] success', self.subscription_id)