2 * ============LICENSE_START=======================================================
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
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=========================================================
21 package org.onap.so.bpmn.infrastructure.scripts
23 import groovy.json.JsonException
24 import org.camunda.bpm.engine.delegate.BpmnError
25 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.onap.aai.domain.yang.GenericVnf
27 import org.onap.aai.domain.yang.VfModule
28 import org.onap.aai.domain.yang.VolumeGroup
29 import org.onap.so.bpmn.common.scripts.ExceptionUtil
30 import org.onap.so.bpmn.common.scripts.MsoUtils
31 import org.onap.so.bpmn.common.scripts.VfModuleBase
32 import org.onap.so.bpmn.common.scripts.VidUtils
33 import org.onap.so.bpmn.core.UrnPropertiesReader
34 import org.onap.so.bpmn.core.WorkflowException
35 import org.onap.so.client.aai.AAIObjectType
36 import org.onap.so.client.aai.entities.AAIResultWrapper
37 import org.onap.so.client.aai.entities.Relationships
38 import org.onap.so.client.aai.entities.uri.AAIResourceUri
39 import org.onap.so.client.aai.entities.uri.AAIUriFactory
40 import org.onap.so.constants.Defaults
41 import org.onap.so.logger.MessageEnum
42 import org.onap.so.logger.MsoLogger
43 import static org.apache.cxf.common.util.CollectionUtils.isEmpty
45 import groovy.json.JsonSlurper
47 import javax.ws.rs.core.UriBuilder
49 class UpdateVfModuleVolumeInfraV1 extends VfModuleBase {
50 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateVfModuleVolumeInfraV1.class)
51 private ExceptionUtil exceptionUtil = new ExceptionUtil()
54 * Initialize the flow's variables.
56 * @param execution The flow's execution instance.
58 private void initProcessVariables(DelegateExecution execution) {
59 execution.setVariable('prefix', 'UPDVfModVol_')
60 execution.setVariable('UPDVfModVol_Request', null)
61 execution.setVariable('UPDVfModVol_requestInfo', null)
62 execution.setVariable('UPDVfModVol_requestId', null)
63 execution.setVariable('UPDVfModVol_source', null)
64 execution.setVariable('UPDVfModVol_volumeInputs', null)
65 execution.setVariable('UPDVfModVol_volumeGroupId', null)
66 execution.setVariable('UPDVfModVol_vnfType', null)
67 execution.setVariable('UPDVfModVol_serviceId', null)
68 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
69 execution.setVariable('UPDVfModVol_tenantId', null)
70 execution.setVariable('UPDVfModVol_volumeParams', null)
71 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
72 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
73 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
77 * Perform initial processing, such as request validation, initialization of variables, etc.
80 public void preProcessRequest(DelegateExecution execution) {
81 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
82 preProcessRequest(execution, isDebugEnabled)
85 public void preProcessRequest(DelegateExecution execution, isDebugLogEnabled) {
87 initProcessVariables(execution)
88 String jsonRequest = validateRequest(execution)
93 def jsonSlurper = new JsonSlurper()
94 Map reqMap = jsonSlurper.parseText(jsonRequest)
96 def serviceInstanceId = execution.getVariable('serviceInstanceId')
97 def volumeGroupId = execution.getVariable('volumeGroupId')
98 //def vnfId = execution.getVariable('vnfId')
100 def vidUtils = new VidUtils(this)
101 request = vidUtils.createXmlVolumeRequest(reqMap, 'UPDATE_VF_MODULE_VOL', serviceInstanceId, volumeGroupId)
103 execution.setVariable('UPDVfModVol_Request', request)
104 execution.setVariable("UPDVfModVol_isVidRequest", true)
106 //need to get persona-model-id aka model-invariantId to use later to validate vf-module relation in AAI
108 def modelInvariantId = reqMap.requestDetails.modelInfo.modelInvariantUuid ?: ''
109 execution.setVariable('UPDVfModVol_modelInvariantId', modelInvariantId)
111 msoLogger.debug("modelInvariantId from request: " + modelInvariantId)
112 msoLogger.debug("XML request:\n" + request)
114 catch (JsonException je) {
115 msoLogger.debug(" Request is in XML format.")
116 // assume request is in XML format - proceed as usual to process XML request
119 def requestId = execution.getVariable('mso-request-id')
121 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
122 execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
123 execution.setVariable('UPDVfModVol_requestId', requestId)
124 //execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
125 execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
127 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
128 execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
129 execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
130 execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
131 execution.setVariable('UPDVfModVol_vnfVersion', getRequiredNodeText(execution, volumeInputs, 'asdc-service-model-version'))
132 execution.setVariable('UPDVfModVol_serviceId', utils.getNodeText(volumeInputs, 'service-id'))
133 execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
134 execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
135 //execution.setVariable('UPDVfModVol_modelCustomizationId', getRequiredNodeText(execution, volumeInputs, 'model-customization-id'))
137 setBasicDBAuthHeader(execution, isDebugLogEnabled)
139 def volumeParams = utils.getNodeXml(request, 'volume-params')
140 execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
144 * Prepare and send the synchronous response.
146 * @param execution The flow's execution instance.
148 public void sendSynchResponse(DelegateExecution execution, isDebugLogEnabled) {
150 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
151 def requestId = execution.getVariable('UPDVfModVol_requestId')
152 def source = execution.getVariable('UPDVfModVol_source')
153 def progress = getNodeTextForce(requestInfo, 'progress')
154 if (progress.isEmpty()) {
157 def startTime = getNodeTextForce(requestInfo, 'start-time')
158 if (startTime.isEmpty()) {
159 startTime = System.currentTimeMillis()
161 def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
163 String xmlSyncResponse = """
164 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
166 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
167 <action>UPDATE_VF_MODULE_VOL</action>
168 <request-status>IN_PROGRESS</request-status>
169 <progress>${MsoUtils.xmlEscape(progress)}</progress>
170 <start-time>${MsoUtils.xmlEscape(startTime)}</start-time>
171 <source>${MsoUtils.xmlEscape(source)}</source>
177 def syncResponse = ''
178 def isVidRequest = execution.getVariable('UPDVfModVol_isVidRequest')
181 def volumeGroupId = execution.getVariable('volumeGroupId')
182 syncResponse = """{"requestReferences":{"instanceId":"${volumeGroupId}","requestId":"${
186 syncResponse = utils.formatXml(xmlSyncResponse)
189 msoLogger.debug('Sync response: ' + syncResponse)
190 execution.setVariable('UPDVfModVol_syncResponseSent', true)
191 sendWorkflowResponse(execution, 200, syncResponse)
195 * Prepare a Request for querying AAI for Volume Group information using the
196 * Volume Group Id and Aic Cloud Region.
197 * @param execution The flow's execution instance.
199 public void queryAAIForVolumeGroup(DelegateExecution execution, isDebugLogEnabled) {
201 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
202 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
205 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), aicCloudRegion, volumeGroupId)
206 AAIResultWrapper wrapper = getAAIClient().get(uri)
207 Optional<VolumeGroup> volumeGroup = wrapper.asBean(VolumeGroup.class)
208 if (volumeGroup.isPresent()) {
209 execution.setVariable('UPDVfModVol_aaiVolumeGroupResponse', volumeGroup.get())
210 Optional<Relationships> relationships = wrapper.getRelationships()
211 if (relationships.isPresent()) {
212 List<AAIResourceUri> tenantURIList = relationships.get().getRelatedAAIUris(AAIObjectType.TENANT)
213 if (!isEmpty(tenantURIList)) {
214 String volumeGroupTenantId = tenantURIList.get(0).getURIKeys().get("tenant-id")
215 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
216 msoLogger.debug("Received Tenant Id " + volumeGroupTenantId + " from AAI for Volume Group with Volume Group Id " + volumeGroupId + ", AIC Cloud Region " + aicCloudRegion)
218 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id " + volumeGroupId
219 + ", AIC Cloud Region " + aicCloudRegion)
221 execution.setVariable('UPDVfModVol_relatedVfModuleLink', relationships.get().getRelatedLinks(AAIObjectType.VF_MODULE).get(0))
224 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id " + volumeGroupId
225 + ", AIC Cloud Region " + aicCloudRegion)
228 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group " + volumeGroupId + " not found at AAI")
230 }catch(BpmnError bpmnError){
233 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occured During queryAAIForGenericVnf"+e.getMessage())
238 * Query AAI service instance
240 * @param isDebugEnabled
242 public void queryAAIForGenericVnf(DelegateExecution execution, isDebugEnabled) {
244 def vnfId = execution.getVariable('vnfId')
246 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
248 Optional<GenericVnf> genericVnf = getAAIClient().get(GenericVnf.class, uri)
249 if (genericVnf.isPresent()) {
250 execution.setVariable('UPDVfModVol_AAIQueryGenericVfnResponse', genericVnf.get())
252 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, 'Generic vnf ' + vnfId + ' was not found in AAI. Return code: 404.')
254 }catch(BpmnError bpmnError){
257 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occured During queryAAIForGenericVnf"+e.getMessage())
262 * Query AAI for VF Module using vf-module-id
264 * @param isDebugLogEnabled
266 public void queryAAIForVfModule(DelegateExecution execution, isDebugLogEnabled) {
268 String queryAAIVfModuleRequest = execution.getVariable('UPDVfModVol_relatedVfModuleLink')
269 execution.setVariable('UPDVfModVol_personaModelId', '')
270 AAIResourceUri uri = AAIUriFactory.createResourceFromExistingURI(AAIObjectType.VF_MODULE, UriBuilder.fromPath(queryAAIVfModuleRequest).build())
272 Optional<VfModule> vfModule = getAAIClient().get(VfModule.class,uri)
273 if(vfModule.isPresent()){
274 execution.setVariable('UPDVfModVol_personaModelId',vfModule.get().getModelInvariantId())
276 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "VF Module not found at AAI")
278 }catch(BpmnError bpmnError){
281 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Error in queryAAIForVfModule: "+e.getMessage())
286 * Prepare a Request for invoking the VnfAdapterRest subflow to do
287 * a Volume Group update.
289 * @param execution The flow's execution instance.
291 public void prepVnfAdapterRest(DelegateExecution execution, isDebugLogEnabled) {
293 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
294 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
295 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
297 VolumeGroup aaiVolumeGroupResponse = execution.getVariable('UPDVfModVol_aaiVolumeGroupResponse')
298 def volumeGroupHeatStackId = aaiVolumeGroupResponse.getHeatStackId()
299 def volumeGroupName = aaiVolumeGroupResponse.getVolumeGroupName()
300 def modelCustomizationId = aaiVolumeGroupResponse.getModelCustomizationId()
302 def vnfType = execution.getVariable('UPDVfModVol_vnfType')
303 def vnfVersion = execution.getVariable('UPDVfModVol_vnfVersion')
305 GenericVnf aaiGenericVnfResponse = execution.getVariable('UPDVfModVol_AAIQueryGenericVfnResponse')
306 def vnfId = aaiGenericVnfResponse.getVnfId()
307 def vnfName = aaiGenericVnfResponse.getVnfName()
310 def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
311 def volumeGroupParams = transformVolumeParamsToEntries(volumeParamsXml)
313 def requestId = execution.getVariable('UPDVfModVol_requestId')
314 def serviceId = execution.getVariable('UPDVfModVol_serviceId')
316 def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
317 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
318 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host", execution)
319 if ('true'.equals(useQualifiedHostName)) {
320 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
323 String vnfAdapterRestRequest = """
324 <updateVolumeGroupRequest>
325 <cloudSiteId>${MsoUtils.xmlEscape(aicCloudRegion)}</cloudSiteId>
326 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
327 <vnfId>${MsoUtils.xmlEscape(vnfId)}</vnfId>
328 <vnfName>${MsoUtils.xmlEscape(vnfName)}</vnfName>
329 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
330 <volumeGroupName>${MsoUtils.xmlEscape(volumeGroupName)}</volumeGroupName>
331 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
332 <vnfType>${MsoUtils.xmlEscape(vnfType)}</vnfType>
333 <vnfVersion>${MsoUtils.xmlEscape(vnfVersion)}</vnfVersion>
334 <vfModuleType></vfModuleType>
335 <modelCustomizationUuid>${MsoUtils.xmlEscape(modelCustomizationId)}</modelCustomizationUuid>
339 <value>${MsoUtils.xmlEscape(vnfId)}</value>
343 <value>${MsoUtils.xmlEscape(vnfName)}</value>
346 <key>vf_module_id</key>
347 <value>${MsoUtils.xmlEscape(volumeGroupId)}</value>
350 <key>vf_module_name</key>
351 <value>${MsoUtils.xmlEscape(volumeGroupName)}</value>
355 <skipAAI>true</skipAAI>
357 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
358 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
360 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
361 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
362 </updateVolumeGroupRequest>
364 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
365 execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
366 msoLogger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
370 * Prepare a Request for updating the DB for this Infra request.
372 * @param execution The flow's execution instance.
374 public void prepDbInfraDbRequest(DelegateExecution execution, isDebugLogEnabled) {
376 def requestId = execution.getVariable('UPDVfModVol_requestId')
378 String updateInfraRequest = """
379 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
380 xmlns:req="http://org.onap.so/requestsdb">
383 <req:updateInfraRequest>
384 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
385 <lastModifiedBy>BPEL</lastModifiedBy>
386 <requestStatus>COMPLETE</requestStatus>
387 <progress>100</progress>
388 </req:updateInfraRequest>
393 updateInfraRequest = utils.formatXml(updateInfraRequest)
394 execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
395 msoLogger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
399 * Build a "CompletionHandler" request.
400 * @param execution The flow's execution instance.
402 public void prepCompletionHandlerRequest(DelegateExecution execution, requestId, action, source, isDebugLogEnabled) {
405 <aetgt:MsoCompletionRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
406 xmlns:ns="http://org.onap/so/request/types/v1">
407 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
408 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
409 <action>UPDATE</action>
410 <source>${MsoUtils.xmlEscape(source)}</source>
412 <aetgt:mso-bpel-name>BPMN VF Module Volume action: UPDATE</aetgt:mso-bpel-name>
413 </aetgt:MsoCompletionRequest>
416 content = utils.formatXml(content)
417 msoLogger.debug('Request for Completion Handler:\n' + content)
418 execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
422 * Build a "FalloutHandler" request.
423 * @param execution The flow's execution instance.
425 public void prepFalloutHandler(DelegateExecution execution, isDebugLogEnabled) {
426 def requestId = execution.getVariable('UPDVfModVol_requestId')
427 def source = execution.getVariable('UPDVfModVol_source')
429 String requestInfo = """
430 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
431 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
432 <action>UPDATE</action>
433 <source>${MsoUtils.xmlEscape(source)}</source>
436 WorkflowException workflowException = execution.getVariable("WorkflowException")
437 def errorResponseCode = workflowException.getErrorCode()
438 def errorResponseMsg = workflowException.getErrorMessage()
439 def encErrorResponseMsg = ""
440 if (errorResponseMsg != null) {
441 encErrorResponseMsg = errorResponseMsg
445 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
446 xmlns:reqtype="http://org.onap/so/request/types/v1"
447 xmlns:msoservtypes="http://org.onap/so/request/types/v1"
448 xmlns:structuredtypes="http://org.onap/so/structured/types/v1">
450 <sdncadapterworkflow:WorkflowException>
451 <sdncadapterworkflow:ErrorMessage>${MsoUtils.xmlEscape(encErrorResponseMsg)}</sdncadapterworkflow:ErrorMessage>
452 <sdncadapterworkflow:ErrorCode>${MsoUtils.xmlEscape(errorResponseCode)}</sdncadapterworkflow:ErrorCode>
453 </sdncadapterworkflow:WorkflowException>
454 </sdncadapterworkflow:FalloutHandlerRequest>
456 content = utils.formatXml(content)
457 msoLogger.debug('Request for Fallout Handler:\n' + content)
458 execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
462 * Create a WorkflowException for the error case where the Tenant Id from
463 * AAI did not match the Tenant Id in the incoming request.
464 * @param execution The flow's execution instance.
466 public void handleTenantIdMismatch(DelegateExecution execution, isDebugLogEnabled) {
468 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
469 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
470 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
471 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
473 String errorMessage = "TenantId " + tenantId + " in incoming request does not match Tenant Id " + volumeGroupTenantId +
474 " retrieved from AAI for Volume Group Id " + volumeGroupId + ", AIC Cloud Region " + aicCloudRegion
476 ExceptionUtil exceptionUtil = new ExceptionUtil()
477 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Error in UpdateVfModuleVol: ' + errorMessage, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception")
478 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, errorMessage)
482 * Create a WorkflowException for the error case where the Personal Model Id from
483 * AAI did not match the model invariant ID in the incoming request.
484 * @param execution The flow's execution instance.
486 public void handlePersonaModelIdMismatch(DelegateExecution execution, isDebugLogEnabled) {
488 def modelInvariantId = execution.getVariable('UPDVfModVol_modelInvariantId')
489 def personaModelId = execution.getVariable('UPDVfModVol_personaModelId')
491 String errorMessage = "Model Invariant ID " + modelInvariantId + " in incoming request does not match persona model ID " + personaModelId +
492 " retrieved from AAI for Volume Group Id "
494 ExceptionUtil exceptionUtil = new ExceptionUtil()
495 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Error in UpdateVfModuleVol: ' + errorMessage, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception")
496 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, errorMessage)