2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. 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=========================================================
23 package org.onap.so.bpmn.infrastructure.scripts
25 import groovy.json.JsonException
26 import groovy.json.JsonSlurper
27 import org.camunda.bpm.engine.delegate.BpmnError
28 import org.camunda.bpm.engine.delegate.DelegateExecution
29 import org.onap.aai.domain.yang.GenericVnf
30 import org.onap.aai.domain.yang.VfModule
31 import org.onap.aai.domain.yang.VolumeGroup
32 import org.onap.so.bpmn.common.scripts.ExceptionUtil
33 import org.onap.so.bpmn.common.scripts.MsoUtils
34 import org.onap.so.bpmn.common.scripts.VfModuleBase
35 import org.onap.so.bpmn.common.scripts.VidUtils
36 import org.onap.so.bpmn.core.UrnPropertiesReader
37 import org.onap.so.bpmn.core.WorkflowException
38 import org.onap.so.client.aai.AAIObjectType
39 import org.onap.so.client.aai.entities.AAIResultWrapper
40 import org.onap.so.client.aai.entities.Relationships
41 import org.onap.so.client.aai.entities.uri.AAIResourceUri
42 import org.onap.so.client.aai.entities.uri.AAIUriFactory
43 import org.onap.so.constants.Defaults
44 import org.onap.so.logger.ErrorCode
45 import org.onap.so.logger.MessageEnum
46 import org.slf4j.Logger
47 import org.slf4j.LoggerFactory
49 import javax.ws.rs.core.UriBuilder
51 import static org.apache.cxf.common.util.CollectionUtils.isEmpty
53 class UpdateVfModuleVolumeInfraV1 extends VfModuleBase {
54 private static final Logger logger = LoggerFactory.getLogger(UpdateVfModuleVolumeInfraV1.class)
55 private ExceptionUtil exceptionUtil = new ExceptionUtil()
58 * Initialize the flow's variables.
60 * @param execution The flow's execution instance.
62 private void initProcessVariables(DelegateExecution execution) {
63 execution.setVariable('prefix', 'UPDVfModVol_')
64 execution.setVariable('UPDVfModVol_Request', null)
65 execution.setVariable('UPDVfModVol_requestInfo', null)
66 execution.setVariable('UPDVfModVol_requestId', null)
67 execution.setVariable('UPDVfModVol_source', null)
68 execution.setVariable('UPDVfModVol_volumeInputs', null)
69 execution.setVariable('UPDVfModVol_volumeGroupId', null)
70 execution.setVariable('UPDVfModVol_vnfType', null)
71 execution.setVariable('UPDVfModVol_serviceId', null)
72 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
73 execution.setVariable('UPDVfModVol_tenantId', null)
74 execution.setVariable('UPDVfModVol_volumeParams', null)
75 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
76 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
77 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
81 * Perform initial processing, such as request validation, initialization of variables, etc.
84 public void preProcessRequest(DelegateExecution execution) {
85 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
86 preProcessRequest(execution, isDebugEnabled)
89 public void preProcessRequest(DelegateExecution execution, isDebugLogEnabled) {
91 initProcessVariables(execution)
92 String jsonRequest = validateRequest(execution)
97 def jsonSlurper = new JsonSlurper()
98 Map reqMap = jsonSlurper.parseText(jsonRequest)
100 def serviceInstanceId = execution.getVariable('serviceInstanceId')
101 def volumeGroupId = execution.getVariable('volumeGroupId')
102 //def vnfId = execution.getVariable('vnfId')
104 def vidUtils = new VidUtils(this)
105 request = vidUtils.createXmlVolumeRequest(reqMap, 'UPDATE_VF_MODULE_VOL', serviceInstanceId, volumeGroupId)
107 execution.setVariable('UPDVfModVol_Request', request)
108 execution.setVariable("UPDVfModVol_isVidRequest", true)
110 //need to get persona-model-id aka model-invariantId to use later to validate vf-module relation in AAI
112 def modelInvariantId = reqMap.requestDetails.modelInfo.modelInvariantUuid ?: ''
113 execution.setVariable('UPDVfModVol_modelInvariantId', modelInvariantId)
115 logger.debug("modelInvariantId from request: {}", modelInvariantId)
116 logger.debug("XML request:\n{}", request)
118 catch (JsonException je) {
119 logger.debug(" Request is in XML format.")
120 // assume request is in XML format - proceed as usual to process XML request
123 def requestId = execution.getVariable('mso-request-id')
125 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
126 execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
127 execution.setVariable('UPDVfModVol_requestId', requestId)
128 //execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
129 execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
131 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
132 execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
133 execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
134 execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
135 execution.setVariable('UPDVfModVol_vnfVersion', getRequiredNodeText(execution, volumeInputs, 'asdc-service-model-version'))
136 execution.setVariable('UPDVfModVol_serviceId', utils.getNodeText(volumeInputs, 'service-id'))
137 execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
138 execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
139 //execution.setVariable('UPDVfModVol_modelCustomizationId', getRequiredNodeText(execution, volumeInputs, 'model-customization-id'))
141 setBasicDBAuthHeader(execution, isDebugLogEnabled)
143 def volumeParams = utils.getNodeXml(request, 'volume-params')
144 execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
148 * Prepare and send the synchronous response.
150 * @param execution The flow's execution instance.
152 public void sendSynchResponse(DelegateExecution execution, isDebugLogEnabled) {
154 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
155 def requestId = execution.getVariable('UPDVfModVol_requestId')
156 def source = execution.getVariable('UPDVfModVol_source')
157 def progress = getNodeTextForce(requestInfo, 'progress')
158 if (progress.isEmpty()) {
161 def startTime = getNodeTextForce(requestInfo, 'start-time')
162 if (startTime.isEmpty()) {
163 startTime = System.currentTimeMillis()
165 def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
167 String xmlSyncResponse = """
168 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
170 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
171 <action>UPDATE_VF_MODULE_VOL</action>
172 <request-status>IN_PROGRESS</request-status>
173 <progress>${MsoUtils.xmlEscape(progress)}</progress>
174 <start-time>${MsoUtils.xmlEscape(startTime)}</start-time>
175 <source>${MsoUtils.xmlEscape(source)}</source>
181 def syncResponse = ''
182 def isVidRequest = execution.getVariable('UPDVfModVol_isVidRequest')
185 def volumeGroupId = execution.getVariable('volumeGroupId')
186 syncResponse = """{"requestReferences":{"instanceId":"${volumeGroupId}","requestId":"${
190 syncResponse = utils.formatXml(xmlSyncResponse)
193 logger.debug('Sync response: {}', syncResponse)
194 execution.setVariable('UPDVfModVol_syncResponseSent', true)
195 sendWorkflowResponse(execution, 200, syncResponse)
199 * Prepare a Request for querying AAI for Volume Group information using the
200 * Volume Group Id and Aic Cloud Region.
201 * @param execution The flow's execution instance.
203 public void queryAAIForVolumeGroup(DelegateExecution execution, isDebugLogEnabled) {
205 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
206 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
209 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), aicCloudRegion, volumeGroupId)
210 AAIResultWrapper wrapper = getAAIClient().get(uri)
211 Optional<VolumeGroup> volumeGroup = wrapper.asBean(VolumeGroup.class)
212 if (volumeGroup.isPresent()) {
213 execution.setVariable('UPDVfModVol_aaiVolumeGroupResponse', volumeGroup.get())
214 Optional<Relationships> relationships = wrapper.getRelationships()
215 if (relationships.isPresent()) {
216 List<AAIResourceUri> tenantURIList = relationships.get().getRelatedAAIUris(AAIObjectType.TENANT)
217 if (!isEmpty(tenantURIList)) {
218 String volumeGroupTenantId = tenantURIList.get(0).getURIKeys().get("tenant-id")
219 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
220 logger.debug("Received Tenant Id {} from AAI for Volume Group with Volume Group Id {}, AIC Cloud Region ",
221 volumeGroupTenantId, volumeGroupId, aicCloudRegion)
223 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id " + volumeGroupId
224 + ", AIC Cloud Region " + aicCloudRegion)
226 execution.setVariable('UPDVfModVol_relatedVfModuleLink', relationships.get().getRelatedLinks(AAIObjectType.VF_MODULE).get(0))
229 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id " + volumeGroupId
230 + ", AIC Cloud Region " + aicCloudRegion)
233 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group " + volumeGroupId + " not found at AAI")
235 }catch(BpmnError bpmnError){
238 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occured During queryAAIForGenericVnf"+e.getMessage())
243 * Query AAI service instance
245 * @param isDebugEnabled
247 public void queryAAIForGenericVnf(DelegateExecution execution, isDebugEnabled) {
249 def vnfId = execution.getVariable('vnfId')
251 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)
253 Optional<GenericVnf> genericVnf = getAAIClient().get(GenericVnf.class, uri)
254 if (genericVnf.isPresent()) {
255 execution.setVariable('UPDVfModVol_AAIQueryGenericVfnResponse', genericVnf.get())
257 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, 'Generic vnf ' + vnfId + ' was not found in AAI. Return code: 404.')
259 }catch(BpmnError bpmnError){
262 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occured During queryAAIForGenericVnf"+e.getMessage())
267 * Query AAI for VF Module using vf-module-id
269 * @param isDebugLogEnabled
271 public void queryAAIForVfModule(DelegateExecution execution, isDebugLogEnabled) {
273 String queryAAIVfModuleRequest = execution.getVariable('UPDVfModVol_relatedVfModuleLink')
274 execution.setVariable('UPDVfModVol_personaModelId', '')
275 AAIResourceUri uri = AAIUriFactory.createResourceFromExistingURI(AAIObjectType.VF_MODULE, UriBuilder.fromPath(queryAAIVfModuleRequest).build())
277 Optional<VfModule> vfModule = getAAIClient().get(VfModule.class,uri)
278 if(vfModule.isPresent()){
279 execution.setVariable('UPDVfModVol_personaModelId',vfModule.get().getModelInvariantId())
281 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "VF Module not found at AAI")
283 }catch(BpmnError bpmnError){
286 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Error in queryAAIForVfModule: "+e.getMessage())
291 * Prepare a Request for invoking the VnfAdapterRest subflow to do
292 * a Volume Group update.
294 * @param execution The flow's execution instance.
296 public void prepVnfAdapterRest(DelegateExecution execution, isDebugLogEnabled) {
298 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
299 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
300 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
302 VolumeGroup aaiVolumeGroupResponse = execution.getVariable('UPDVfModVol_aaiVolumeGroupResponse')
303 def volumeGroupHeatStackId = aaiVolumeGroupResponse.getHeatStackId()
304 def volumeGroupName = aaiVolumeGroupResponse.getVolumeGroupName()
305 def modelCustomizationId = aaiVolumeGroupResponse.getModelCustomizationId()
307 def vnfType = execution.getVariable('UPDVfModVol_vnfType')
308 def vnfVersion = execution.getVariable('UPDVfModVol_vnfVersion')
310 GenericVnf aaiGenericVnfResponse = execution.getVariable('UPDVfModVol_AAIQueryGenericVfnResponse')
311 def vnfId = aaiGenericVnfResponse.getVnfId()
312 def vnfName = aaiGenericVnfResponse.getVnfName()
315 def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
316 def volumeGroupParams = transformVolumeParamsToEntries(volumeParamsXml)
318 def requestId = execution.getVariable('UPDVfModVol_requestId')
319 def serviceId = execution.getVariable('UPDVfModVol_serviceId')
321 def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
322 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
323 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host", execution)
324 if ('true'.equals(useQualifiedHostName)) {
325 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
328 String vnfAdapterRestRequest = """
329 <updateVolumeGroupRequest>
330 <cloudSiteId>${MsoUtils.xmlEscape(aicCloudRegion)}</cloudSiteId>
331 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
332 <vnfId>${MsoUtils.xmlEscape(vnfId)}</vnfId>
333 <vnfName>${MsoUtils.xmlEscape(vnfName)}</vnfName>
334 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
335 <volumeGroupName>${MsoUtils.xmlEscape(volumeGroupName)}</volumeGroupName>
336 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
337 <vnfType>${MsoUtils.xmlEscape(vnfType)}</vnfType>
338 <vnfVersion>${MsoUtils.xmlEscape(vnfVersion)}</vnfVersion>
339 <vfModuleType></vfModuleType>
340 <modelCustomizationUuid>${MsoUtils.xmlEscape(modelCustomizationId)}</modelCustomizationUuid>
344 <value>${MsoUtils.xmlEscape(vnfId)}</value>
348 <value>${MsoUtils.xmlEscape(vnfName)}</value>
351 <key>vf_module_id</key>
352 <value>${MsoUtils.xmlEscape(volumeGroupId)}</value>
355 <key>vf_module_name</key>
356 <value>${MsoUtils.xmlEscape(volumeGroupName)}</value>
360 <skipAAI>true</skipAAI>
362 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
363 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
365 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
366 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
367 </updateVolumeGroupRequest>
369 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
370 execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
371 logger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
375 * Prepare a Request for updating the DB for this Infra request.
377 * @param execution The flow's execution instance.
379 public void prepDbInfraDbRequest(DelegateExecution execution, isDebugLogEnabled) {
381 def requestId = execution.getVariable('UPDVfModVol_requestId')
383 String updateInfraRequest = """
384 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
385 xmlns:req="http://org.onap.so/requestsdb">
388 <req:updateInfraRequest>
389 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
390 <lastModifiedBy>BPEL</lastModifiedBy>
391 <requestStatus>COMPLETE</requestStatus>
392 <progress>100</progress>
393 </req:updateInfraRequest>
398 updateInfraRequest = utils.formatXml(updateInfraRequest)
399 execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
400 logger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
404 * Build a "CompletionHandler" request.
405 * @param execution The flow's execution instance.
407 public void prepCompletionHandlerRequest(DelegateExecution execution, requestId, action, source, isDebugLogEnabled) {
410 <aetgt:MsoCompletionRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
411 xmlns:ns="http://org.onap/so/request/types/v1">
412 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
413 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
414 <action>UPDATE</action>
415 <source>${MsoUtils.xmlEscape(source)}</source>
417 <aetgt:mso-bpel-name>BPMN VF Module Volume action: UPDATE</aetgt:mso-bpel-name>
418 </aetgt:MsoCompletionRequest>
421 content = utils.formatXml(content)
422 logger.debug('Request for Completion Handler:\n' + content)
423 execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
427 * Build a "FalloutHandler" request.
428 * @param execution The flow's execution instance.
430 public void prepFalloutHandler(DelegateExecution execution, isDebugLogEnabled) {
431 def requestId = execution.getVariable('UPDVfModVol_requestId')
432 def source = execution.getVariable('UPDVfModVol_source')
434 String requestInfo = """
435 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
436 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
437 <action>UPDATE</action>
438 <source>${MsoUtils.xmlEscape(source)}</source>
441 WorkflowException workflowException = execution.getVariable("WorkflowException")
442 def errorResponseCode = workflowException.getErrorCode()
443 def errorResponseMsg = workflowException.getErrorMessage()
444 def encErrorResponseMsg = ""
445 if (errorResponseMsg != null) {
446 encErrorResponseMsg = errorResponseMsg
450 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
451 xmlns:reqtype="http://org.onap/so/request/types/v1"
452 xmlns:msoservtypes="http://org.onap/so/request/types/v1"
453 xmlns:structuredtypes="http://org.onap/so/structured/types/v1">
455 <sdncadapterworkflow:WorkflowException>
456 <sdncadapterworkflow:ErrorMessage>${MsoUtils.xmlEscape(encErrorResponseMsg)}</sdncadapterworkflow:ErrorMessage>
457 <sdncadapterworkflow:ErrorCode>${MsoUtils.xmlEscape(errorResponseCode)}</sdncadapterworkflow:ErrorCode>
458 </sdncadapterworkflow:WorkflowException>
459 </sdncadapterworkflow:FalloutHandlerRequest>
461 content = utils.formatXml(content)
462 logger.debug('Request for Fallout Handler:\n' + content)
463 execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
467 * Create a WorkflowException for the error case where the Tenant Id from
468 * AAI did not match the Tenant Id in the incoming request.
469 * @param execution The flow's execution instance.
471 public void handleTenantIdMismatch(DelegateExecution execution, isDebugLogEnabled) {
473 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
474 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
475 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
476 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
478 String errorMessage = "TenantId " + tenantId + " in incoming request does not match Tenant Id " + volumeGroupTenantId +
479 " retrieved from AAI for Volume Group Id " + volumeGroupId + ", AIC Cloud Region " + aicCloudRegion
481 ExceptionUtil exceptionUtil = new ExceptionUtil()
482 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Error in ' +
483 'UpdateVfModuleVol: ' + errorMessage, "BPMN", ErrorCode.UnknownError.getValue(), "Exception")
484 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, errorMessage)
488 * Create a WorkflowException for the error case where the Personal Model Id from
489 * AAI did not match the model invariant ID in the incoming request.
490 * @param execution The flow's execution instance.
492 public void handlePersonaModelIdMismatch(DelegateExecution execution, isDebugLogEnabled) {
494 def modelInvariantId = execution.getVariable('UPDVfModVol_modelInvariantId')
495 def personaModelId = execution.getVariable('UPDVfModVol_personaModelId')
497 String errorMessage = "Model Invariant ID " + modelInvariantId + " in incoming request does not match persona model ID " + personaModelId +
498 " retrieved from AAI for Volume Group Id "
500 ExceptionUtil exceptionUtil = new ExceptionUtil()
501 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), 'Error in ' +
502 'UpdateVfModuleVol: ' + errorMessage, "BPMN", ErrorCode.UnknownError.getValue(), "Exception")
503 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, errorMessage)