update link to upper-constraints.txt
[vfc/nfvo/lcm.git] / lcm / ns_vnfs / biz / place_vnfs.py
1 # Copyright 2017-2018 Intel 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 json
17
18 from lcm.pub.database.models import OOFDataModel
19 from lcm.pub.utils import values
20
21 logger = logging.getLogger(__name__)
22
23
24 class PlaceVnfs(object):
25     def __init__(self, data):
26         self.data = data
27         self.placements = ""
28         self.request_id = data.get("requestId")
29
30     def validateCallbackResponse(self):
31         if self.data == "":
32             logger.error("Error occurred in Homing: OOF Async Callback Response is empty")
33             return False
34         if self.data.get('requestStatus') == "completed" and self.data.get("requestId"):
35             if self.data.get("solutions").get("placementSolutions") is not None:
36                 self.placements = self.data.get("solutions").get("placementSolutions")
37                 logger.debug("Got placement solutions in OOF Async Callback response")
38                 return True
39             else:
40                 logger.error("Error occurred in Homing: OOF Async Callback Response "
41                              "does not contain placement solution")
42                 return False
43         else:
44             if self.data.get("statusMessage"):
45                 logger.error(
46                     "Error occurred in Homing: Request has not been completed, the request status is %s, "
47                     "the status message is %s" % (self.data.get('requestStatus'), self.data.get("statusMessage")))
48             else:
49                 logger.error(
50                     "Error occurred in Homing: Request has not been completed, the request status is %s, "
51                     % self.data.get('requestStatus'))
52             return False
53
54     def extract(self):
55         params = ["locationId", "vimId", "oof_directives", "cloudOwner"]
56         vim_info = {}
57         if not self.validateCallbackResponse():
58             logger.error("OOF request Failed")
59             self.update_response_to_db(self.request_id, self.data.get("requestStatus"), "none", "none",
60                                        "none", "none")
61             return
62         if self.placements == [] or self.placements == [[]]:
63             logger.debug("No solution found for request %s " % self.request_id)
64             self.update_response_to_db(self.request_id, self.data.get("requestStatus"), "none", "none",
65                                        "none", "none")
66             return
67         for item in self.placements:
68             if not isinstance(item, list):
69                 self.update_response_to_db(self.request_id, self.data.get("requestStatus"), "none", "none",
70                                            "none", "none")
71                 continue
72             for placement in item:
73                 assignmentInfo = placement.get("assignmentInfo")
74                 if not assignmentInfo or not placement.get("solution"):
75                     logger.debug(
76                         "No assignment info/Solution inside Homing response for request %s"
77                         % self.request_id)
78                     self.update_response_to_db(self.request_id, self.data.get("requestStatus"), "none", "none",
79                                                "none", "none")
80                     continue
81                 for info in assignmentInfo:
82                     if info.get("key") in params:
83                         vim_info[info.get("key")] = info.get("value")
84                 if not vim_info.get("oof_directives"):
85                     logger.warn("Missing flavor info as no directive found in response")
86                     self.update_response_to_db(self.request_id,
87                                                self.data.get("requestStatus"), "none", "none",
88                                                "none", "none")
89                     continue
90                 vduinfo = self.get_info_from_directives(
91                     vim_info['oof_directives'])
92                 if not vduinfo:
93                     self.update_response_to_db(self.request_id,
94                                                self.data.get("requestStatus"), "none", "none",
95                                                "none", "none")
96                     return
97                 else:
98                     cloud_owner = placement.get("solution").get("cloudOwner") \
99                         if placement.get("solution").get("cloudOwner") \
100                         else vim_info.get("cloudOwner")
101                     location_id = vim_info.get("locationId")
102                     if not cloud_owner or not location_id:
103                         self.update_response_to_db(self.request_id,
104                                                    self.data.get("requestStatus"), "none", "none",
105                                                    "none", "none")
106                         return
107                     vim_id = vim_info['vimId'] if vim_info.get('vimId') \
108                         else cloud_owner + "_" + location_id
109                     self.update_response_to_db(requestId=self.request_id,
110                                                requestStatus=self.data.get("requestStatus"),
111                                                vimId=vim_id,
112                                                cloudOwner=cloud_owner,
113                                                cloudRegionId=values.ignore_case_get(vim_info, "locationId"),
114                                                vduInfo=vduinfo)
115                     logger.debug(
116                         "Placement solution has been stored for request %s " % self.request_id)
117                     return "Done"
118
119     def get_info_from_directives(self, directives):
120         vduinfo = []
121         for directive in directives.get("directives"):
122             if directive.get("type") == "tosca.nodes.nfv.Vdu.Compute":
123                 vdu = {"vduName": directive.get("id")}
124                 other_directives = []
125                 for item in directive.get("directives"):
126                     if item.get("type") == "flavor_directives":
127                         for attribute in item.get("attributes"):
128                             vdu[attribute.get("attribute_name")] = attribute.get("attribute_value")
129                     else:
130                         other_directives.append(item)
131                 if other_directives:
132                     other_directives = json.dumps(other_directives)
133                 vdu['directive'] = other_directives
134                 vduinfo.append(vdu)
135             else:
136                 logger.warn("Find unrecognized type %s " % directive.get("type"))
137         if vduinfo:
138             vduinfo = json.dumps(vduinfo)
139             return vduinfo
140         else:
141             logger.warn("No OOF directive for VDU")
142             return None
143
144     def update_response_to_db(self, requestId, requestStatus, vimId, cloudOwner,
145                               cloudRegionId, vduInfo):
146         OOFDataModel.objects.filter(request_id=requestId).update(
147             request_status=requestStatus,
148             vim_id=vimId,
149             cloud_owner=cloudOwner,
150             cloud_region_id=cloudRegionId,
151             vdu_info=vduInfo
152         )