/*- * ============LICENSE_START======================================================= * ONAP - SO * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.onap.so.bpmn.infrastructure.scripts import org.apache.commons.lang3.* import org.camunda.bpm.engine.delegate.BpmnError import org.camunda.bpm.engine.delegate.DelegateExecution import org.onap.so.bpmn.common.scripts.AaiUtil import org.onap.so.bpmn.common.scripts.ExceptionUtil import org.onap.so.bpmn.common.scripts.MsoUtils import org.onap.so.bpmn.common.scripts.VfModuleBase import org.onap.so.bpmn.core.UrnPropertiesReader; import org.onap.so.bpmn.core.WorkflowException import org.onap.so.logger.MessageEnum import org.onap.so.logger.MsoLogger import org.onap.so.rest.APIResponse import org.springframework.web.util.UriUtils class UpdateVfModuleVolume extends VfModuleBase { private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateVfModuleVolume.class); ExceptionUtil exceptionUtil = new ExceptionUtil() /** * Initialize the flow's variables. * * @param execution The flow's execution instance. */ private void initProcessVariables(DelegateExecution execution) { execution.setVariable('prefix', 'UPDVfModVol_') execution.setVariable('UPDVfModVol_Request', null) execution.setVariable('UPDVfModVol_requestInfo', null) execution.setVariable('UPDVfModVol_requestId', null) execution.setVariable('UPDVfModVol_source', null) execution.setVariable('UPDVfModVol_volumeInputs', null) execution.setVariable('UPDVfModVol_volumeGroupId', null) execution.setVariable('UPDVfModVol_vnfType', null) execution.setVariable('UPDVfModVol_serviceId', null) execution.setVariable('UPDVfModVol_aicCloudRegion', null) execution.setVariable('UPDVfModVol_tenantId', null) execution.setVariable('UPDVfModVol_volumeParams', null) execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null) execution.setVariable('UPDVfModVol_volumeGroupTenantId', null) execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false) } /** * Check for missing elements in the received request. * * @param execution The flow's execution instance. */ @Override public void preProcessRequest(DelegateExecution execution) { def method = getClass().getSimpleName() + '.preProcessRequest(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) try { initProcessVariables(execution) String request = validateRequest(execution) def requestInfo = getRequiredNodeXml(execution, request, 'request-info') execution.setVariable('UPDVfModVol_requestInfo', requestInfo) execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id')) execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source')) def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs') execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs) execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id')) execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type')) execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id')) execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region')) execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id')) def volumeParams = utils.getNodeXml(request, 'volume-params') execution.setVariable('UPDVfModVol_volumeParams', volumeParams) msoLogger.trace('Exited ' + method) msoLogger.debug("UpdateVfModuleVolume request: " + request) } catch (BpmnError bpmnError) { throw bpmnError } catch (Exception e) { msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e); exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage()) } } /** * Prepare and send the synchronous response. * * @param execution The flow's execution instance. */ public void sendSynchResponse(DelegateExecution execution) { def method = getClass().getSimpleName() + '.sendSynchResponse(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) try { def requestInfo = execution.getVariable('UPDVfModVol_requestInfo') def requestId = execution.getVariable('UPDVfModVol_requestId') def source = execution.getVariable('UPDVfModVol_source') def progress = getNodeTextForce(requestInfo, 'progress') if (progress.isEmpty()) { progress = '0' } def startTime = getNodeTextForce(requestInfo, 'start-time') if (startTime.isEmpty()) { startTime = System.currentTimeMillis() } def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs') String synchResponse = """ ${MsoUtils.xmlEscape(requestId)} UPDATE_VF_MODULE_VOL IN_PROGRESS ${MsoUtils.xmlEscape(progress)} ${MsoUtils.xmlEscape(startTime)} ${MsoUtils.xmlEscape(source)} ${volumeInputs} """ synchResponse = utils.formatXml(synchResponse) sendWorkflowResponse(execution, 200, synchResponse) msoLogger.debug("UpdateVfModuleVolume Synch Response: " + synchResponse) } catch (BpmnError e) { throw e; } catch (Exception e) { msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e); exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage()) } } /** * Prepare a Request for querying AAI for Volume Group information using the * Volume Group Id and Aic Cloud Region. * * @param execution The flow's execution instance. */ public void queryAAIForVolumeGroup(DelegateExecution execution) { def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) try { def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId') def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion') def endPoint = UrnPropertiesReader.getVariable("aai.endpoint", execution) + '/aai/v7/cloud-infrastructure/cloud-regions/cloud-region/att-aic/' + UriUtils.encode(aicCloudRegion, "UTF-8") + '/volume-groups/volume-group/' + UriUtils.encode(volumeGroupId, "UTF-8") msoLogger.debug('Sending GET to AAI endpoint \'' + endPoint + '\'') msoLogger.debug("UpdateVfModuleVolume sending GET for quering AAI endpoint: " + endPoint) AaiUtil aaiUtil = new AaiUtil(this) APIResponse response = aaiUtil.executeAAIGetCall(execution, endPoint) def int statusCode = response.getStatusCode() def responseData = response.getResponseBodyAsString() msoLogger.debug('Response code:' + statusCode) msoLogger.debug('Response:' + System.lineSeparator() + responseData) msoLogger.debug("UpdateVfModuleVolume response data: " + responseData) def volumeGroup = responseData def heatStackId = getNodeTextForce(volumeGroup, 'heat-stack-id') execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId) if ((statusCode == 200) || (statusCode == 204)) { def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroup) if (volumeGroupTenantId == null) { throw new Exception('Could not find Tenant Id element in Volume Group with Volume Group Id \'' + volumeGroupId + '\'' + '\', AIC Cloud Region \'' + aicCloudRegion + '\'') } execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId) msoLogger.debug('Received Tenant Id \'' + volumeGroupTenantId + '\' from AAI for Volume Group with Volume Group Id \'' + volumeGroupId + '\'' + '\', AIC Cloud Region \'' + aicCloudRegion + '\'') } else if (statusCode == 404) { throw new Exception('Volume Group \'' + volumeGroupId + '\' not found at AAI') } else { throw new Exception('Bad status code ' + statusCode + ' received from AAI; Response data: ' + responseData) } msoLogger.trace('Exited ' + method) } catch (BpmnError e) { throw e; } catch (Exception e) { msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e); exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage()) } } /** * Prepare a Request for invoking the VnfAdapterRest subflow to do * a Volume Group update. * * @param execution The flow's execution instance. */ public void prepVnfAdapterRest(DelegateExecution execution) { def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) try { def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion') def tenantId = execution.getVariable('UPDVfModVol_tenantId') def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId') def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId') def vnfType = execution.getVariable('UPDVfModVol_vnfType') def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams') def volumeGroupParams = transformParamsToEntries(volumeParamsXml) def requestId = execution.getVariable('UPDVfModVol_requestId') def serviceId = execution.getVariable('UPDVfModVol_serviceId') def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis() def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId) def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host",execution) if ('true'.equals(useQualifiedHostName)) { notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl) } String vnfAdapterRestRequest = """ ${MsoUtils.xmlEscape(aicCloudRegion)} ${MsoUtils.xmlEscape(tenantId)} ${MsoUtils.xmlEscape(volumeGroupId)} ${MsoUtils.xmlEscape(volumeGroupHeatStackId)} ${MsoUtils.xmlEscape(vnfType)} ${volumeGroupParams} true ${MsoUtils.xmlEscape(requestId)} ${MsoUtils.xmlEscape(serviceId)} ${MsoUtils.xmlEscape(messageId)} ${MsoUtils.xmlEscape(notificationUrl)} """ vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest) execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest) msoLogger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest) msoLogger.debug("UpdateVfModuleVolume Request for VNFAdapter Rest: " + vnfAdapterRestRequest) msoLogger.trace('Exited ' + method) } catch (BpmnError e) { throw e; } catch (Exception e) { msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e); exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage()) } } /** * Prepare a Request for updating the DB for this Infra request. * * @param execution The flow's execution instance. */ public void prepDbInfraDbRequest(DelegateExecution execution) { def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) try { def requestId = execution.getVariable('UPDVfMod_requestId') String updateInfraRequest = """ ${MsoUtils.xmlEscape(requestId)} BPEL COMPLETE 100 """ updateInfraRequest = utils.formatXml(updateInfraRequest) execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest) msoLogger.debug('Request for Update Infra Request:\n' + updateInfraRequest) msoLogger.debug("UpdateVfModuleVolume Request for Updating DB for Infra: " + updateInfraRequest) msoLogger.trace('Exited ' + method) } catch (BpmnError e) { throw e; } catch (Exception e) { msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e); exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage()) } } /** * Build a "CompletionHandler" request. * * @param execution The flow's execution instance. */ public void prepCompletionHandlerRequest(DelegateExecution execution) { def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) try { def requestInfo = execution.getVariable('UPDVfModVol_requestInfo') String content = """ ${requestInfo} MSO_ACTIVATE_BPEL """ content = utils.formatXml(content) msoLogger.debug('Request for Completion Handler:\n' + content) msoLogger.debug("UpdateVfModuleVolume Completion Handler request: " + content) execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content) msoLogger.trace('Exited ' + method) } catch (BpmnError e) { throw e; } catch (Exception e) { msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e); exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage()) } } /** * Build a "FalloutHandler" request. * * @param execution The flow's execution instance. */ public void prepFalloutHandler(DelegateExecution execution) { def method = getClass().getSimpleName() + '.prepFalloutHandler(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) try { def requestInfo = execution.getVariable('UPDVfModVol_requestInfo') def WorkflowException workflowException = execution.getVariable("WorkflowException") def errorResponseCode = workflowException.getErrorCode() def errorResponseMsg = workflowException.getErrorMessage() def encErrorResponseMsg = "" if (errorResponseMsg != null) { encErrorResponseMsg = errorResponseMsg } String content = """ ${requestInfo} ${MsoUtils.xmlEscape(encErrorResponseMsg)} ${MsoUtils.xmlEscape(errorResponseCode)} """ content = utils.formatXml(content) msoLogger.debug('Request for Fallout Handler:\n' + content) msoLogger.debug("UpdateVfModuleVolume Fallout request: " + content) execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content) msoLogger.trace('Exited ' + method) } catch (BpmnError e) { throw e; } catch (Exception e) { msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e); exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage()) } } /** * Create a WorkflowException for the error case where the Tenant Id from * AAI did not match the Tenant Id in the incoming request. * * @param execution The flow's execution instance. */ public void handleTenantIdMismatch(DelegateExecution execution) { def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' + 'execution=' + execution.getId() + ')' msoLogger.trace('Entered ' + method) String processKey = getProcessKey(execution); def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId') def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion') def tenantId = execution.getVariable('UPDVfModVol_tenantId') def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId') def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId + '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\'' msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Error in UpdateVfModuleVol: ' + errorMessage, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception"); WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage); execution.setVariable("WorkflowException", exception); msoLogger.trace('Exited ' + method) msoLogger.debug("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage) } }