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.openecomp.mso.bpmn.infrastructure.scripts
 
  23 import java.util.concurrent.ExecutionException;
 
  25 import org.camunda.bpm.engine.delegate.BpmnError
 
  26 import org.camunda.bpm.engine.runtime.Execution
 
  27 import org.apache.commons.lang3.*
 
  28 import org.springframework.web.util.UriUtils
 
  29 import org.openecomp.mso.bpmn.common.scripts.AaiUtil
 
  30 import org.openecomp.mso.bpmn.common.scripts.VfModuleBase
 
  31 import org.openecomp.mso.bpmn.core.WorkflowException
 
  32 import org.openecomp.mso.bpmn.core.json.JsonUtils;
 
  33 import org.openecomp.mso.rest.APIResponse
 
  34 import org.openecomp.mso.bpmn.common.scripts.ExceptionUtil
 
  36 class UpdateVfModuleVolume extends VfModuleBase {
 
  38         ExceptionUtil exceptionUtil = new ExceptionUtil()
 
  41          * Initialize the flow's variables.
 
  43          * @param execution The flow's execution instance.
 
  45         private void initProcessVariables(Execution execution) {
 
  46                 execution.setVariable('prefix', 'UPDVfModVol_')
 
  47                 execution.setVariable('UPDVfModVol_Request', null)
 
  48                 execution.setVariable('UPDVfModVol_requestInfo', null)
 
  49                 execution.setVariable('UPDVfModVol_requestId', null)
 
  50                 execution.setVariable('UPDVfModVol_source', null)
 
  51                 execution.setVariable('UPDVfModVol_volumeInputs', null)
 
  52                 execution.setVariable('UPDVfModVol_volumeGroupId', null)
 
  53                 execution.setVariable('UPDVfModVol_vnfType', null)
 
  54                 execution.setVariable('UPDVfModVol_serviceId', null)
 
  55                 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
 
  56                 execution.setVariable('UPDVfModVol_tenantId', null)
 
  57                 execution.setVariable('UPDVfModVol_volumeParams', null)
 
  58                 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
 
  59                 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
 
  60                 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
 
  64          * Check for missing elements in the received request.
 
  66          * @param execution The flow's execution instance.
 
  69         public void preProcessRequest(Execution execution) {
 
  70                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
 
  71                         'execution=' + execution.getId() +
 
  73                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
  74                 logDebug('Entered ' + method, isDebugLogEnabled)
 
  77                         initProcessVariables(execution)
 
  78                         String request = validateRequest(execution)
 
  80                         def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
 
  81                         execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
 
  82                         execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
 
  83                         execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
 
  85                         def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
 
  86                         execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
 
  87                         execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
 
  88                         execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
 
  89                         execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id'))
 
  90                         execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
 
  91                         execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
 
  93                         def volumeParams = utils.getNodeXml(request, 'volume-params')
 
  94                         execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
 
  96                         logDebug('Exited ' + method, isDebugLogEnabled)
 
  97                         utils.logAudit("UpdateVfModuleVolume request: " + request)
 
  98                 } catch (BpmnError bpmnError) {
 
 100                 } catch (Exception e) {
 
 101                         logError('Caught exception in ' + method, e)
 
 102                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
 
 107          * Prepare and send the synchronous response.
 
 109          * @param execution The flow's execution instance.
 
 111         public void sendSynchResponse(Execution execution) {
 
 112                 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
 
 113                         'execution=' + execution.getId() +
 
 115                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
 116                 logDebug('Entered ' + method, isDebugLogEnabled)
 
 119                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
 
 120                         def requestId = execution.getVariable('UPDVfModVol_requestId')
 
 121                         def source = execution.getVariable('UPDVfModVol_source')
 
 122                         def progress = getNodeTextForce(requestInfo, 'progress')
 
 123                         if (progress.isEmpty()) {
 
 126                         def startTime = getNodeTextForce(requestInfo, 'start-time')
 
 127                         if (startTime.isEmpty()) {
 
 128                                 startTime = System.currentTimeMillis()
 
 130                         def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
 
 132                         String synchResponse = """
 
 133                                 <volume-request xmlns="http://org.openecomp/mso/infra/vnf-request/v1">
 
 135                                                 <request-id>${requestId}</request-id>
 
 136                                                 <action>UPDATE_VF_MODULE_VOL</action>
 
 137                                                 <request-status>IN_PROGRESS</request-status>
 
 138                                                 <progress>${progress}</progress>
 
 139                                                 <start-time>${startTime}</start-time>
 
 140                                                 <source>${source}</source>
 
 146                         synchResponse = utils.formatXml(synchResponse)
 
 147                         sendWorkflowResponse(execution, 200, synchResponse)
 
 148                         utils.logAudit("UpdateVfModuleVolume Synch Response: " + synchResponse)
 
 149                 } catch (BpmnError e) {
 
 151                 } catch (Exception e) {
 
 152                         logError('Caught exception in ' + method, e)
 
 153                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
 
 158          * Prepare a Request for querying AAI for Volume Group information using the
 
 159          * Volume Group Id and Aic Cloud Region.
 
 161          * @param execution The flow's execution instance.
 
 163         public void queryAAIForVolumeGroup(Execution execution) {
 
 164                 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
 
 165                         'execution=' + execution.getId() +
 
 167                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
 168                 logDebug('Entered ' + method, isDebugLogEnabled)
 
 171                         def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
 
 172                         def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
 
 173                         def endPoint = execution.getVariable('URN_aai_endpoint') +
 
 174                                 '/aai/v7/cloud-infrastructure/cloud-regions/cloud-region/att-aic/' + UriUtils.encode(aicCloudRegion, "UTF-8") +
 
 175                                 '/volume-groups/volume-group/' + UriUtils.encode(volumeGroupId, "UTF-8")
 
 177                         logDebug('Sending GET to AAI endpoint \'' + endPoint + '\'', isDebugLogEnabled)
 
 178                         utils.logAudit("UpdateVfModuleVolume sending GET for quering AAI endpoint: " + endPoint)
 
 180                         AaiUtil aaiUtil = new AaiUtil(this)
 
 181                         APIResponse response = aaiUtil.executeAAIGetCall(execution, endPoint)
 
 182                         def int statusCode = response.getStatusCode()
 
 183                         def responseData = response.getResponseBodyAsString()
 
 184                         logDebug('Response code:' + statusCode, isDebugLogEnabled)
 
 185                         logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
 
 186                         utils.logAudit("UpdateVfModuleVolume response data: " + responseData)
 
 188                         def volumeGroup = responseData
 
 189                         def heatStackId = getNodeTextForce(volumeGroup, 'heat-stack-id')
 
 190                         execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId)
 
 191                         if ((statusCode == 200) || (statusCode == 204)) {
 
 192                                 def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroup)
 
 193                                 if (volumeGroupTenantId == null) {
 
 194                                         throw new Exception('Could not find Tenant Id element in Volume Group with Volume Group Id \'' + volumeGroupId + '\''
 
 195                                                 + '\', AIC Cloud Region \'' + aicCloudRegion + '\'')
 
 197                                 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
 
 198                                 logDebug('Received Tenant Id \'' + volumeGroupTenantId + '\' from AAI for Volume Group with Volume Group Id \'' + volumeGroupId + '\''
 
 199                                         + '\', AIC Cloud Region \'' + aicCloudRegion + '\'', isDebugLogEnabled)
 
 200                         } else if (statusCode == 404) {
 
 201                                 throw new Exception('Volume Group \'' + volumeGroupId + '\' not found at AAI')
 
 203                                 throw new Exception('Bad status code ' + statusCode + ' received from AAI; Response data: ' + responseData)
 
 206                         logDebug('Exited ' + method, isDebugLogEnabled)
 
 207                 } catch (BpmnError e) {
 
 209                 } catch (Exception e) {
 
 210                         logError('Caught exception in ' + method, e)
 
 211                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
 
 216          * Prepare a Request for invoking the VnfAdapterRest subflow to do
 
 217          * a Volume Group update.
 
 219          * @param execution The flow's execution instance.
 
 221         public void prepVnfAdapterRest(Execution execution) {
 
 222                 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
 
 223                         'execution=' + execution.getId() +
 
 225                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
 226                 logDebug('Entered ' + method, isDebugLogEnabled)
 
 229                         def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
 
 230                         def tenantId = execution.getVariable('UPDVfModVol_tenantId')
 
 231                         def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
 
 232                         def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId')
 
 233                         def vnfType = execution.getVariable('UPDVfModVol_vnfType')
 
 235                         def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
 
 236                         def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
 
 238                         def requestId = execution.getVariable('UPDVfModVol_requestId')
 
 239                         def serviceId = execution.getVariable('UPDVfModVol_serviceId')
 
 241                         def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
 
 242                         def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
 
 243                         def useQualifiedHostName = execution.getVariable("URN_mso_use_qualified_host")
 
 244                         if ('true'.equals(useQualifiedHostName)) {
 
 245                                         notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
 
 248                         String vnfAdapterRestRequest = """
 
 249                                 <updateVolumeGroupRequest>
 
 250                                         <cloudSiteId>${aicCloudRegion}</cloudSiteId>
 
 251                                         <tenantId>${tenantId}</tenantId>
 
 252                                         <volumeGroupId>${volumeGroupId}</volumeGroupId>
 
 253                                         <volumeGroupStackId>${volumeGroupHeatStackId}</volumeGroupStackId>
 
 254                                         <vnfType>${vnfType}</vnfType>
 
 255                                         <vnfVersion></vnfVersion>
 
 256                                         <vfModuleType></vfModuleType>
 
 260                                         <skipAAI>true</skipAAI>
 
 262                                         <requestId>${requestId}</requestId>
 
 263                                         <serviceInstanceId>${serviceId}</serviceInstanceId>
 
 265                                     <messageId>${messageId}</messageId>
 
 266                                     <notificationUrl>${notificationUrl}</notificationUrl>
 
 267                                 </updateVolumeGroupRequest>
 
 269                         vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
 
 270                         execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
 
 271                         logDebug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest, isDebugLogEnabled)
 
 273                         utils.logAudit("UpdateVfModuleVolume Request for VNFAdapter Rest: " + vnfAdapterRestRequest)
 
 274                         logDebug('Exited ' + method, isDebugLogEnabled)
 
 275                 } catch (BpmnError e) {
 
 277                 } catch (Exception e) {
 
 278                         logError('Caught exception in ' + method, e)
 
 279                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
 
 284          * Prepare a Request for updating the DB for this Infra request.
 
 286          * @param execution The flow's execution instance.
 
 288         public void prepDbInfraDbRequest(Execution execution) {
 
 289                 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
 
 290                         'execution=' + execution.getId() +
 
 292                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
 293                 logDebug('Entered ' + method, isDebugLogEnabled)
 
 296                         def requestId = execution.getVariable('UPDVfMod_requestId')
 
 298                         String updateInfraRequest = """
 
 299                                 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 
 300                                                 xmlns:req="http://org.openecomp.mso/requestsdb">
 
 303                                                 <req:updateInfraRequest>
 
 304                                                         <requestId>${requestId}</requestId>
 
 305                                                         <lastModifiedBy>BPEL</lastModifiedBy>
 
 306                                                         <requestStatus>COMPLETE</requestStatus>
 
 307                                                         <progress>100</progress>
 
 308                                                 </req:updateInfraRequest>
 
 313                         updateInfraRequest = utils.formatXml(updateInfraRequest)
 
 314                         execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
 
 315                         logDebug('Request for Update Infra Request:\n' + updateInfraRequest, isDebugLogEnabled)
 
 317                         utils.logAudit("UpdateVfModuleVolume Request for Updating DB for Infra: " + updateInfraRequest)
 
 318                         logDebug('Exited ' + method, isDebugLogEnabled)
 
 319                 } catch (BpmnError e) {
 
 321                 } catch (Exception e) {
 
 322                         logError('Caught exception in ' + method, e)
 
 323                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
 
 328          * Build a "CompletionHandler" request.
 
 330          * @param execution The flow's execution instance.
 
 332         public void prepCompletionHandlerRequest(Execution execution) {
 
 333                 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
 
 334                         'execution=' + execution.getId() +
 
 336                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
 337                 logDebug('Entered ' + method, isDebugLogEnabled)
 
 340                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
 
 343                                 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.openecomp/mso/workflow/schema/v1"
 
 344                                                 xmlns:reqtype="http://org.openecomp/mso/request/types/v1">
 
 346                                         <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
 
 347                                 </sdncadapterworkflow:MsoCompletionRequest>
 
 350                         content = utils.formatXml(content)
 
 351                         logDebug('Request for Completion Handler:\n' + content, isDebugLogEnabled)
 
 352                         utils.logAudit("UpdateVfModuleVolume Completion Handler request: " + content)
 
 353                         execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
 
 355                         logDebug('Exited ' + method, isDebugLogEnabled)
 
 356                 } catch (BpmnError e) {
 
 358                 } catch (Exception e) {
 
 359                         logError('Caught exception in ' + method, e)
 
 360                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
 
 365          * Build a "FalloutHandler" request.
 
 367          * @param execution The flow's execution instance.
 
 369         public void prepFalloutHandler(Execution execution) {
 
 370                 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
 
 371                         'execution=' + execution.getId() +
 
 373                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
 374                 logDebug('Entered ' + method, isDebugLogEnabled)
 
 377                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
 
 379                         def WorkflowException workflowException = execution.getVariable("WorkflowException")
 
 380                         def errorResponseCode = workflowException.getErrorCode()
 
 381                         def errorResponseMsg = workflowException.getErrorMessage()
 
 382                         def encErrorResponseMsg = ""
 
 383                         if (errorResponseMsg != null) {
 
 384                                 encErrorResponseMsg = errorResponseMsg.replace("&", "&").replace("<", "<").replace(">", ">")
 
 388                                 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.openecomp/mso/workflow/schema/v1"
 
 389                                                 xmlns:reqtype="http://org.openecomp/mso/request/types/v1"
 
 390                                                 xmlns:msoservtypes="http://org.openecomp/mso/request/types/v1"
 
 391                                                 xmlns:structuredtypes="http://org.openecomp/mso/structured/types/v1">
 
 393                                         <sdncadapterworkflow:WorkflowException>
 
 394                                                 <sdncadapterworkflow:ErrorMessage>${encErrorResponseMsg}</sdncadapterworkflow:ErrorMessage>
 
 395                                                 <sdncadapterworkflow:ErrorCode>${errorResponseCode}</sdncadapterworkflow:ErrorCode>
 
 396                                         </sdncadapterworkflow:WorkflowException>
 
 397                                 </sdncadapterworkflow:FalloutHandlerRequest>
 
 399                         content = utils.formatXml(content)
 
 400                         logDebug('Request for Fallout Handler:\n' + content, isDebugLogEnabled)
 
 401                         utils.logAudit("UpdateVfModuleVolume Fallout request: " + content)
 
 402                         execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
 
 404                         logDebug('Exited ' + method, isDebugLogEnabled)
 
 405                 } catch (BpmnError e) {
 
 407                 } catch (Exception e) {
 
 408                         logError('Caught exception in ' + method, e)
 
 409                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
 
 414          * Create a WorkflowException for the error case where the Tenant Id from
 
 415          * AAI did not match the Tenant Id in the incoming request.
 
 417          * @param execution The flow's execution instance.
 
 419         public void handleTenantIdMismatch(Execution execution) {
 
 420                 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
 
 421                         'execution=' + execution.getId() +
 
 423                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
 
 424                 logDebug('Entered ' + method, isDebugLogEnabled)
 
 426                 String processKey = getProcessKey(execution);
 
 427                 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
 
 428                 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
 
 429                 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
 
 430                 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
 
 432                 def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId +
 
 433                         '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\''
 
 435                 logError('Error in UpdateVfModuleVol: ' + errorMessage)
 
 437                 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage);
 
 438                 execution.setVariable("WorkflowException", exception);
 
 440                 logDebug('Exited ' + method, isDebugLogEnabled)
 
 441                 utils.logAudit("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)