2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 Intel Corp. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
22 package org.onap.so.bpmn.common.scripts
24 import org.onap.so.bpmn.core.UrnPropertiesReader
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.delegate.DelegateExecution
28 import org.onap.so.bpmn.core.domain.InventoryType
29 import org.onap.so.bpmn.core.domain.Resource
30 import org.onap.so.bpmn.core.domain.ResourceType
31 import org.onap.so.bpmn.core.domain.ServiceDecomposition
32 import org.onap.so.bpmn.core.domain.Subscriber
33 import org.onap.so.bpmn.core.domain.VnfResource
34 import org.onap.so.bpmn.core.json.JsonUtils
35 import org.onap.so.client.HttpClient
36 import org.onap.so.client.HttpClientFactory
37 import org.slf4j.Logger
38 import org.slf4j.LoggerFactory
39 import org.onap.so.db.catalog.beans.CloudIdentity
40 import org.onap.so.db.catalog.beans.CloudSite
41 import org.onap.so.db.catalog.beans.HomingInstance
42 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
43 import org.onap.so.utils.TargetEntity
45 import org.json.JSONArray
46 import org.json.JSONObject
47 import org.springframework.web.util.UriUtils
49 import static org.onap.so.bpmn.common.scripts.GenericUtils.*
51 import javax.ws.rs.core.Response
54 * This class contains the scripts used
55 * by the OOF Homing Subflow building block. The
56 * subflow attempts to home the provided
57 * resources by calling OOF.
59 class OofHoming extends AbstractServiceTaskProcessor {
60 private static final Logger logger = LoggerFactory.getLogger( OofHoming.class);
62 ExceptionUtil exceptionUtil = new ExceptionUtil()
63 JsonUtils jsonUtil = new JsonUtils()
64 OofUtils oofUtils = new OofUtils(this)
67 * This method validates the incoming variables.
68 * The method then prepares the OOF request
69 * and posts it to OOF's rest api.
73 public void callOof(DelegateExecution execution) {
74 execution.setVariable("prefix", "HOME_")
75 logger.debug( "*** Started Homing Call OOF ***")
77 execution.setVariable("rollbackData", null)
78 execution.setVariable("rolledBack", false)
80 String requestId = execution.getVariable("msoRequestId")
81 logger.debug( "Incoming Request Id is: " + requestId)
82 String serviceInstanceId = execution.getVariable("serviceInstanceId")
83 logger.debug( "Incoming Service Instance Id is: " + serviceInstanceId)
84 String serviceInstanceName = execution.getVariable("serviceInstanceName")
85 logger.debug( "Incoming Service Instance Name is: " + serviceInstanceName)
86 ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
87 logger.debug( "Incoming Service Decomposition is: " + serviceDecomposition)
88 String subscriberInfo = execution.getVariable("subscriberInfo")
89 logger.debug( "Incoming Subscriber Information is: " + subscriberInfo)
90 Map customerLocation = execution.getVariable("customerLocation")
91 logger.debug( "Incoming Customer Location is: " + customerLocation.toString())
92 String cloudOwner = execution.getVariable("cloudOwner")
93 logger.debug( "Incoming cloudOwner is: " + cloudOwner)
94 String cloudRegionId = execution.getVariable("cloudRegionId")
95 logger.debug( "Incoming cloudRegionId is: " + cloudRegionId)
97 if (isBlank(requestId) ||
98 isBlank(serviceInstanceId) ||
99 isBlank(serviceInstanceName) ||
100 isBlank(serviceDecomposition.toString()) ||
101 isBlank(customerLocation.toString())) {
102 exceptionUtil.buildAndThrowWorkflowException(execution, 4000,
103 "A required input variable is missing or null")
105 Subscriber subscriber = null
106 if (isBlank(subscriberInfo)) {
107 subscriber = new Subscriber("", "", "")
109 String subId = jsonUtil.getJsonValue(subscriberInfo, "globalSubscriberId")
110 String subName = jsonUtil.getJsonValue(subscriberInfo, "subscriberName")
111 String subCommonSiteId = ""
112 if (jsonUtil.jsonElementExist(subscriberInfo, "subscriberCommonSiteId")) {
113 subCommonSiteId = jsonUtil.getJsonValue(subscriberInfo, "subscriberCommonSiteId")
115 subscriber = new Subscriber(subId, subName, subCommonSiteId)
120 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
121 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
123 String basicAuthValue = utils.encrypt(basicAuth, msokey)
124 if (basicAuthValue != null) {
125 logger.debug( "Obtained BasicAuth username and password for OOF Adapter: " + basicAuthValue)
127 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
128 execution.setVariable("BasicAuthHeaderValue", authHeader)
129 } catch (Exception ex) {
130 logger.debug( "Unable to encode username and password string: " + ex)
131 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
132 "encode username and password string")
135 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
136 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
141 String timeout = execution.getVariable("timeout")
142 if (isBlank(timeout)) {
143 timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
144 if (isBlank(timeout)) {
148 logger.debug( "Async Callback Timeout will be: " + timeout)
150 execution.setVariable("timeout", timeout)
151 execution.setVariable("correlator", requestId)
152 execution.setVariable("messageType", "oofResponse")
154 //Build Request & Call OOF
155 String oofRequest = oofUtils.buildRequest(execution, requestId, serviceDecomposition,
156 subscriber, customerLocation)
157 execution.setVariable("oofRequest", oofRequest)
158 logger.debug( "OOF Request is: " + oofRequest)
160 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
161 logger.debug( "Posting to OOF Url: " + urlString)
164 URL url = new URL(urlString);
165 HttpClient httpClient = new HttpClientFactory().newJsonClient(url, TargetEntity.SNIRO)
166 httpClient.addAdditionalHeader("Authorization", authHeader)
167 Response httpResponse = httpClient.post(oofRequest)
169 int responseCode = httpResponse.getStatus()
170 logger.debug("OOF sync response code is: " + responseCode)
173 logger.debug( "*** Completed Homing Call OOF ***")
175 } catch (BpmnError b) {
177 } catch (Exception e) {
179 exceptionUtil.buildAndThrowWorkflowException(execution, 2500,
180 "Internal Error - Occured in Homing callOof: " + e.getMessage())
185 * This method processes the callback response
186 * and the contained homing solution. It sets
187 * homing solution assignment and license
188 * information to the corresponding resources
192 public void processHomingSolution(DelegateExecution execution) {
194 logger.debug( "*** Started Homing Process Homing Solution ***")
196 String response = execution.getVariable("asyncCallbackResponse")
197 logger.debug( "OOF Async Callback Response is: " + response)
199 oofUtils.validateCallbackResponse(execution, response)
200 String placements = jsonUtil.getJsonValue(response, "solutions.placementSolutions")
201 logger.debug( "****** Solution Placements: " + placements + " *****")
203 ServiceDecomposition decomposition = execution.getVariable("serviceDecomposition")
204 logger.debug( "Service Decomposition: " + decomposition)
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 logger.debug( "****** Placement Solution is: " + placement + " *****")
213 String jsonServiceResourceId = jsonUtil.getJsonValue( placement.toString(), "serviceResourceId")
214 logger.debug( "****** homing serviceResourceId is: " + jsonServiceResourceId + " *****")
215 for (Resource resource : resourceList) {
216 String serviceResourceId = resource.getResourceId()
217 logger.debug( "****** decomp serviceResourceId is: " + serviceResourceId + " *****")
218 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
219 JSONObject solution = placement.getJSONObject("solution")
220 String solutionType = solution.getString("identifierType")
221 String inventoryType = ""
222 if (solutionType.equalsIgnoreCase("serviceInstanceId")) {
223 inventoryType = "service"
225 inventoryType = "cloud"
227 logger.debug( "****** homing inventoryType is: " + inventoryType + " *****")
228 resource.getHomingSolution().setInventoryType(InventoryType.valueOf(inventoryType))
230 JSONArray assignmentArr = placement.getJSONArray("assignmentInfo")
231 logger.debug( "****** assignmentInfo is: " + assignmentArr.toString() + " *****")
233 Map<String, String> assignmentMap = jsonUtil.entryArrayToMap(execution,
234 assignmentArr.toString(), "key", "value")
235 String oofDirectives = null
236 assignmentMap.each { key, value ->
237 logger.debug( "****** element: " + key + " *****")
238 if (key == "oof_directives") {
239 oofDirectives = value
240 logger.debug( "****** homing oofDirectives: " + oofDirectives + " *****")
243 String cloudOwner = assignmentMap.get("cloudOwner")
244 logger.debug( "****** homing cloudOwner: " + cloudOwner + " *****")
245 String cloudRegionId = assignmentMap.get("locationId")
246 logger.debug( "****** homing cloudRegionId: " + cloudRegionId + " *****")
247 resource.getHomingSolution().setCloudOwner(cloudOwner)
248 resource.getHomingSolution().setCloudRegionId(cloudRegionId)
250 CloudSite cloudSite = new CloudSite()
251 cloudSite.setId(cloudRegionId)
252 cloudSite.setRegionId(cloudRegionId)
253 String orchestrator = execution.getVariable("orchestrator")
254 if ((orchestrator != null) && (orchestrator != "")) {
255 cloudSite.setOrchestrator(orchestrator)
256 logger.debug( "****** orchestrator: " + orchestrator + " *****")
258 cloudSite.setOrchestrator("multicloud")
261 CloudIdentity cloudIdentity = new CloudIdentity()
262 cloudIdentity.setId(cloudRegionId)
263 cloudIdentity.setIdentityServerType(ServerType."KEYSTONE")
264 cloudIdentity.setAdminTenant("service")
265 cloudIdentity.setIdentityAuthenticationType(AuthenticationType.USERNAME_PASSWORD)
266 String msoMulticloudUserName = UrnPropertiesReader
267 .getVariable("mso.multicloud.api.username", execution,
269 String msoMulticloudPassword = UrnPropertiesReader
270 .getVariable("mso.multicloud.api.password", execution,
272 cloudIdentity.setMsoId(msoMulticloudUserName)
273 cloudIdentity.setMsoPass(msoMulticloudPassword)
275 String msbHost = oofUtils.getMsbHost(execution)
276 String multicloudApiEndpoint = UrnPropertiesReader
277 .getVariable("mso.multicloud.api.endpoint", execution,
278 "/api/multicloud-titaniumcloud/v1")
279 cloudIdentity.setIdentityUrl(msbHost + multicloudApiEndpoint
280 + "/" + cloudOwner + "/" +
281 cloudRegionId + "/infra_workload")
282 logger.debug( "****** Cloud IdentityUrl: " + msbHost + multicloudApiEndpoint
283 + "/" + cloudOwner + "/" +
284 cloudRegionId + "/infra_workload"
286 logger.debug( "****** CloudIdentity: " + cloudIdentity.toString()
288 cloudSite.setIdentityService(cloudIdentity)
289 logger.debug( "****** CloudSite: " + cloudSite.toString()
292 // Set cloudsite in catalog DB here
293 oofUtils.createCloudSite(cloudSite, execution)
295 if (oofDirectives != null && oofDirectives != "") {
296 resource.getHomingSolution().setOofDirectives(oofDirectives)
297 execution.setVariable("oofDirectives", oofDirectives)
298 logger.debug( "***** OofDirectives set to: " + oofDirectives +
302 // Set Homing Instance
303 String serviceInstanceId = decomposition.getServiceInstance().getInstanceId()
304 HomingInstance homingInstance = new HomingInstance()
305 homingInstance.setServiceInstanceId(serviceInstanceId)
306 homingInstance.setCloudOwner(cloudOwner)
307 homingInstance.setCloudRegionId(cloudRegionId)
308 if (oofDirectives != null && oofDirectives != "") {
309 homingInstance.setOofDirectives(oofDirectives)}
311 homingInstance.setOofDirectives("{}")
313 oofUtils.createHomingInstance(homingInstance, execution)
315 if (inventoryType.equalsIgnoreCase("service")) {
316 resource.getHomingSolution().setRehome(assignmentMap.get("isRehome").toBoolean())
317 VnfResource vnf = new VnfResource()
318 vnf.setVnfHostname(assignmentMap.get("vnfHostName"))
319 resource.getHomingSolution().setVnf(vnf)
320 resource.getHomingSolution().setServiceInstanceId(solution.getJSONArray("identifiers")[0].toString())
323 logger.debug( "ProcessHomingSolution Exception: no matching serviceResourceIds returned in " +
325 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - " +
326 "Occurred in Homing ProcessHomingSolution: no matching serviceResourceIds returned")
331 if (JsonUtils.jsonElementExist(response, "solutions.licenseSolutions")) {
332 String licenseSolutions = jsonUtil.getJsonValue(response, "solutions.licenseSolutions")
333 JSONArray licenseArr = new JSONArray(licenseSolutions)
334 for (int l = 0; l < licenseArr.length(); l++) {
335 JSONObject license = licenseArr.getJSONObject(l)
336 String jsonServiceResourceId = license.getString("serviceResourceId")
337 for (Resource resource : resourceList) {
338 String serviceResourceId = resource.getResourceId()
339 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
340 String jsonEntitlementPoolList = jsonUtil.getJsonValue(license.toString(), "entitlementPoolUUID")
341 List<String> entitlementPoolList = jsonUtil.StringArrayToList(execution, jsonEntitlementPoolList)
342 resource.getHomingSolution().getLicense().setEntitlementPoolList(entitlementPoolList)
344 String jsonLicenseKeyGroupList = jsonUtil.getJsonValue(license.toString(), "licenseKeyGroupUUID")
345 List<String> licenseKeyGroupList = jsonUtil.StringArrayToList(execution, jsonLicenseKeyGroupList)
346 resource.getHomingSolution().getLicense().setLicenseKeyGroupList(licenseKeyGroupList)
352 execution.setVariable("serviceDecomposition", decomposition)
353 execution.setVariable("homingSolution", placements) //TODO - can be removed as output variable
355 logger.debug( "*** Completed Homing Process Homing Solution ***")
356 } catch (BpmnError b) {
357 logger.debug( "ProcessHomingSolution Error: " + b)
359 } catch (Exception e) {
360 logger.debug( "ProcessHomingSolution Exception: " + e)
362 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occurred in Homing ProcessHomingSolution")
367 * This method logs the start of DHVCreateService
368 * to make debugging easier.
372 public String logStart(DelegateExecution execution) {
374 String requestId = execution.getVariable("testReqId")
375 if (isBlank(requestId)) {
376 requestId = execution.getVariable("msoRequestId")
378 execution.setVariable("DHVCS_requestId", requestId)
379 logger.debug( "***** STARTED Homing Subflow for request: " + requestId + " *****")
383 * Auto-generated method stub
385 public void preProcessRequest(DelegateExecution execution) {}
386 // Not Implemented Method
389 * Constructs a workflow message callback URL for the specified message type and correlator.
390 * This type of callback URL is used when a workflow wants an MSO adapter (like the SDNC
391 * adapter) to call it back. In other words, this is for callbacks internal to the MSO
392 * complex. Use <code>createWorkflowMessageAdapterCallbackURL</code> if the callback
393 * will come from outside the MSO complex.
394 * @param endpoint endpoint address to contruct URL from
395 * @param messageType the message type (e.g. SDNCAResponse or VNFAResponse)
396 * @param correlator the correlator value (e.g. a request ID)
398 public String createHomingCallbackURL(String endpoint, String messageType, String correlator) {
400 if (endpoint == null || endpoint.isEmpty()) {
401 ExceptionUtil exceptionUtil = new ExceptionUtil()
402 exceptionUtil.buildAndThrowWorkflowException(execution, 2000,
403 'mso:workflow:message:endpoint was not passed in')
406 logger.debug( "passed in endpoint: " + endpoint + " *****")
408 while (endpoint.endsWith('/')) {
409 endpoint = endpoint.substring(0, endpoint.length() - 1)
411 logger.debug( "processed endpoint: " + endpoint + " *****")
414 '/' + UriUtils.encodePathSegment(messageType, 'UTF-8') +
415 '/' + UriUtils.encodePathSegment(correlator, 'UTF-8')
416 } catch (Exception ex) {
417 logger.debug( "createCallbackURL Exception: " + ex + " *****")