2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 Intel Corp. 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.onap.so.bpmn.common.scripts
22 import org.onap.so.bpmn.core.UrnPropertiesReader
23 import org.camunda.bpm.engine.delegate.BpmnError
24 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.onap.so.bpmn.core.domain.InventoryType
27 import org.onap.so.bpmn.core.domain.Resource
28 import org.onap.so.bpmn.core.domain.ResourceType
29 import org.onap.so.bpmn.core.domain.ServiceDecomposition
30 import org.onap.so.bpmn.core.domain.Subscriber
31 import org.onap.so.bpmn.core.domain.VnfResource
32 import org.onap.so.bpmn.core.json.JsonUtils
33 import org.onap.so.client.HttpClient
34 import org.onap.so.logger.MsoLogger
35 import org.onap.so.db.catalog.beans.CloudIdentity
36 import org.onap.so.db.catalog.beans.CloudSite
38 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
39 import org.onap.so.utils.TargetEntity
41 import org.json.JSONArray
42 import org.json.JSONObject
43 import org.springframework.web.util.UriUtils
45 import static org.onap.so.bpmn.common.scripts.GenericUtils.*
47 import javax.ws.rs.core.Response
50 * This class contains the scripts used
51 * by the OOF Homing Subflow building block. The
52 * subflow attempts to home the provided
53 * resources by calling OOF.
55 class OofHoming extends AbstractServiceTaskProcessor {
57 ExceptionUtil exceptionUtil = new ExceptionUtil()
58 JsonUtils jsonUtil = new JsonUtils()
59 OofUtils oofUtils = new OofUtils(this)
62 * This method validates the incoming variables.
63 * The method then prepares the OOF request
64 * and posts it to OOF's rest api.
68 public void callOof(DelegateExecution execution) {
69 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
70 execution.setVariable("prefix", "HOME_")
71 utils.log("DEBUG", "*** Started Homing Call OOF ***", isDebugEnabled)
73 execution.setVariable("rollbackData", null)
74 execution.setVariable("rolledBack", false)
76 String requestId = execution.getVariable("msoRequestId")
77 utils.log("DEBUG", "Incoming Request Id is: " + requestId, isDebugEnabled)
78 String serviceInstanceId = execution.getVariable("serviceInstanceId")
79 utils.log("DEBUG", "Incoming Service Instance Id is: " + serviceInstanceId, isDebugEnabled)
80 String serviceInstanceName = execution.getVariable("serviceInstanceName")
81 utils.log("DEBUG", "Incoming Service Instance Name is: " + serviceInstanceName, isDebugEnabled)
82 ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
83 utils.log("DEBUG", "Incoming Service Decomposition is: " + serviceDecomposition, isDebugEnabled)
84 String subscriberInfo = execution.getVariable("subscriberInfo")
85 utils.log("DEBUG", "Incoming Subscriber Information is: " + subscriberInfo, isDebugEnabled)
86 Map customerLocation = execution.getVariable("customerLocation")
87 utils.log("DEBUG", "Incoming Customer Location is: " + customerLocation.toString(), isDebugEnabled)
88 String cloudOwner = execution.getVariable("cloudOwner")
89 utils.log("DEBUG", "Incoming cloudOwner is: " + cloudOwner, isDebugEnabled)
90 String cloudRegionId = execution.getVariable("cloudRegionId")
91 utils.log("DEBUG", "Incoming cloudRegionId is: " + cloudRegionId, isDebugEnabled)
93 if (isBlank(requestId) ||
94 isBlank(serviceInstanceId) ||
95 isBlank(serviceInstanceName) ||
96 isBlank(serviceDecomposition.toString()) ||
97 isBlank(customerLocation.toString())) {
98 exceptionUtil.buildAndThrowWorkflowException(execution, 4000,
99 "A required input variable is missing or null")
101 Subscriber subscriber = null
102 if (isBlank(subscriberInfo)) {
103 subscriber = new Subscriber("", "", "")
105 String subId = jsonUtil.getJsonValue(subscriberInfo, "globalSubscriberId")
106 String subName = jsonUtil.getJsonValue(subscriberInfo, "subscriberName")
107 String subCommonSiteId = ""
108 if (jsonUtil.jsonElementExist(subscriberInfo, "subscriberCommonSiteId")) {
109 subCommonSiteId = jsonUtil.getJsonValue(subscriberInfo, "subscriberCommonSiteId")
111 subscriber = new Subscriber(subId, subName, subCommonSiteId)
116 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
117 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
119 String basicAuthValue = utils.encrypt(basicAuth, msokey)
120 if (basicAuthValue != null) {
121 utils.log("DEBUG", "Obtained BasicAuth username and password for OOF Adapter: " + basicAuthValue,
124 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
125 execution.setVariable("BasicAuthHeaderValue", authHeader)
126 } catch (Exception ex) {
127 utils.log("DEBUG", "Unable to encode username and password string: " + ex, isDebugEnabled)
128 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
129 "encode username and password string")
132 utils.log("DEBUG", "Unable to obtain BasicAuth - BasicAuth value null", isDebugEnabled)
133 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
138 String timeout = execution.getVariable("timeout")
139 if (isBlank(timeout)) {
140 timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
141 if (isBlank(timeout)) {
145 utils.log("DEBUG", "Async Callback Timeout will be: " + timeout, isDebugEnabled)
147 execution.setVariable("timeout", timeout)
148 execution.setVariable("correlator", requestId)
149 execution.setVariable("messageType", "oofResponse")
151 //Build Request & Call OOF
152 String oofRequest = oofUtils.buildRequest(execution, requestId, serviceDecomposition,
153 subscriber, customerLocation)
154 execution.setVariable("oofRequest", oofRequest)
155 utils.log("DEBUG", "OOF Request is: " + oofRequest, isDebugEnabled)
157 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
158 utils.log("DEBUG", "Posting to OOF Url: " + urlString, isDebugEnabled)
161 URL url = new URL(urlString);
162 HttpClient httpClient = new HttpClient(url, "application/json", TargetEntity.SNIRO)
163 httpClient.addAdditionalHeader("Authorization", authHeader)
164 Response httpResponse = httpClient.post(oofRequest)
166 int responseCode = httpResponse.getStatus()
167 logDebug("OOF sync response code is: " + responseCode, isDebugEnabled)
170 utils.log("DEBUG", "*** Completed Homing Call OOF ***", isDebugEnabled)
172 } catch (BpmnError b) {
174 } catch (Exception e) {
176 exceptionUtil.buildAndThrowWorkflowException(execution, 2500,
177 "Internal Error - Occured in Homing callOof: " + e.getMessage())
182 * This method processes the callback response
183 * and the contained homing solution. It sets
184 * homing solution assignment and license
185 * information to the corresponding resources
189 public void processHomingSolution(DelegateExecution execution) {
190 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
191 utils.log("DEBUG", "*** Started Homing Process Homing Solution ***", isDebugEnabled)
193 String response = execution.getVariable("asyncCallbackResponse")
194 utils.log("DEBUG", "OOF Async Callback Response is: " + response, isDebugEnabled)
195 utils.logAudit("OOF Async Callback Response is: " + response)
197 oofUtils.validateCallbackResponse(execution, response)
198 String placements = jsonUtil.getJsonValue(response, "solutions.placementSolutions")
199 utils.log("DEBUG", "****** Solution Placements: " + placements + " *****", isDebugEnabled)
201 ServiceDecomposition decomposition = execution.getVariable("serviceDecomposition")
202 utils.log("DEBUG", "Service Decomposition: " + decomposition, isDebugEnabled)
204 List<Resource> resourceList = decomposition.getServiceResources()
205 JSONArray arr = new JSONArray(placements)
206 for (int i = 0; i < arr.length(); i++) {
207 JSONArray arrSol = arr.getJSONArray(i)
208 for (int j = 0; j < arrSol.length(); j++) {
209 JSONObject placement = arrSol.getJSONObject(j)
210 utils.log("DEBUG", "****** Placement Solution is: " + placement + " *****", "true")
211 String jsonServiceResourceId = placement.getString("serviceResourceId")
212 String jsonResourceModuleName = placement.getString("resourceModuleName")
213 for (Resource resource : resourceList) {
214 String serviceResourceId = resource.getResourceId()
215 String resourceModuleName = ""
216 if (resource.getResourceType() == ResourceType.ALLOTTED_RESOURCE ||
217 resource.getResourceType() == ResourceType.VNF) {
218 resourceModuleName = resource.getNfFunction()
220 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId) ||
221 resourceModuleName.equalsIgnoreCase(jsonResourceModuleName)) {
222 JSONObject solution = placement.getJSONObject("solution")
223 String solutionType = solution.getString("identifierType")
224 String inventoryType = ""
225 if (solutionType.equalsIgnoreCase("serviceInstanceId")) {
226 inventoryType = "service"
228 inventoryType = "cloud"
230 resource.getHomingSolution().setInventoryType(InventoryType.valueOf(inventoryType))
232 JSONArray assignmentArr = placement.getJSONArray("assignmentInfo")
233 String oofDirectives = null
234 assignmentArr.each { element ->
235 JSONObject jsonObject = new JSONObject(element.toString())
236 if (jsonUtil.getJsonRawValue(jsonObject.toString(), "key") == "oof_directives") {
237 oofDirectives = jsonUtil.getJsonRawValue(jsonObject.toString(), "value")
240 Map<String, String> assignmentMap = jsonUtil.entryArrayToMap(execution,
241 assignmentArr.toString(), "key", "value")
242 String cloudOwner = assignmentMap.get("cloudOwner")
243 String cloudRegionId = assignmentMap.get("locationId")
244 resource.getHomingSolution().setCloudOwner(cloudOwner)
245 resource.getHomingSolution().setCloudRegionId(cloudRegionId)
247 CloudSite cloudSite = new CloudSite()
248 cloudSite.setId(cloudRegionId)
249 cloudSite.setRegionId(cloudRegionId)
250 String orchestrator = execution.getVariable("orchestrator")
251 if ((orchestrator != null) || (orchestrator != "")) {
252 cloudSite.setOrchestrator(orchestrator)
255 CloudIdentity cloudIdentity = new CloudIdentity()
256 cloudIdentity.setId(cloudRegionId)
258 String msbHost = oofUtils.getMsbHost(execution)
259 String multicloudApiEndpoint = UrnPropertiesReader
260 .getVariable("mso.multicloud.api.endpoint", execution,
261 "/api/multicloud-titaniumcloud/v1")
262 cloudIdentity.setIdentityUrl(msbHost + multicloudApiEndpoint
263 + "/" + cloudOwner + "/" +
264 cloudRegionId + "/infra_workload")
266 cloudSite.setIdentityService(cloudIdentity)
268 // Set cloudsite in catalog DB here
269 oofUtils.createCloudSiteCatalogDb(cloudSite)
271 if (oofDirectives != null && oofDirectives != "") {
272 resource.getHomingSolution().setOofDirectives(oofDirectives)
273 execution.setVariable("oofDirectives", oofDirectives)
274 utils.log("DEBUG", "***** OofDirectives is: " + oofDirectives +
278 if (inventoryType.equalsIgnoreCase("service")) {
279 resource.getHomingSolution().setRehome(assignmentMap.get("isRehome").toBoolean())
280 VnfResource vnf = new VnfResource()
281 vnf.setVnfHostname(assignmentMap.get("vnfHostName"))
282 resource.getHomingSolution().setVnf(vnf)
283 resource.getHomingSolution().setServiceInstanceId(solution.getJSONArray("identifiers")[0].toString())
288 if (JsonUtils.jsonElementExist(response, "solutions.licenseSolutions")) {
289 String licenseSolutions = jsonUtil.getJsonValue(response, "solutions.licenseSolutions")
290 JSONArray licenseArr = new JSONArray(licenseSolutions)
291 for (int l = 0; l < licenseArr.length(); l++) {
292 JSONObject license = licenseArr.getJSONObject(l)
293 String jsonServiceResourceId = license.getString("serviceResourceId")
294 for (Resource resource : resourceList) {
295 String serviceResourceId = resource.getResourceId()
296 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
297 String jsonEntitlementPoolList = jsonUtil.getJsonValue(license.toString(), "entitlementPoolUUID")
298 List<String> entitlementPoolList = jsonUtil.StringArrayToList(execution, jsonEntitlementPoolList)
299 resource.getHomingSolution().getLicense().setEntitlementPoolList(entitlementPoolList)
301 String jsonLicenseKeyGroupList = jsonUtil.getJsonValue(license.toString(), "licenseKeyGroupUUID")
302 List<String> licenseKeyGroupList = jsonUtil.StringArrayToList(execution, jsonLicenseKeyGroupList)
303 resource.getHomingSolution().getLicense().setLicenseKeyGroupList(licenseKeyGroupList)
309 execution.setVariable("serviceDecomposition", decomposition)
310 execution.setVariable("homingSolution", placements) //TODO - can be removed as output variable
312 utils.log("DEBUG", "*** Completed Homing Process Homing Solution ***", isDebugEnabled)
313 } catch (BpmnError b) {
315 } catch (Exception e) {
317 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occurred in Homing ProcessHomingSolution")
322 * This method logs the start of DHVCreateService
323 * to make debugging easier.
327 public String logStart(DelegateExecution execution) {
328 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
329 String requestId = execution.getVariable("testReqId")
330 if (isBlank(requestId)) {
331 requestId = execution.getVariable("msoRequestId")
333 execution.setVariable("DHVCS_requestId", requestId)
334 utils.log("DEBUG", "***** STARTED Homing Subflow for request: " + requestId + " *****", "true")
335 utils.log("DEBUG", "****** Homing Subflow Global Debug Enabled: " + isDebugEnabled + " *****", "true")
336 utils.logAudit("***** STARTED Homing Subflow for request: " + requestId + " *****")
340 * Auto-generated method stub
342 public void preProcessRequest(DelegateExecution execution) {}
343 // Not Implemented Method
346 * Constructs a workflow message callback URL for the specified message type and correlator.
347 * This type of callback URL is used when a workflow wants an MSO adapter (like the SDNC
348 * adapter) to call it back. In other words, this is for callbacks internal to the MSO
349 * complex. Use <code>createWorkflowMessageAdapterCallbackURL</code> if the callback
350 * will come from outside the MSO complex.
351 * @param endpoint endpoint address to contruct URL from
352 * @param messageType the message type (e.g. SDNCAResponse or VNFAResponse)
353 * @param correlator the correlator value (e.g. a request ID)
355 public String createHomingCallbackURL(String endpoint, String messageType, String correlator) {
357 if (endpoint == null || endpoint.isEmpty()) {
358 ExceptionUtil exceptionUtil = new ExceptionUtil()
359 exceptionUtil.buildAndThrowWorkflowException(execution, 2000,
360 'mso:workflow:message:endpoint was not passed in')
363 utils.log("DEBUG", "passed in endpoint: " + endpoint + " *****", "true")
365 while (endpoint.endsWith('/')) {
366 endpoint = endpoint.substring(0, endpoint.length() - 1)
368 utils.log("DEBUG", "processed endpoint: " + endpoint + " *****", "true")
371 '/' + UriUtils.encodePathSegment(messageType, 'UTF-8') +
372 '/' + UriUtils.encodePathSegment(correlator, 'UTF-8')
373 } catch (Exception ex) {
374 utils.log("DEBUG", "createCallbackURL Exception: " + ex + " *****", "true")