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.lang3.StringUtils
 
  26 import org.camunda.bpm.engine.delegate.BpmnError
 
  27 import org.camunda.bpm.engine.delegate.DelegateExecution
 
  28 import org.onap.aai.domain.yang.Relationship
 
  29 import org.onap.aai.domain.yang.RelationshipData
 
  30 import org.onap.aai.domain.yang.VolumeGroup
 
  31 import org.onap.so.bpmn.common.scripts.AaiUtil
 
  32 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
 
  33 import org.onap.so.bpmn.common.scripts.ExceptionUtil
 
  34 import org.onap.so.bpmn.common.scripts.MsoUtils
 
  35 import org.onap.so.bpmn.core.UrnPropertiesReader;
 
  36 import org.onap.so.bpmn.core.WorkflowException
 
  37 import org.onap.so.bpmn.core.json.JsonUtils
 
  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.slf4j.Logger
 
  45 import org.slf4j.LoggerFactory
 
  46 import javax.ws.rs.NotFoundException
 
  48 class DoDeleteVfModuleVolumeV2 extends AbstractServiceTaskProcessor{
 
  49     private static final Logger logger = LoggerFactory.getLogger( DoDeleteVfModuleVolumeV2.class);
 
  51         String prefix="DDVMV_"
 
  52         ExceptionUtil exceptionUtil = new ExceptionUtil()
 
  53         XmlParser xmlParser = new XmlParser()
 
  54         JsonUtils jsonUtil = new JsonUtils()
 
  57         public void preProcessRequest(DelegateExecution execution) {
 
  58                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
 
  59                 preProcessRequest(execution, isDebugEnabled)
 
  63          * Set default variable values
 
  65          * @param isDebugLogEnabled
 
  67         public void preProcessRequest (DelegateExecution execution, isDebugEnabled) {
 
  72                 //  failIfNotFound (Optional)
 
  73                 //  serviceInstanceId (Optional)
 
  76                 //  vfModuleModelInfo (Optional)
 
  77                 //  lcpCloudRegionId (Optional)                 @TODO: this is actually required
 
  78                 //  tenantId (Optional)                                 @TODO: this is actually required
 
  79                 //  cloudConfiguration                                  @TODO: temporary solution? this contains lcpCloudregion and tenantId
 
  82                 //  workflowException                                   @TODO: actual variable name is WorkflowException
 
  86                 execution.setVariable('prefix', prefix)
 
  87                 execution.setVariable('wasDeleted', 'false')
 
  89                 def tenantId = execution.getVariable("tenantId")
 
  90                 def cloudSiteId = execution.getVariable("lcpCloudRegionId")
 
  92                 // if tenantId or lcpCloudregionId is not passed, get it from cloudRegionConfiguration variable
 
  93                 if(!tenantId || !cloudSiteId) {
 
  94                         def cloudConfiguration = execution.getVariable("cloudConfiguration")
 
  95                         logger.debug("Using cloudConfiguration variable to get tenantId and lcpCloudRegionId - " + cloudConfiguration)
 
  96                         tenantId = jsonUtil.getJsonValue(cloudConfiguration, "tenantId")
 
  97                         execution.setVariable("tenantId", tenantId)
 
  98                         cloudSiteId = jsonUtil.getJsonValue(cloudConfiguration, "lcpCloudRegionId")
 
  99                         execution.setVariable("lcpCloudRegionId", cloudSiteId)
 
 100                         cloudOwner = jsonUtil.getJsonValue(cloudConfiguration, "cloudOwner")
 
 101                         execution.setVariable("cloudOwner", cloudOwner)
 
 107          * Set out 'wasDeleted' variable to 'true'
 
 109          * @param isDebugLogEnabled
 
 111         public void postProcess(DelegateExecution execution, isDebugLogEnabled) {
 
 112                 execution.setVariable('wasDeleted', 'true')
 
 117          * Query and set cloud region to use for AAI calls
 
 118          * Output variables: prefix+'aicCloudRegion', prefix+'cloudRegion'
 
 120          * @param isDebugEnabled
 
 122         public void callRESTQueryAAICloudRegion(DelegateExecution execution, isDebugEnabled) {
 
 124                 String cloudRegion = execution.getVariable('lcpCloudRegionId')
 
 125                 AaiUtil aaiUtil = new AaiUtil(this)
 
 127                 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.CLOUD_REGION, Defaults.CLOUD_OWNER.toString(), cloudRegion)
 
 128                 def queryCloudRegionRequest = aaiUtil.createAaiUri(uri)
 
 130                 cloudRegion = aaiUtil.getAAICloudReqion(execution,  queryCloudRegionRequest, "PO", cloudRegion)
 
 132                 if ((cloudRegion != "ERROR")) {
 
 133                         if(execution.getVariable(prefix+"queryCloudRegionReturnCode") == "404") {
 
 134                                 execution.setVariable(prefix+"aicCloudRegion", "AAIAIC25")
 
 137                                 execution.setVariable(prefix+"aicCloudRegion", cloudRegion)
 
 141                         logger.debug("AAI Query Cloud Region Unsuccessful.")
 
 142                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "AAI Query Cloud Region Unsuccessful. Return Code: " + execution.getVariable(prefix+"queryCloudRegionReturnCode"))
 
 148          * Query AAI Volume Group
 
 149          * Output variables: prefix+'queryAAIVolGrpResponse'; prefix+'volumeGroupHeatStackId'
 
 151          * @param isDebugLogEnabled
 
 153         public void callRESTQueryAAIForVolumeGroup(DelegateExecution execution, isDebugLogEnabled) {
 
 155                 def tenantId = execution.getVariable('tenantId')
 
 156                 def volumeGroupId = execution.getVariable('volumeGroupId')
 
 157                 if(volumeGroupId == null) {
 
 158                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, 'volumeGroupId is not provided in the request')
 
 159                         throw new Exception('volume-group-id is not provided in the request')
 
 161                 String cloudRegion = execution.getVariable(prefix+'aicCloudRegion')
 
 164                         AAIResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP , Defaults.CLOUD_OWNER.toString(), cloudRegion,volumeGroupId)
 
 165                         Optional<VolumeGroup> volumeGroupOps = getAAIClient().get(VolumeGroup.class,resourceUri)
 
 166             if(volumeGroupOps.present) {
 
 167                 VolumeGroup volumeGroup = volumeGroupOps.get()
 
 168                 execution.setVariable(prefix + "queryAAIVolGrpResponse", volumeGroup)
 
 169                 def heatStackId = volumeGroup.getHeatStackId()==null ? '' : volumeGroup.getHeatStackId()
 
 170                 execution.setVariable(prefix+'volumeGroupHeatStackId', heatStackId)
 
 172                 logger.debug('Heat stack id from AAI response: ' + heatStackId)
 
 173                                 AAIResultWrapper wrapper = getAAIClient().get(resourceUri);
 
 174                                 Optional<Relationships> relationships = wrapper.getRelationships()
 
 175                                 String volumeGroupTenantId = null
 
 177                                 if(relationships.isPresent()){
 
 178                                         if(relationships.get().getRelatedAAIUris(AAIObjectType.VF_MODULE)){
 
 179                                                 logger.debug('Volume Group ' + volumeGroupId + ' currently in use')
 
 180                                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} currently in use - found vf-module relationship.")
 
 182                                         for(AAIResourceUri aaiResourceUri: relationships.get().getRelatedAAIUris(AAIObjectType.TENANT)){
 
 183                                                 volumeGroupTenantId = aaiResourceUri.getURIKeys().get("tenant-id")
 
 187                 logger.debug('Tenant ID from AAI response: ' + volumeGroupTenantId)
 
 189                 if (volumeGroupTenantId == null) {
 
 190                     logger.debug("Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
 
 191                     exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
 
 194                 if (volumeGroupTenantId != tenantId) {
 
 195                     def String errorMessage = 'TenantId ' + tenantId + ' in incoming request does not match Tenant Id ' + volumeGroupTenantId + ' retrieved from AAI for Volume Group Id ' + volumeGroupId
 
 196                     logger.debug("Error in DeleteVfModuleVolume: " + errorMessage)
 
 197                     exceptionUtil.buildAndThrowWorkflowException(execution, 5000, errorMessage)
 
 199                 logger.debug('Received Tenant Id ' + volumeGroupTenantId + ' from AAI for Volume Group with Volume Group Id ' + volumeGroupId )
 
 201                 execution.setVariable(prefix + "queryAAIVolGrpResponse", "Volume Group ${volumeGroupId} not found in AAI. Response code: 404")
 
 202                 logger.debug("Volume Group ${volumeGroupId} not found in AAI")
 
 203                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} not found in AAI. Response code: 404")
 
 205                 }catch (Exception ex) {
 
 206             execution.setVariable(prefix+"queryAAIVolGrpResponse", ex.getMessage())
 
 207             WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(ex.getMessage(), execution)
 
 208             throw new BpmnError("MSOWorkflowException")
 
 213          * Format VNF Adapter subflow request XML
 
 214          * Variables: prefix+'deleteVnfARequest'
 
 216          * @param isDebugLogEnabled
 
 218         public void prepareVnfAdapterDeleteRequest(DelegateExecution execution, isDebugLogEnabled) {
 
 219                 def cloudRegion = execution.getVariable(prefix+'aicCloudRegion')
 
 220                 def cloudOwner = execution.getVariable(prefix+'cloudOwner')
 
 221                 def tenantId = execution.getVariable('tenantId')                                                                                // input parameter (optional) - see preProcessRequest
 
 222                 def volumeGroupId = execution.getVariable('volumeGroupId')                                                              // input parameter (required)
 
 223                 def volumeGroupHeatStackId = execution.getVariable(prefix+'volumeGroupHeatStackId')             // from AAI query volume group
 
 224                 def requestId = execution.getVariable('msoRequestId')                                                                   // input parameter (required)
 
 225                 def serviceId = execution.getVariable('serviceInstanceId')                                                              // imput parameter (optional)
 
 227                 def messageId = UUID.randomUUID().toString()
 
 228                 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
 
 229                 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host",execution)
 
 230                 if ('true'.equals(useQualifiedHostName)) {
 
 231                                 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
 
 234                 String vnfAdapterRestRequest = """
 
 235                         <deleteVolumeGroupRequest>
 
 236                                 <cloudSiteId>${MsoUtils.xmlEscape(cloudRegion)}</cloudSiteId>
 
 237                                 <cloudOwner>${MsoUtils.xmlEscape(cloudOwner)}</cloudOwner>
 
 238                                 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
 
 239                                 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
 
 240                                 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
 
 241                                 <skipAAI>true</skipAAI>
 
 243                                 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
 
 244                                 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
 
 246                             <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
 
 247                             <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
 
 248                         </deleteVolumeGroupRequest>
 
 250                 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
 
 251                 execution.setVariable(prefix+'deleteVnfARequest', vnfAdapterRestRequest)
 
 252                 logger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
 
 257          * Delete volume group in AAI
 
 259          * @param isDebugEnabled
 
 261         public void callRESTDeleteAAIVolumeGroup(DelegateExecution execution, isDebugEnabled) {
 
 264                 VolumeGroup volumeGroupResponse = execution.getVariable(prefix+"queryAAIVolGrpResponse")
 
 265                 String volumeGroupId = volumeGroupResponse.getVolumeGroupId()
 
 266                 String cloudRegion = execution.getVariable(prefix+'aicCloudRegion')
 
 269             AAIResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP,Defaults.CLOUD_OWNER.toString(), cloudRegion, volumeGroupId)
 
 270             getAAIClient().delete(resourceUri)
 
 271             logger.debug("Volume group $volumeGroupId deleted.")
 
 272         }catch (NotFoundException ex) {
 
 273             exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume group $volumeGroupId not found for delete in AAI Response code: 404")
 
 274         }catch (Exception ex) {
 
 275             WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(ex.getMessage(), execution)
 
 276             throw new BpmnError("MSOWorkflowException")