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 org.apache.commons.collections.CollectionUtils
26 import org.camunda.bpm.engine.delegate.BpmnError
27 import org.camunda.bpm.engine.delegate.DelegateExecution
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.core.UrnPropertiesReader
33 import org.onap.so.bpmn.core.WorkflowException
34 import org.onap.so.client.aai.AAIObjectType
35 import org.onap.so.client.aai.entities.AAIResultWrapper
36 import org.onap.so.client.aai.entities.Relationships
37 import org.onap.so.client.aai.entities.uri.AAIResourceUri
38 import org.onap.so.client.aai.entities.uri.AAIUriFactory
39 import org.onap.so.constants.Defaults
40 import org.onap.so.logger.MessageEnum
41 import org.onap.so.logger.MsoLogger
42 import org.slf4j.Logger
43 import org.slf4j.LoggerFactory
45 import static org.apache.commons.lang.StringUtils.isEmpty
47 class UpdateVfModuleVolume extends VfModuleBase {
48 private static final Logger logger = LoggerFactory.getLogger(UpdateVfModuleVolume.class)
50 ExceptionUtil exceptionUtil = new ExceptionUtil()
53 * Initialize the flow's variables.
55 * @param execution The flow's execution instance.
57 private void initProcessVariables(DelegateExecution execution) {
58 execution.setVariable('prefix', 'UPDVfModVol_')
59 execution.setVariable('UPDVfModVol_Request', null)
60 execution.setVariable('UPDVfModVol_requestInfo', null)
61 execution.setVariable('UPDVfModVol_requestId', null)
62 execution.setVariable('UPDVfModVol_source', null)
63 execution.setVariable('UPDVfModVol_volumeInputs', null)
64 execution.setVariable('UPDVfModVol_volumeGroupId', null)
65 execution.setVariable('UPDVfModVol_vnfType', null)
66 execution.setVariable('UPDVfModVol_serviceId', null)
67 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
68 execution.setVariable('UPDVfModVol_tenantId', null)
69 execution.setVariable('UPDVfModVol_volumeParams', null)
70 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
71 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
72 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
76 * Check for missing elements in the received request.
78 * @param execution The flow's execution instance.
81 public void preProcessRequest(DelegateExecution execution) {
82 def method = getClass().getSimpleName() + '.preProcessRequest(' +
83 'execution=' + execution.getId() +
86 logger.trace('Entered {}', method)
89 initProcessVariables(execution)
90 String request = validateRequest(execution)
92 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
93 execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
94 execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
95 execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
97 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
98 execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
99 execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
100 execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
101 execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id'))
102 execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
103 execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
105 def volumeParams = utils.getNodeXml(request, 'volume-params')
106 execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
108 logger.trace('Exited {}', method)
109 logger.debug("UpdateVfModuleVolume request: {}", request)
110 } catch (BpmnError bpmnError) {
112 } catch (Exception e) {
113 logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
114 MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
115 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
120 * Prepare and send the synchronous response.
122 * @param execution The flow's execution instance.
124 public void sendSynchResponse(DelegateExecution execution) {
125 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
126 'execution=' + execution.getId() +
129 logger.trace('Entered {}', method)
132 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
133 def requestId = execution.getVariable('UPDVfModVol_requestId')
134 def source = execution.getVariable('UPDVfModVol_source')
135 def progress = getNodeTextForce(requestInfo, 'progress')
136 if (progress.isEmpty()) {
139 def startTime = getNodeTextForce(requestInfo, 'start-time')
140 if (startTime.isEmpty()) {
141 startTime = System.currentTimeMillis()
143 def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
145 String synchResponse = """
146 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
148 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
149 <action>UPDATE_VF_MODULE_VOL</action>
150 <request-status>IN_PROGRESS</request-status>
151 <progress>${MsoUtils.xmlEscape(progress)}</progress>
152 <start-time>${MsoUtils.xmlEscape(startTime)}</start-time>
153 <source>${MsoUtils.xmlEscape(source)}</source>
159 synchResponse = utils.formatXml(synchResponse)
160 sendWorkflowResponse(execution, 200, synchResponse)
161 logger.debug("UpdateVfModuleVolume Synch Response: {}", synchResponse)
162 } catch (BpmnError e) {
164 } catch (Exception e) {
165 logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
166 MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
167 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
172 * Prepare a Request for querying AAI for Volume Group information using the
173 * Volume Group Id and Aic Cloud Region.
175 * @param execution The flow's execution instance.
177 public void queryAAIForVolumeGroup(DelegateExecution execution) {
178 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
179 'execution=' + execution.getId() +
182 logger.trace('Entered {}', method)
185 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
186 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
187 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(),aicCloudRegion,volumeGroupId)
188 AAIResultWrapper wrapper = getAAIClient().get(uri)
189 Optional<VolumeGroup> volumeGroup = wrapper.asBean(VolumeGroup.class)
190 if(volumeGroup.isPresent()){
191 def heatStackId = volumeGroup.get().getHeatStackId()
192 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId)
193 Optional<Relationships> relationships = wrapper.getRelationships()
194 if(relationships.isPresent()){
195 List<AAIResourceUri> resourceUriList = relationships.get().getRelatedAAIUris(AAIObjectType.TENANT)
196 if(CollectionUtils.isNotEmpty(resourceUriList)){
197 AAIResourceUri tenantUri = resourceUriList.get(0)
198 String volumeGroupTenantId = tenantUri.getURIKeys().get("tenant-id")
199 if( isEmpty(volumeGroupTenantId)){
200 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Could not find Tenant Id element in Volume Group with Volume Group Id" + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
202 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
203 logger.debug("Received Tenant Id: {} from AAI for Volume Group with Volume Group Id: {}, AIC Cloud Region",
204 volumeGroupTenantId, volumeGroupId, aicCloudRegion)
206 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Could not find Tenant Id element in Volume Group with Volume Group Id" + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
210 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Volume Group" + volumeGroupId + " not found at AAI")
212 logger.trace('Exited {}', method)
213 } catch (BpmnError e) {
215 } catch (Exception e) {
216 logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
217 MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
218 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
223 * Prepare a Request for invoking the VnfAdapterRest subflow to do
224 * a Volume Group update.
226 * @param execution The flow's execution instance.
228 public void prepVnfAdapterRest(DelegateExecution execution) {
229 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
230 'execution=' + execution.getId() +
233 logger.trace('Entered {}', method)
236 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
237 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
238 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
239 def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId')
240 def vnfType = execution.getVariable('UPDVfModVol_vnfType')
242 def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
243 def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
245 def requestId = execution.getVariable('UPDVfModVol_requestId')
246 def serviceId = execution.getVariable('UPDVfModVol_serviceId')
248 def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
249 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
250 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host",execution)
251 if ('true'.equals(useQualifiedHostName)) {
252 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
255 String vnfAdapterRestRequest = """
256 <updateVolumeGroupRequest>
257 <cloudSiteId>${MsoUtils.xmlEscape(aicCloudRegion)}</cloudSiteId>
258 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
259 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
260 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
261 <vnfType>${MsoUtils.xmlEscape(vnfType)}</vnfType>
262 <vnfVersion></vnfVersion>
263 <vfModuleType></vfModuleType>
267 <skipAAI>true</skipAAI>
269 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
270 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
272 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
273 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
274 </updateVolumeGroupRequest>
276 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
277 execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
278 logger.debug('Request for VNFAdapter Rest:\n{}', vnfAdapterRestRequest)
280 logger.debug("UpdateVfModuleVolume Request for VNFAdapter Rest: {}", vnfAdapterRestRequest)
281 logger.trace('Exited {}', method)
282 } catch (BpmnError e) {
284 } catch (Exception e) {
285 logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
286 MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
287 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
292 * Prepare a Request for updating the DB for this Infra request.
294 * @param execution The flow's execution instance.
296 public void prepDbInfraDbRequest(DelegateExecution execution) {
297 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
298 'execution=' + execution.getId() +
301 logger.trace('Entered {}', method)
304 def requestId = execution.getVariable('UPDVfMod_requestId')
306 String updateInfraRequest = """
307 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
308 xmlns:req="http://org.onap.so/requestsdb">
311 <req:updateInfraRequest>
312 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
313 <lastModifiedBy>BPEL</lastModifiedBy>
314 <requestStatus>COMPLETE</requestStatus>
315 <progress>100</progress>
316 </req:updateInfraRequest>
321 updateInfraRequest = utils.formatXml(updateInfraRequest)
322 execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
323 logger.debug('Request for Update Infra Request:\n{}', updateInfraRequest)
325 logger.debug("UpdateVfModuleVolume Request for Updating DB for Infra: {}", updateInfraRequest)
326 logger.trace('Exited {}', method)
327 } catch (BpmnError e) {
329 } catch (Exception e) {
330 logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
331 MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
332 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
337 * Build a "CompletionHandler" request.
339 * @param execution The flow's execution instance.
341 public void prepCompletionHandlerRequest(DelegateExecution execution) {
342 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
343 'execution=' + execution.getId() +
346 logger.trace('Entered {}', method)
349 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
352 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
353 xmlns:reqtype="http://org.onap/so/request/types/v1">
355 <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
356 </sdncadapterworkflow:MsoCompletionRequest>
359 content = utils.formatXml(content)
360 logger.debug('Request for Completion Handler:\n{}', content)
361 logger.debug("UpdateVfModuleVolume Completion Handler request: {}", content)
362 execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
364 logger.trace('Exited {}', method)
365 } catch (BpmnError e) {
367 } catch (Exception e) {
368 logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
369 MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
370 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
375 * Build a "FalloutHandler" request.
377 * @param execution The flow's execution instance.
379 public void prepFalloutHandler(DelegateExecution execution) {
380 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
381 'execution=' + execution.getId() +
384 logger.trace('Entered {}', method)
387 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
389 def WorkflowException workflowException = execution.getVariable("WorkflowException")
390 def errorResponseCode = workflowException.getErrorCode()
391 def errorResponseMsg = workflowException.getErrorMessage()
392 def encErrorResponseMsg = ""
393 if (errorResponseMsg != null) {
394 encErrorResponseMsg = errorResponseMsg
398 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
399 xmlns:reqtype="http://org.onap/so/request/types/v1"
400 xmlns:msoservtypes="http://org.onap/so/request/types/v1"
401 xmlns:structuredtypes="http://org.onap/so/structured/types/v1">
403 <sdncadapterworkflow:WorkflowException>
404 <sdncadapterworkflow:ErrorMessage>${MsoUtils.xmlEscape(encErrorResponseMsg)}</sdncadapterworkflow:ErrorMessage>
405 <sdncadapterworkflow:ErrorCode>${MsoUtils.xmlEscape(errorResponseCode)}</sdncadapterworkflow:ErrorCode>
406 </sdncadapterworkflow:WorkflowException>
407 </sdncadapterworkflow:FalloutHandlerRequest>
409 content = utils.formatXml(content)
410 logger.debug('Request for Fallout Handler:\n{}', content)
411 logger.debug("UpdateVfModuleVolume Fallout request: {}", content)
412 execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
414 logger.trace('Exited {}', method)
415 } catch (BpmnError e) {
417 } catch (Exception e) {
418 logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
419 MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
420 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
425 * Create a WorkflowException for the error case where the Tenant Id from
426 * AAI did not match the Tenant Id in the incoming request.
428 * @param execution The flow's execution instance.
430 public void handleTenantIdMismatch(DelegateExecution execution) {
431 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
432 'execution=' + execution.getId() +
435 logger.trace('Entered {}', method)
437 String processKey = getProcessKey(execution)
438 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
439 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
440 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
441 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
443 def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId +
444 '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\''
446 logger.error("{} {} Error in UpdateVfModuleVol: {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
447 MsoLogger.ErrorCode.UnknownError.getValue(), errorMessage)
449 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage)
450 execution.setVariable("WorkflowException", exception)
452 logger.trace('Exited ' + method)
453 logger.debug("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)