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.db.catalog.beans.AuthenticationType
34 import org.onap.so.db.catalog.beans.CloudIdentity
35 import org.onap.so.db.catalog.beans.CloudSite
36 import org.onap.so.db.catalog.beans.HomingInstance
37 import org.onap.so.db.catalog.beans.ServerType
38 import org.onap.so.rest.APIResponse
39 import org.onap.so.rest.RESTClient
40 import org.onap.so.rest.RESTConfig
42 import org.json.JSONArray
43 import org.json.JSONObject
44 import org.springframework.web.util.UriUtils
46 import static org.onap.so.bpmn.common.scripts.GenericUtils.*
49 * This class contains the scripts used
50 * by the OOF Homing Subflow building block. The
51 * subflow attempts to home the provided
52 * resources by calling OOF.
54 class OofHoming extends AbstractServiceTaskProcessor {
56 ExceptionUtil exceptionUtil = new ExceptionUtil()
57 JsonUtils jsonUtil = new JsonUtils()
58 OofUtils oofUtils = new OofUtils(this)
61 * This method validates the incoming variables.
62 * The method then prepares the OOF request
63 * and posts it to OOF's rest api.
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)
72 execution.setVariable("rollbackData", null)
73 execution.setVariable("rolledBack", false)
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)
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")
100 Subscriber subscriber = null
101 if (isBlank(subscriberInfo)) {
102 subscriber = new Subscriber("", "", "")
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")
110 subscriber = new Subscriber(subId, subName, subCommonSiteId)
115 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
116 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
118 String basicAuthValue = utils.encrypt(basicAuth, msokey)
119 if (basicAuthValue != null) {
120 utils.log("DEBUG", "Obtained BasicAuth username and password for OOF Adapter: " + basicAuthValue,
123 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
124 execution.setVariable("BasicAuthHeaderValue", authHeader)
125 } catch (Exception ex) {
126 utils.log("DEBUG", "Unable to encode username and password string: " + ex, isDebugEnabled)
127 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
128 "encode username and password string")
131 utils.log("DEBUG", "Unable to obtain BasicAuth - BasicAuth value null", isDebugEnabled)
132 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
137 String timeout = execution.getVariable("timeout")
138 if (isBlank(timeout)) {
139 timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
140 if (isBlank(timeout)) {
144 utils.log("DEBUG", "Async Callback Timeout will be: " + timeout, isDebugEnabled)
146 execution.setVariable("timeout", timeout)
147 execution.setVariable("correlator", requestId)
148 execution.setVariable("messageType", "oofResponse")
150 //Build Request & Call OOF
151 String oofRequest = oofUtils.buildRequest(execution, requestId, serviceDecomposition,
152 subscriber, customerLocation)
153 execution.setVariable("oofRequest", oofRequest)
154 utils.log("DEBUG", "OOF Request is: " + oofRequest, isDebugEnabled)
156 String url = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
157 utils.log("DEBUG", "Posting to OOF Url: " + url, isDebugEnabled)
159 logDebug("URL to be used is: " + url, isDebugEnabled)
161 RESTConfig config = new RESTConfig(url)
162 RESTClient client = new RESTClient(config).addAuthorizationHeader(authHeader).
163 addHeader("Content-Type", "application/json")
164 APIResponse response = client.httpPost(oofRequest)
166 int responseCode = response.getStatusCode()
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)
172 if(responseCode != 202){
173 exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
176 utils.log("DEBUG", "*** Completed Homing Call OOF ***", isDebugEnabled)
178 } catch (BpmnError b) {
180 } catch (Exception e) {
182 exceptionUtil.buildAndThrowWorkflowException(execution, 2500,
183 "Internal Error - Occured in Homing callOof: " + e.getMessage())
188 * This method processes the callback response
189 * and the contained homing solution. It sets
190 * homing solution assignment and license
191 * information to the corresponding resources
195 public void processHomingSolution(DelegateExecution execution) {
196 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
197 utils.log("DEBUG", "*** Started Homing Process Homing Solution ***", isDebugEnabled)
199 String response = execution.getVariable("asyncCallbackResponse")
200 utils.log("DEBUG", "OOF Async Callback Response is: " + response, isDebugEnabled)
201 utils.logAudit("OOF Async Callback Response is: " + response)
203 oofUtils.validateCallbackResponse(execution, response)
204 String placements = jsonUtil.getJsonValue(response, "solutions.placementSolutions")
205 utils.log("DEBUG", "****** Solution Placements: " + placements + " *****", isDebugEnabled)
207 ServiceDecomposition decomposition = execution.getVariable("serviceDecomposition")
208 utils.log("DEBUG", "Service Decomposition: " + decomposition, isDebugEnabled)
210 List<Resource> resourceList = decomposition.getServiceResources()
211 JSONArray arr = new JSONArray(placements)
212 for (int i = 0; i < arr.length(); i++) {
213 JSONArray arrSol = arr.getJSONArray(i)
214 for (int j = 0; j < arrSol.length(); j++) {
215 JSONObject placement = arrSol.getJSONObject(j)
216 utils.log("DEBUG", "****** Placement Solution is: " + placement + " *****", "true")
217 String jsonServiceResourceId = jsonUtil.getJsonValue( placement.toString(), "serviceResourceId")
218 utils.log("DEBUG", "****** homing serviceResourceId is: " + jsonServiceResourceId + " *****", "true")
219 for (Resource resource : resourceList) {
220 String serviceResourceId = resource.getResourceId()
221 utils.log("DEBUG", "****** decomp serviceResourceId is: " + serviceResourceId + " *****", "true")
222 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
223 JSONObject solution = placement.getJSONObject("solution")
224 String solutionType = solution.getString("identifierType")
225 String inventoryType = ""
226 if (solutionType.equalsIgnoreCase("serviceInstanceId")) {
227 inventoryType = "service"
229 inventoryType = "cloud"
231 utils.log("DEBUG", "****** homing inventoryType is: " + inventoryType + " *****", "true")
232 resource.getHomingSolution().setInventoryType(InventoryType.valueOf(inventoryType))
234 JSONArray assignmentArr = placement.getJSONArray("assignmentInfo")
235 utils.log("DEBUG", "****** assignmentInfo is: " + assignmentArr.toString() + " *****", "true")
237 Map<String, String> assignmentMap = jsonUtil.entryArrayToMap(execution,
238 assignmentArr.toString(), "key", "value")
239 String oofDirectives = null
240 assignmentMap.each { key, value ->
241 utils.log("DEBUG", "****** element: " + key + " *****", "true")
242 if (key == "oof_directives") {
243 oofDirectives = value
244 utils.log("DEBUG", "****** homing oofDirectives: " + oofDirectives + " *****", "true")
247 String cloudOwner = assignmentMap.get("cloudOwner")
248 utils.log("DEBUG", "****** homing cloudOwner: " + cloudOwner + " *****", "true")
249 String cloudRegionId = assignmentMap.get("locationId")
250 utils.log("DEBUG", "****** homing cloudRegionId: " + cloudRegionId + " *****", "true")
251 resource.getHomingSolution().setCloudOwner(cloudOwner)
252 resource.getHomingSolution().setCloudRegionId(cloudRegionId)
254 CloudSite cloudSite = new CloudSite()
255 cloudSite.setId(cloudRegionId)
256 cloudSite.setRegionId(cloudRegionId)
257 String orchestrator = execution.getVariable("orchestrator")
258 if ((orchestrator != null) && (orchestrator != "")) {
259 cloudSite.setOrchestrator(orchestrator)
260 utils.log("DEBUG", "****** orchestrator: " + orchestrator + " *****", "true")
262 cloudSite.setOrchestrator("multicloud")
265 CloudIdentity cloudIdentity = new CloudIdentity()
266 cloudIdentity.setId(cloudRegionId)
267 cloudIdentity.setIdentityServerType(ServerType."KEYSTONE")
268 cloudIdentity.setAdminTenant("service")
269 cloudIdentity.setIdentityAuthenticationType(AuthenticationType.USERNAME_PASSWORD)
270 String msoMulticloudUserName = UrnPropertiesReader
271 .getVariable("mso.multicloud.api.password", execution,
273 String msoMulticloudPassword = UrnPropertiesReader
274 .getVariable("mso.multicloud.api.password", execution,
276 cloudIdentity.setMsoId(msoMulticloudUserName)
277 cloudIdentity.setMsoPass(msoMulticloudPassword)
279 String msbHost = oofUtils.getMsbHost(execution)
280 String multicloudApiEndpoint = UrnPropertiesReader
281 .getVariable("mso.multicloud.api.endpoint", execution,
282 "/api/multicloud-titaniumcloud/v1")
283 cloudIdentity.setIdentityUrl(msbHost + multicloudApiEndpoint
284 + "/" + cloudOwner + "/" +
285 cloudRegionId + "/infra_workload")
286 utils.log("DEBUG", "****** Cloud IdentityUrl: " + msbHost + multicloudApiEndpoint
287 + "/" + cloudOwner + "/" +
288 cloudRegionId + "/infra_workload"
290 utils.log("DEBUG", "****** CloudIdentity: " + cloudIdentity.toString()
292 cloudSite.setIdentityService(cloudIdentity)
293 utils.log("DEBUG", "****** CloudSite: " + cloudSite.toString()
296 // Set cloudsite in catalog DB here
297 oofUtils.createCloudSite(cloudSite, execution)
299 if (oofDirectives != null && oofDirectives != "") {
300 resource.getHomingSolution().setOofDirectives(oofDirectives)
301 execution.setVariable("oofDirectives", oofDirectives)
302 utils.log("DEBUG", "***** OofDirectives set to: " + oofDirectives +
306 // Set Homing Instance
307 String serviceInstanceId = decomposition.getServiceInstance().getInstanceId()
308 HomingInstance homingInstance = new HomingInstance()
309 homingInstance.setServiceInstanceId(serviceInstanceId)
310 homingInstance.setCloudOwner(cloudOwner)
311 homingInstance.setCloudRegionId(cloudRegionId)
312 if (oofDirectives != null && oofDirectives != "") {
313 homingInstance.setOofDirectives(oofDirectives)}
315 homingInstance.setOofDirectives("{}")
317 oofUtils.createHomingInstance(homingInstance, execution)
319 if (inventoryType.equalsIgnoreCase("service")) {
320 resource.getHomingSolution().setRehome(assignmentMap.get("isRehome").toBoolean())
321 VnfResource vnf = new VnfResource()
322 vnf.setVnfHostname(assignmentMap.get("vnfHostName"))
323 resource.getHomingSolution().setVnf(vnf)
324 resource.getHomingSolution().setServiceInstanceId(solution.getJSONArray("identifiers")[0].toString())
327 utils.log("DEBUG", "ProcessHomingSolution Exception: no matching serviceResourceIds returned in " +
328 "homing solution", isDebugEnabled)
329 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - " +
330 "Occurred in Homing ProcessHomingSolution: no matching serviceResourceIds returned")
335 if (JsonUtils.jsonElementExist(response, "solutions.licenseSolutions")) {
336 String licenseSolutions = jsonUtil.getJsonValue(response, "solutions.licenseSolutions")
337 JSONArray licenseArr = new JSONArray(licenseSolutions)
338 for (int l = 0; l < licenseArr.length(); l++) {
339 JSONObject license = licenseArr.getJSONObject(l)
340 String jsonServiceResourceId = license.getString("serviceResourceId")
341 for (Resource resource : resourceList) {
342 String serviceResourceId = resource.getResourceId()
343 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
344 String jsonEntitlementPoolList = jsonUtil.getJsonValue(license.toString(), "entitlementPoolUUID")
345 List<String> entitlementPoolList = jsonUtil.StringArrayToList(execution, jsonEntitlementPoolList)
346 resource.getHomingSolution().getLicense().setEntitlementPoolList(entitlementPoolList)
348 String jsonLicenseKeyGroupList = jsonUtil.getJsonValue(license.toString(), "licenseKeyGroupUUID")
349 List<String> licenseKeyGroupList = jsonUtil.StringArrayToList(execution, jsonLicenseKeyGroupList)
350 resource.getHomingSolution().getLicense().setLicenseKeyGroupList(licenseKeyGroupList)
356 execution.setVariable("serviceDecomposition", decomposition)
357 execution.setVariable("homingSolution", placements) //TODO - can be removed as output variable
359 utils.log("DEBUG", "*** Completed Homing Process Homing Solution ***", isDebugEnabled)
360 } catch (BpmnError b) {
361 utils.log("DEBUG", "ProcessHomingSolution Error: " + b, isDebugEnabled)
363 } catch (Exception e) {
364 utils.log("DEBUG", "ProcessHomingSolution Exception: " + e, isDebugEnabled)
366 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occurred in Homing ProcessHomingSolution")
371 * This method logs the start of DHVCreateService
372 * to make debugging easier.
376 public String logStart(DelegateExecution execution) {
377 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
378 String requestId = execution.getVariable("testReqId")
379 if (isBlank(requestId)) {
380 requestId = execution.getVariable("msoRequestId")
382 execution.setVariable("DHVCS_requestId", requestId)
383 utils.log("DEBUG", "***** STARTED Homing Subflow for request: " + requestId + " *****", "true")
384 utils.log("DEBUG", "****** Homing Subflow Global Debug Enabled: " + isDebugEnabled + " *****", "true")
385 utils.logAudit("***** STARTED Homing Subflow for request: " + requestId + " *****")
389 * Auto-generated method stub
391 public void preProcessRequest(DelegateExecution execution) {}
392 // Not Implemented Method
395 * Constructs a workflow message callback URL for the specified message type and correlator.
396 * This type of callback URL is used when a workflow wants an MSO adapter (like the SDNC
397 * adapter) to call it back. In other words, this is for callbacks internal to the MSO
398 * complex. Use <code>createWorkflowMessageAdapterCallbackURL</code> if the callback
399 * will come from outside the MSO complex.
400 * @param endpoint endpoint address to contruct URL from
401 * @param messageType the message type (e.g. SDNCAResponse or VNFAResponse)
402 * @param correlator the correlator value (e.g. a request ID)
404 public String createHomingCallbackURL(String endpoint, String messageType, String correlator) {
406 if (endpoint == null || endpoint.isEmpty()) {
407 ExceptionUtil exceptionUtil = new ExceptionUtil()
408 exceptionUtil.buildAndThrowWorkflowException(execution, 2000,
409 'mso:workflow:message:endpoint was not passed in')
412 utils.log("DEBUG", "passed in endpoint: " + endpoint + " *****", "true")
414 while (endpoint.endsWith('/')) {
415 endpoint = endpoint.substring(0, endpoint.length() - 1)
417 utils.log("DEBUG", "processed endpoint: " + endpoint + " *****", "true")
420 '/' + UriUtils.encodePathSegment(messageType, 'UTF-8') +
421 '/' + UriUtils.encodePathSegment(correlator, 'UTF-8')
422 } catch (Exception ex) {
423 utils.log("DEBUG", "createCallbackURL Exception: " + ex + " *****", "true")