Support second level NSSI in terminate app
[optf/osdf.git] / apps / nxi_termination / optimizers / remote_opt_processor.py
1 # -------------------------------------------------------------------------
2 #   Copyright (C) 2020 Wipro Limited.
3 #
4 #   Licensed under the Apache License, Version 2.0 (the "License");
5 #   you may not use this file except in compliance with the License.
6 #   You may obtain a copy of the License at
7 #
8 #       http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #   Unless required by applicable law or agreed to in writing, software
11 #   distributed under the License is distributed on an "AS IS" BASIS,
12 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 #   See the License for the specific language governing permissions and
14 #   limitations under the License.
15 #
16 # -------------------------------------------------------------------------
17 #
18
19 from jinja2 import Template
20
21 from apps.nxi_termination.optimizers.response_processor import get_nxi_termination_response
22 from osdf.adapters.aai.fetch_aai_data import AAIException
23 from osdf.adapters.aai.fetch_aai_data import execute_dsl_query
24 from osdf.adapters.aai.fetch_aai_data import get_aai_data
25 from osdf.logging.osdf_logging import debug_log
26
27
28 def process_nxi_termination_opt(request_json, osdf_config):
29     """Process the nxi Termination request from API layer
30
31            :param request_json: api request
32            :param osdf_config: configuration specific to OSDF app
33            :return: response as a success,failure
34     """
35
36     request_type = request_json["type"]
37     request_info = request_json.get("requestInfo", {})
38     addtnl_args = request_info.get("addtnlArgs", {})
39     query_templates = osdf_config.core["nxi_termination"]["query_templates"]
40
41     inputs = {
42         "instance_id": request_json["NxIId"]
43     }
44
45     try:
46         if request_type == "NSSI":
47             templates = query_templates["nssi"]
48             for template in templates:
49                 resource_count = get_resource_count(template, inputs, osdf_config)
50                 if resource_count == -1:
51                     continue
52                 elif resource_count > 1 or (resource_count == 1 and not addtnl_args.get("serviceInstanceId")):
53                     terminate_response = False
54                 elif resource_count == 0:
55                     terminate_response = True
56                 elif resource_count == 1 and addtnl_args.get("serviceInstanceId"):
57                     new_template = template + "('service-instance-id','{}')".format(addtnl_args["serviceInstanceId"])
58                     terminate_response = get_resource_count(new_template, inputs, osdf_config) == 1
59                 return set_response("success", "", request_info, terminate_response)
60
61         if request_type == "NSI":
62             allotted_resources = get_allotted_resources(request_json, osdf_config)
63             resource_count = len(allotted_resources)
64             if resource_count == 1 and addtnl_args.get("serviceInstanceId"):
65                 debug_log.debug("resource count {}".format(resource_count))
66                 terminate_response = False
67                 properties = allotted_resources[0]["relationship-data"]
68                 for property in properties:
69                     if property["relationship-key"] == "service-instance.service-instance-id" \
70                             and property["relationship-value"] == addtnl_args.get("serviceInstanceId"):
71                         terminate_response = True
72             elif resource_count > 1 or (resource_count == 1 and not addtnl_args.get("serviceInstanceId")):
73                 terminate_response = False
74             elif resource_count == 0:
75                 terminate_response = True
76
77         return set_response("success", "", request_info, terminate_response)
78     except AAIException as e:
79         reason = str(e)
80         return set_response("failure", reason, request_info)
81
82     except Exception as e:
83         reason = "{} Exception Occurred while processing".format(str(e))
84         return set_response("failure", reason, request_info)
85
86
87 def set_response(status, reason, request_info, terminate_response=None):
88     res = dict()
89     res["requestStatus"] = status
90     res["terminateResponse"] = terminate_response
91     res["reason"] = reason
92     return get_nxi_termination_response(request_info, res)
93
94
95 def get_resource_count(query_template, inputs, osdf_config):
96     query = Template(query_template).render(inputs)
97     dsl_response = execute_dsl_query(query, "count", osdf_config)
98     debug_log.debug("dsl_response {}".format(dsl_response))
99     # the dsl query with format "count" includes the original service-instance, hence reducing one from the result
100     count = dsl_response["results"][0]
101     return count.get("service-instance", 0) - 1
102
103
104 def get_allotted_resources(request_json, osdf_config):
105     response = get_aai_data(request_json, osdf_config)
106     rel_list = response["relationship-list"]["relationship"]
107     return [rel for rel in rel_list if rel["related-to"] == "allotted-resource"]