Containerization feature of SO
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / onap / so / bpmn / common / scripts / OofHoming.groovy
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.so.bpmn.common.scripts
21 import org.onap.so.bpmn.core.UrnPropertiesReader
22 import org.camunda.bpm.engine.delegate.BpmnError
23 import org.camunda.bpm.engine.delegate.DelegateExecution
24
25 import org.onap.so.bpmn.common.scripts.AaiUtil
26 import org.onap.so.bpmn.common.scripts.ExceptionUtil
27 import org.onap.so.bpmn.common.scripts.SDNCAdapterUtils
28 import org.onap.so.bpmn.core.domain.CloudFlavor
29 import org.onap.so.bpmn.core.domain.InventoryType
30 import org.onap.so.bpmn.core.domain.Resource
31 import org.onap.so.bpmn.core.domain.ResourceType
32 import org.onap.so.bpmn.core.domain.ServiceDecomposition
33 import org.onap.so.bpmn.core.domain.Subscriber
34 import org.onap.so.bpmn.core.domain.VnfResource
35 import org.onap.so.bpmn.core.json.JsonUtils
36 import org.onap.so.logger.MsoLogger
37 import org.onap.so.rest.APIResponse
38 import org.onap.so.rest.RESTClient
39 import org.onap.so.rest.RESTConfig
40 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
41
42 import org.json.JSONArray
43 import org.json.JSONObject
44
45 import static org.onap.so.bpmn.common.scripts.GenericUtils.*
46
47 /**
48  * This class contains the scripts used
49  * by the OOF Homing Subflow building block. The
50  * subflow attempts to home the provided
51  * resources by calling OOF.
52  */
53 class OofHoming extends AbstractServiceTaskProcessor {
54
55         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, OofHoming.class);
56     ExceptionUtil exceptionUtil = new ExceptionUtil()
57     JsonUtils jsonUtil = new JsonUtils()
58     OofUtils oofUtils = new OofUtils(this)
59
60     /**
61      * This method validates the incoming variables.
62      * The method then prepares the OOF request
63      * and posts it to OOF's rest api.
64      *
65      * @param execution
66      */
67     public void callOof(DelegateExecution execution) {
68         def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
69         execution.setVariable("prefix", "HOME_")
70         utils.log("DEBUG", "*** Started Homing Call OOF ***", isDebugEnabled)
71         try {
72             execution.setVariable("rollbackData", null)
73             execution.setVariable("rolledBack", false)
74
75             String requestId = execution.getVariable("msoRequestId")
76             utils.log("DEBUG", "Incoming Request Id is: " + requestId, isDebugEnabled)
77             String serviceInstanceId = execution.getVariable("serviceInstanceId")
78             utils.log("DEBUG", "Incoming Service Instance Id is: " + serviceInstanceId, isDebugEnabled)
79             String serviceInstanceName = execution.getVariable("serviceInstanceName")
80             utils.log("DEBUG", "Incoming Service Instance Name is: " + serviceInstanceName, isDebugEnabled)
81             ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
82             utils.log("DEBUG", "Incoming Service Decomposition is: " + serviceDecomposition, isDebugEnabled)
83             String subscriberInfo = execution.getVariable("subscriberInfo")
84             utils.log("DEBUG", "Incoming Subscriber Information is: " + subscriberInfo, isDebugEnabled)
85             Map customerLocation = execution.getVariable("customerLocation")
86             utils.log("DEBUG", "Incoming Customer Location is: " + customerLocation.toString(), isDebugEnabled)
87             String cloudOwner = execution.getVariable("cloudOwner")
88             utils.log("DEBUG", "Incoming cloudOwner is: " + cloudOwner, isDebugEnabled)
89             String cloudRegionId = execution.getVariable("cloudRegionId")
90             utils.log("DEBUG", "Incoming cloudRegionId is: " + cloudRegionId, isDebugEnabled)
91
92             if (isBlank(requestId) ||
93                     isBlank(serviceInstanceId) ||
94                     isBlank(serviceInstanceName) ||
95                     isBlank(serviceDecomposition.toString()) ||
96                     isBlank(customerLocation.toString())) {
97                 exceptionUtil.buildAndThrowWorkflowException(execution, 4000,
98                         "A required input variable is missing or null")
99             } else {
100                 Subscriber subscriber = null
101                 if (isBlank(subscriberInfo)) {
102                     subscriber = new Subscriber("", "", "")
103                 } else {
104                 String subId = jsonUtil.getJsonValue(subscriberInfo, "globalSubscriberId")
105                 String subName = jsonUtil.getJsonValue(subscriberInfo, "subscriberName")
106                 String subCommonSiteId = ""
107                 if (jsonUtil.jsonElementExist(subscriberInfo, "subscriberCommonSiteId")) {
108                     subCommonSiteId = jsonUtil.getJsonValue(subscriberInfo, "subscriberCommonSiteId")
109                 }
110                     subscriber = new Subscriber(subId, subName, subCommonSiteId)
111                 }
112
113                 //Authentication
114                 def authHeader = ""
115                 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
116                 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
117                                 
118
119                                 
120                                 
121                 String basicAuthValue = utils.encrypt(basicAuth, msokey)
122                 if (basicAuthValue != null) {
123                     utils.log("DEBUG", "Obtained BasicAuth username and password for OOF Adapter: " + basicAuthValue,
124                             isDebugEnabled)
125                     try {
126                         authHeader = utils.getBasicAuth(basicAuthValue, msokey)
127                         execution.setVariable("BasicAuthHeaderValue", authHeader)
128                     } catch (Exception ex) {
129                         utils.log("DEBUG", "Unable to encode username and password string: " + ex, isDebugEnabled)
130                         exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
131                                 "encode username and password string")
132                     }
133                 } else {
134                     utils.log("DEBUG", "Unable to obtain BasicAuth - BasicAuth value null", isDebugEnabled)
135                     exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
136                             "value null")
137                 }
138
139                 //Prepare Callback
140                 String timeout = execution.getVariable("timeout")
141                 if (isBlank(timeout)) {                                 
142                     timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
143                     if (isBlank(timeout)) {
144                         timeout = "PT30M"
145                     }
146                 }
147                 utils.log("DEBUG", "Async Callback Timeout will be: " + timeout, isDebugEnabled)
148
149                 execution.setVariable("timeout", timeout)
150                 execution.setVariable("correlator", requestId)
151                 execution.setVariable("messageType", "oofResponse")
152
153                 //Build Request & Call OOF
154                 String oofRequest = oofUtils.buildRequest(execution, requestId, serviceDecomposition,
155                         subscriber, customerLocation)
156                 execution.setVariable("oofRequest", oofRequest)
157                 utils.log("DEBUG", "OOF Request is: " + oofRequest, isDebugEnabled)
158
159                 String endpoint = UrnPropertiesReader.getVariable("mso.oof.service.agnostic.endpoint", execution);
160                 String host = UrnPropertiesReader.getVariable("mso.oof.service.agnostic.host", execution); 
161                 String url = host + endpoint
162                 utils.log("DEBUG", "Posting to OOF Url: " + url, isDebugEnabled)
163
164                 logDebug("URL to be used is: " + url, isDebugEnabled)
165
166                 RESTConfig config = new RESTConfig(url)
167                 RESTClient client = new RESTClient(config).addAuthorizationHeader(authHeader).
168                         addHeader("Content-Type", "application/json")
169                 APIResponse response = client.httpPost(oofRequest)
170
171                 int responseCode = response.getStatusCode()
172                 logDebug("OOF sync response code is: " + responseCode, isDebugEnabled)
173                 String syncResponse = response.getResponseBodyAsString()
174                 execution.setVariable("syncResponse", syncResponse)
175                 logDebug("OOF sync response is: " + syncResponse, isDebugEnabled)
176
177                                 if(responseCode != 202){
178                                         exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
179                                 }
180
181                 utils.log("DEBUG", "*** Completed Homing Call OOF ***", isDebugEnabled)
182             }
183         } catch (BpmnError b) {
184             throw b
185         } catch (Exception e) {
186                         msoLogger.error(e);
187             exceptionUtil.buildAndThrowWorkflowException(execution, 2500,
188                     "Internal Error - Occured in Homing callOof: " + e.getMessage())
189         }
190     }
191
192     /**
193      * This method processes the callback response
194      * and the contained homing solution. It sets
195      * homing solution assignment and license
196      * information to the corresponding resources
197      *
198      * @param execution
199      */
200     public void processHomingSolution(DelegateExecution execution) {
201         def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
202         utils.log("DEBUG", "*** Started Homing Process Homing Solution ***", isDebugEnabled)
203         try {
204             String response = execution.getVariable("asyncCallbackResponse")
205             utils.log("DEBUG", "OOF Async Callback Response is: " + response, isDebugEnabled)
206             utils.logAudit("OOF Async Callback Response is: " + response)
207
208             oofUtils.validateCallbackResponse(execution, response)
209             String placements = jsonUtil.getJsonValue(response, "solutions.placementSolutions")
210             utils.log("DEBUG", "****** Solution Placements: " + placements + " *****", isDebugEnabled)
211
212             ServiceDecomposition decomposition = execution.getVariable("serviceDecomposition")
213             utils.log("DEBUG", "Service Decomposition: " + decomposition, isDebugEnabled)
214
215             List<Resource> resourceList = decomposition.getServiceResources()
216             JSONArray arr = new JSONArray(placements)
217             for (int i = 0; i < arr.length(); i++) {
218                 JSONArray arrSol = arr.getJSONArray(i)
219                 for (int j = 0; j < arrSol.length(); j++) {
220                     JSONObject placement = arrSol.getJSONObject(j)
221                     utils.log("DEBUG", "****** Placement Solution is: " + placement + " *****", "true")
222                     String jsonServiceResourceId = placement.getString("serviceResourceId")
223                     String jsonResourceModuleName = placement.getString("resourceModuleName")
224                     for (Resource resource : resourceList) {
225                         String serviceResourceId = resource.getResourceId()
226                         String resourceModuleName = ""
227                         if (resource.getResourceType() == ResourceType.ALLOTTED_RESOURCE ||
228                             resource.getResourceType() == ResourceType.VNF) {
229                             resourceModuleName = resource.getNfFunction()
230                             }
231                         if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId) ||
232                             resourceModuleName.equalsIgnoreCase(jsonResourceModuleName)) {
233                             JSONObject solution = placement.getJSONObject("solution")
234                             String solutionType = solution.getString("identifierType")
235                             String inventoryType = ""
236                             if (solutionType.equalsIgnoreCase("serviceInstanceId")) {
237                                 inventoryType = "service"
238                             } else {
239                                 inventoryType = "cloud"
240                             }
241                             resource.getHomingSolution().setInventoryType(InventoryType.valueOf(inventoryType))
242
243                             // TODO Deal with Placement Solutions & Assignment Info here
244                             JSONArray assignmentArr = placement.getJSONArray("assignmentInfo")
245                             Integer arrayIndex = 0
246                             Integer flavorsIndex = null
247                             Boolean foundFlavors = false
248                             String flavors = null
249                             Map<String, String> flavorsMap = null
250                             ArrayList<CloudFlavor> flavorsArrayList = new ArrayList<CloudFlavor>()
251                             assignmentArr.each { element ->
252                                 JSONObject jsonObject = new JSONObject(element.toString())
253                                 if (jsonUtil.getJsonRawValue(jsonObject.toString(), "key") == "flavors") {
254                                     flavors = jsonUtil.getJsonRawValue(jsonObject.toString(), "value")
255                                     foundFlavors = true
256                                     flavorsIndex = arrayIndex
257                                 } else {
258                                     arrayIndex += 1
259                                 }
260                             }
261                             if (foundFlavors) {
262                                 assignmentArr.remove(flavorsIndex)
263                                 flavorsMap = jsonUtil.jsonStringToMap(execution, flavors.toString())
264                                 flavorsMap.each { label, flavor ->
265                                     CloudFlavor cloudFlavor = new CloudFlavor(label, flavor)
266                                     flavorsArrayList.add(cloudFlavor)
267                                 }
268                             }
269                             Map<String, String> assignmentMap = jsonUtil.entryArrayToMap(execution,
270                                     assignmentArr.toString(), "key", "value")
271                             String cloudOwner = assignmentMap.get("cloudOwner")
272                             String cloudRegionId = assignmentMap.get("locationId")
273                             resource.getHomingSolution().setCloudOwner(cloudOwner)
274                             resource.getHomingSolution().setCloudRegionId(cloudRegionId)
275                             if (flavorsArrayList != null && flavorsArrayList.size != 0) {
276                                 resource.getHomingSolution().setFlavors(flavorsArrayList)
277                                 execution.setVariable(cloudRegionId + "_flavorList", flavorsArrayList)
278                                 utils.log("DEBUG", "***** _flavorList is: " + flavorsArrayList.toString() +
279                                         " *****", "true")
280                             }
281
282                             if (inventoryType.equalsIgnoreCase("service")) {
283                                 resource.getHomingSolution().setRehome(assignmentMap.get("isRehome").toBoolean())
284                                 VnfResource vnf = new VnfResource()
285                                 vnf.setVnfHostname(assignmentMap.get("vnfHostName"))
286                                 resource.getHomingSolution().setVnf(vnf)
287                                 resource.getHomingSolution().setServiceInstanceId(solution.getJSONArray("identifiers")[0].toString())
288                             }
289                         }
290                     }
291                 }
292                 if (JsonUtils.jsonElementExist(response, "solutions.licenseSolutions")) {
293                     String licenseSolutions = jsonUtil.getJsonValue(response, "solutions.licenseSolutions")
294                     JSONArray licenseArr = new JSONArray(licenseSolutions)
295                     for (int l = 0; l < licenseArr.length(); l++) {
296                         JSONObject license = licenseArr.getJSONObject(l)
297                         String jsonServiceResourceId = license.getString("serviceResourceId")
298                         for (Resource resource : resourceList) {
299                             String serviceResourceId = resource.getResourceId()
300                             if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
301                                 String jsonEntitlementPoolList = jsonUtil.getJsonValue(license.toString(), "entitlementPoolUUID")
302                                 List<String> entitlementPoolList = jsonUtil.StringArrayToList(execution, jsonEntitlementPoolList)
303                                 resource.getHomingSolution().getLicense().setEntitlementPoolList(entitlementPoolList)
304
305                                 String jsonLicenseKeyGroupList = jsonUtil.getJsonValue(license.toString(), "licenseKeyGroupUUID")
306                                 List<String> licenseKeyGroupList = jsonUtil.StringArrayToList(execution, jsonLicenseKeyGroupList)
307                                 resource.getHomingSolution().getLicense().setLicenseKeyGroupList(licenseKeyGroupList)
308                             }
309                         }
310                     }
311                 }
312             }
313             execution.setVariable("serviceDecomposition", decomposition)
314             execution.setVariable("homingSolution", placements) //TODO - can be removed as output variable
315
316             utils.log("DEBUG", "*** Completed Homing Process Homing Solution ***", isDebugEnabled)
317         } catch (BpmnError b) {
318             throw b
319         } catch (Exception e) {
320                         msoLogger.error(e);
321             exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occurred in Homing ProcessHomingSolution")
322         }
323     }
324
325     /**
326      * This method logs the start of DHVCreateService
327      * to make debugging easier.
328      *
329      * @param - execution
330      */
331     public String logStart(DelegateExecution execution) {
332         def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
333         String requestId = execution.getVariable("testReqId")
334         if (isBlank(requestId)) {
335             requestId = execution.getVariable("msoRequestId")
336         }
337         execution.setVariable("DHVCS_requestId", requestId)
338         utils.log("DEBUG", "***** STARTED Homing Subflow for request: " + requestId + " *****", "true")
339         utils.log("DEBUG", "****** Homing Subflow Global Debug Enabled: " + isDebugEnabled + " *****", "true")
340         utils.logAudit("***** STARTED Homing Subflow for request: " + requestId + " *****")
341     }
342
343     /**
344      * Auto-generated method stub
345      */
346     public void preProcessRequest(DelegateExecution execution) {}
347         // Not Implemented Method
348 }