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.AuthenticationType
40 import org.onap.so.db.catalog.beans.CloudIdentity
41 import org.onap.so.db.catalog.beans.CloudSite
42 import org.onap.so.db.catalog.beans.HomingInstance
43 import org.onap.so.db.catalog.beans.ServerType
44 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
45 import org.onap.so.utils.TargetEntity
47 import org.json.JSONArray
48 import org.json.JSONObject
49 import org.springframework.web.util.UriUtils
51 import static org.onap.so.bpmn.common.scripts.GenericUtils.*
53 import javax.ws.rs.core.Response
56 * This class contains the scripts used
57 * by the OOF Homing Subflow building block. The
58 * subflow attempts to home the provided
59 * resources by calling OOF.
61 class OofHoming extends AbstractServiceTaskProcessor {
62 private static final Logger logger = LoggerFactory.getLogger( OofHoming.class);
64 ExceptionUtil exceptionUtil = new ExceptionUtil()
65 JsonUtils jsonUtil = new JsonUtils()
66 OofUtils oofUtils = new OofUtils(this)
69 * This method validates the incoming variables.
70 * The method then prepares the OOF request
71 * and posts it to OOF's rest api.
75 public void callOof(DelegateExecution execution) {
76 execution.setVariable("prefix", "HOME_")
77 logger.debug( "*** Started Homing Call OOF ***")
79 execution.setVariable("rollbackData", null)
80 execution.setVariable("rolledBack", false)
82 String requestId = execution.getVariable("msoRequestId")
83 logger.debug( "Incoming Request Id is: " + requestId)
84 String serviceInstanceId = execution.getVariable("serviceInstanceId")
85 logger.debug( "Incoming Service Instance Id is: " + serviceInstanceId)
86 String serviceInstanceName = execution.getVariable("serviceInstanceName")
87 logger.debug( "Incoming Service Instance Name is: " + serviceInstanceName)
88 ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
89 logger.debug( "Incoming Service Decomposition is: " + serviceDecomposition)
90 String subscriberInfo = execution.getVariable("subscriberInfo")
91 logger.debug( "Incoming Subscriber Information is: " + subscriberInfo)
92 Map customerLocation = execution.getVariable("customerLocation")
93 logger.debug( "Incoming Customer Location is: " + customerLocation.toString())
94 String cloudOwner = execution.getVariable("cloudOwner")
95 logger.debug( "Incoming cloudOwner is: " + cloudOwner)
96 String cloudRegionId = execution.getVariable("cloudRegionId")
97 logger.debug( "Incoming cloudRegionId is: " + cloudRegionId)
99 if (isBlank(requestId) ||
100 isBlank(serviceInstanceId) ||
101 isBlank(serviceInstanceName) ||
102 isBlank(serviceDecomposition.toString()) ||
103 isBlank(customerLocation.toString())) {
104 exceptionUtil.buildAndThrowWorkflowException(execution, 4000,
105 "A required input variable is missing or null")
107 Subscriber subscriber = null
108 if (isBlank(subscriberInfo)) {
109 subscriber = new Subscriber("", "", "")
111 String subId = jsonUtil.getJsonValue(subscriberInfo, "globalSubscriberId")
112 String subName = jsonUtil.getJsonValue(subscriberInfo, "subscriberName")
113 String subCommonSiteId = ""
114 if (jsonUtil.jsonElementExist(subscriberInfo, "subscriberCommonSiteId")) {
115 subCommonSiteId = jsonUtil.getJsonValue(subscriberInfo, "subscriberCommonSiteId")
117 subscriber = new Subscriber(subId, subName, subCommonSiteId)
122 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
123 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
125 String basicAuthValue = utils.encrypt(basicAuth, msokey)
126 if (basicAuthValue != null) {
127 logger.debug( "Obtained BasicAuth username and password for OOF Adapter: " + basicAuthValue)
129 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
130 execution.setVariable("BasicAuthHeaderValue", authHeader)
131 } catch (Exception ex) {
132 logger.debug( "Unable to encode username and password string: " + ex)
133 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
134 "encode username and password string")
137 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
138 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
143 String timeout = execution.getVariable("timeout")
144 if (isBlank(timeout)) {
145 timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
146 if (isBlank(timeout)) {
150 logger.debug( "Async Callback Timeout will be: " + timeout)
152 execution.setVariable("timeout", timeout)
153 execution.setVariable("correlator", requestId)
154 execution.setVariable("messageType", "oofResponse")
156 //Build Request & Call OOF
157 String oofRequest = oofUtils.buildRequest(execution, requestId, serviceDecomposition,
158 subscriber, customerLocation)
159 execution.setVariable("oofRequest", oofRequest)
160 logger.debug( "OOF Request is: " + oofRequest)
162 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
163 logger.debug( "Posting to OOF Url: " + urlString)
166 URL url = new URL(urlString);
167 HttpClient httpClient = new HttpClientFactory().newJsonClient(url, TargetEntity.SNIRO)
168 httpClient.addAdditionalHeader("Authorization", authHeader)
169 Response httpResponse = httpClient.post(oofRequest)
171 int responseCode = httpResponse.getStatus()
172 logger.debug("OOF sync response code is: " + responseCode)
175 logger.debug( "*** Completed Homing Call OOF ***")
177 } catch (BpmnError b) {
179 } catch (Exception e) {
181 exceptionUtil.buildAndThrowWorkflowException(execution, 2500,
182 "Internal Error - Occured in Homing callOof: " + e.getMessage())
187 * This method processes the callback response
188 * and the contained homing solution. It sets
189 * homing solution assignment and license
190 * information to the corresponding resources
194 public void processHomingSolution(DelegateExecution execution) {
196 logger.debug( "*** Started Homing Process Homing Solution ***")
198 String response = execution.getVariable("asyncCallbackResponse")
199 logger.debug( "OOF Async Callback Response is: " + response)
201 oofUtils.validateCallbackResponse(execution, response)
202 String placements = jsonUtil.getJsonValue(response, "solutions.placementSolutions")
203 logger.debug( "****** Solution Placements: " + placements + " *****")
205 ServiceDecomposition decomposition = execution.getVariable("serviceDecomposition")
206 logger.debug( "Service Decomposition: " + decomposition)
208 List<Resource> resourceList = decomposition.getServiceResources()
209 JSONArray arr = new JSONArray(placements)
210 for (int i = 0; i < arr.length(); i++) {
211 JSONArray arrSol = arr.getJSONArray(i)
212 for (int j = 0; j < arrSol.length(); j++) {
213 JSONObject placement = arrSol.getJSONObject(j)
214 logger.debug( "****** Placement Solution is: " + placement + " *****")
215 String jsonServiceResourceId = jsonUtil.getJsonValue( placement.toString(), "serviceResourceId")
216 logger.debug( "****** homing serviceResourceId is: " + jsonServiceResourceId + " *****")
217 for (Resource resource : resourceList) {
218 String serviceResourceId = resource.getResourceId()
219 logger.debug( "****** decomp serviceResourceId is: " + serviceResourceId + " *****")
220 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
221 JSONObject solution = placement.getJSONObject("solution")
222 String solutionType = solution.getString("identifierType")
223 String inventoryType = ""
224 if (solutionType.equalsIgnoreCase("serviceInstanceId")) {
225 inventoryType = "service"
227 inventoryType = "cloud"
229 logger.debug( "****** homing inventoryType is: " + inventoryType + " *****")
230 resource.getHomingSolution().setInventoryType(InventoryType.valueOf(inventoryType))
232 JSONArray assignmentArr = placement.getJSONArray("assignmentInfo")
233 logger.debug( "****** assignmentInfo is: " + assignmentArr.toString() + " *****")
235 Map<String, String> assignmentMap = jsonUtil.entryArrayToMap(execution,
236 assignmentArr.toString(), "key", "value")
237 String oofDirectives = null
238 assignmentMap.each { key, value ->
239 logger.debug( "****** element: " + key + " *****")
240 if (key == "oof_directives") {
241 oofDirectives = value
242 logger.debug( "****** homing oofDirectives: " + oofDirectives + " *****")
245 String cloudOwner = assignmentMap.get("cloudOwner")
246 logger.debug( "****** homing cloudOwner: " + cloudOwner + " *****")
247 String cloudRegionId = assignmentMap.get("locationId")
248 logger.debug( "****** homing cloudRegionId: " + cloudRegionId + " *****")
249 resource.getHomingSolution().setCloudOwner(cloudOwner)
250 resource.getHomingSolution().setCloudRegionId(cloudRegionId)
252 CloudSite cloudSite = new CloudSite()
253 cloudSite.setId(cloudRegionId)
254 cloudSite.setRegionId(cloudRegionId)
255 String orchestrator = execution.getVariable("orchestrator")
256 if ((orchestrator != null) && (orchestrator != "")) {
257 cloudSite.setOrchestrator(orchestrator)
258 logger.debug( "****** orchestrator: " + orchestrator + " *****")
260 cloudSite.setOrchestrator("multicloud")
263 CloudIdentity cloudIdentity = new CloudIdentity()
264 cloudIdentity.setId(cloudRegionId)
265 cloudIdentity.setIdentityServerType(ServerType."KEYSTONE")
266 cloudIdentity.setAdminTenant("service")
267 cloudIdentity.setIdentityAuthenticationType(AuthenticationType.USERNAME_PASSWORD)
268 String msoMulticloudUserName = UrnPropertiesReader
269 .getVariable("mso.multicloud.api.username", execution,
271 String msoMulticloudPassword = UrnPropertiesReader
272 .getVariable("mso.multicloud.api.password", execution,
274 cloudIdentity.setMsoId(msoMulticloudUserName)
275 cloudIdentity.setMsoPass(msoMulticloudPassword)
277 String msbHost = oofUtils.getMsbHost(execution)
278 String multicloudApiEndpoint = UrnPropertiesReader
279 .getVariable("mso.multicloud.api.endpoint", execution,
280 "/api/multicloud-titaniumcloud/v1")
281 cloudIdentity.setIdentityUrl(msbHost + multicloudApiEndpoint
282 + "/" + cloudOwner + "/" +
283 cloudRegionId + "/infra_workload")
284 logger.debug( "****** Cloud IdentityUrl: " + msbHost + multicloudApiEndpoint
285 + "/" + cloudOwner + "/" +
286 cloudRegionId + "/infra_workload"
288 logger.debug( "****** CloudIdentity: " + cloudIdentity.toString()
290 cloudSite.setIdentityService(cloudIdentity)
291 logger.debug( "****** CloudSite: " + cloudSite.toString()
294 // Set cloudsite in catalog DB here
295 oofUtils.createCloudSite(cloudSite, execution)
297 if (oofDirectives != null && oofDirectives != "") {
298 resource.getHomingSolution().setOofDirectives(oofDirectives)
299 execution.setVariable("oofDirectives", oofDirectives)
300 logger.debug( "***** OofDirectives set to: " + oofDirectives +
304 // Set Homing Instance
305 String serviceInstanceId = decomposition.getServiceInstance().getInstanceId()
306 HomingInstance homingInstance = new HomingInstance()
307 homingInstance.setServiceInstanceId(serviceInstanceId)
308 homingInstance.setCloudOwner(cloudOwner)
309 homingInstance.setCloudRegionId(cloudRegionId)
310 if (oofDirectives != null && oofDirectives != "") {
311 homingInstance.setOofDirectives(oofDirectives)}
313 homingInstance.setOofDirectives("{}")
315 oofUtils.createHomingInstance(homingInstance, execution)
317 if (inventoryType.equalsIgnoreCase("service")) {
318 resource.getHomingSolution().setRehome(assignmentMap.get("isRehome").toBoolean())
319 VnfResource vnf = new VnfResource()
320 vnf.setVnfHostname(assignmentMap.get("vnfHostName"))
321 resource.getHomingSolution().setVnf(vnf)
322 resource.getHomingSolution().setServiceInstanceId(solution.getJSONArray("identifiers")[0].toString())
325 logger.debug( "ProcessHomingSolution Exception: no matching serviceResourceIds returned in " +
327 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - " +
328 "Occurred in Homing ProcessHomingSolution: no matching serviceResourceIds returned")
333 if (JsonUtils.jsonElementExist(response, "solutions.licenseSolutions")) {
334 String licenseSolutions = jsonUtil.getJsonValue(response, "solutions.licenseSolutions")
335 JSONArray licenseArr = new JSONArray(licenseSolutions)
336 for (int l = 0; l < licenseArr.length(); l++) {
337 JSONObject license = licenseArr.getJSONObject(l)
338 String jsonServiceResourceId = license.getString("serviceResourceId")
339 for (Resource resource : resourceList) {
340 String serviceResourceId = resource.getResourceId()
341 if (serviceResourceId.equalsIgnoreCase(jsonServiceResourceId)) {
342 String jsonEntitlementPoolList = jsonUtil.getJsonValue(license.toString(), "entitlementPoolUUID")
343 List<String> entitlementPoolList = jsonUtil.StringArrayToList(execution, jsonEntitlementPoolList)
344 resource.getHomingSolution().getLicense().setEntitlementPoolList(entitlementPoolList)
346 String jsonLicenseKeyGroupList = jsonUtil.getJsonValue(license.toString(), "licenseKeyGroupUUID")
347 List<String> licenseKeyGroupList = jsonUtil.StringArrayToList(execution, jsonLicenseKeyGroupList)
348 resource.getHomingSolution().getLicense().setLicenseKeyGroupList(licenseKeyGroupList)
354 execution.setVariable("serviceDecomposition", decomposition)
355 execution.setVariable("homingSolution", placements) //TODO - can be removed as output variable
357 logger.debug( "*** Completed Homing Process Homing Solution ***")
358 } catch (BpmnError b) {
359 logger.debug( "ProcessHomingSolution Error: " + b)
361 } catch (Exception e) {
362 logger.debug( "ProcessHomingSolution Exception: " + e)
364 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occurred in Homing ProcessHomingSolution")
369 * This method logs the start of DHVCreateService
370 * to make debugging easier.
374 public String logStart(DelegateExecution execution) {
376 String requestId = execution.getVariable("testReqId")
377 if (isBlank(requestId)) {
378 requestId = execution.getVariable("msoRequestId")
380 execution.setVariable("DHVCS_requestId", requestId)
381 logger.debug( "***** STARTED Homing Subflow for request: " + requestId + " *****")
385 * Auto-generated method stub
387 public void preProcessRequest(DelegateExecution execution) {}
388 // Not Implemented Method
391 * Constructs a workflow message callback URL for the specified message type and correlator.
392 * This type of callback URL is used when a workflow wants an MSO adapter (like the SDNC
393 * adapter) to call it back. In other words, this is for callbacks internal to the MSO
394 * complex. Use <code>createWorkflowMessageAdapterCallbackURL</code> if the callback
395 * will come from outside the MSO complex.
396 * @param endpoint endpoint address to contruct URL from
397 * @param messageType the message type (e.g. SDNCAResponse or VNFAResponse)
398 * @param correlator the correlator value (e.g. a request ID)
400 public String createHomingCallbackURL(String endpoint, String messageType, String correlator) {
402 if (endpoint == null || endpoint.isEmpty()) {
403 ExceptionUtil exceptionUtil = new ExceptionUtil()
404 exceptionUtil.buildAndThrowWorkflowException(execution, 2000,
405 'mso:workflow:message:endpoint was not passed in')
408 logger.debug( "passed in endpoint: " + endpoint + " *****")
410 while (endpoint.endsWith('/')) {
411 endpoint = endpoint.substring(0, endpoint.length() - 1)
413 logger.debug( "processed endpoint: " + endpoint + " *****")
416 '/' + UriUtils.encodePathSegment(messageType, 'UTF-8') +
417 '/' + UriUtils.encodePathSegment(correlator, 'UTF-8')
418 } catch (Exception ex) {
419 logger.debug( "createCallbackURL Exception: " + ex + " *****")