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