d63ee74eec6d8ca2d6f7801131b26238dc811f58
[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                                                    )
116                         logger.debug(
117                             "Placement solution has been stored for request %s "
118                             % self.request_id)
119                         return "Done"
120
121     def get_info_from_directives(self, directives):
122         vduinfo = []
123         for directive in directives.get("directives"):
124             if directive.get("type") == "tocsa.nodes.nfv.Vdu.Compute":
125                 vdu = {"vduName": directive.get("id")}
126                 other_directives = []
127                 for item in directive.get("directives"):
128                     if item.get("type") == "flavor_directives":
129                         for attribute in item.get("attributes"):
130                             vdu[attribute.get("attribute_name")] = attribute.get("attribute_value")
131                     else:
132                         other_directives.append(item)
133                 if other_directives:
134                     other_directives = json.dumps(other_directives)
135                 vdu['directive'] = other_directives
136                 vduinfo.append(vdu)
137             else:
138                 logger.warn("Find unrecognized type %s " % directive.get("type"))
139         if vduinfo:
140             vduinfo = json.dumps(vduinfo)
141             return vduinfo
142         else:
143             logger.warn("No OOF directive for VDU")
144             return None
145
146     def update_response_to_db(self, requestId, requestStatus, vimId, cloudOwner,
147                               cloudRegionId, vduInfo):
148         OOFDataModel.objects.filter(request_id=requestId).update(
149             request_status=requestStatus,
150             vim_id=vimId,
151             cloud_owner=cloudOwner,
152             cloud_region_id=cloudRegionId,
153             vdu_info=vduInfo
154         )