/*- * ============LICENSE_START======================================================= * ONAP - SO * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * Copyright (C) 2017 Huawei Technologies Co., Ltd. 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.openecomp.mso.bpmn.infrastructure.scripts; import static org.apache.commons.lang3.StringUtils.*; import groovy.xml.XmlUtil import groovy.json.* import org.openecomp.mso.bpmn.core.json.JsonUtils import org.openecomp.mso.bpmn.common.scripts.AbstractServiceTaskProcessor import org.openecomp.mso.bpmn.common.scripts.ExceptionUtil import org.openecomp.mso.bpmn.common.scripts.SDNCAdapterUtils import org.openecomp.mso.bpmn.core.WorkflowException import org.openecomp.mso.rest.APIResponse; import org.openecomp.mso.rest.RESTClient import org.openecomp.mso.rest.RESTConfig import java.util.UUID; import javax.xml.parsers.DocumentBuilder import javax.xml.parsers.DocumentBuilderFactory import org.camunda.bpm.engine.delegate.BpmnError import org.camunda.bpm.engine.runtime.Execution import org.json.JSONObject; import org.apache.commons.lang3.* import org.apache.commons.codec.binary.Base64; import org.springframework.web.util.UriUtils; import org.w3c.dom.Document import org.w3c.dom.Element import org.w3c.dom.Node import org.w3c.dom.NodeList import org.xml.sax.InputSource /** * This groovy class supports the DoDeleteE2EServiceInstance.bpmn process. * * Inputs: * @param - msoRequestId * @param - globalSubscriberId - O * @param - subscriptionServiceType - O * @param - serviceInstanceId * @param - serviceInstanceName - O * @param - serviceModelInfo - O * @param - productFamilyId * @param - serviceInputParams (should contain aic_zone for serviceTypes TRANSPORT,ATM) * @param - sdncVersion * @param - failNotFound - TODO * @param - serviceInputParams - TODO * * Outputs: * @param - WorkflowException * * Rollback - Deferred */ public class DoDeleteE2EServiceInstance extends AbstractServiceTaskProcessor { String Prefix="DDELSI_" ExceptionUtil exceptionUtil = new ExceptionUtil() JsonUtils jsonUtil = new JsonUtils() public void preProcessRequest (Execution execution) { def isDebugEnabled = execution.getVariable("isDebugLogEnabled") utils.log("DEBUG"," ***** preProcessRequest *****", isDebugEnabled) String msg = "" try { String requestId = execution.getVariable("msoRequestId") execution.setVariable("prefix",Prefix) //Inputs //requestDetails.subscriberInfo. for AAI GET & PUT & SDNC assignToplology String globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId if (globalSubscriberId == null) { execution.setVariable("globalSubscriberId", "") } //requestDetails.requestParameters. for AAI PUT & SDNC assignTopology String subscriptionServiceType = execution.getVariable("subscriptionServiceType") if (subscriptionServiceType == null) { execution.setVariable("subscriptionServiceType", "") } //Generated in parent for AAI PUT String serviceInstanceId = execution.getVariable("serviceInstanceId") if (isBlank(serviceInstanceId)){ msg = "Input serviceInstanceId is null" utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg) } String sdncCallbackUrl = execution.getVariable('URN_mso_workflow_sdncadapter_callback') if (isBlank(sdncCallbackUrl)) { msg = "URN_mso_workflow_sdncadapter_callback is null" utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg) } execution.setVariable("sdncCallbackUrl", sdncCallbackUrl) utils.log("DEBUG","SDNC Callback URL: " + sdncCallbackUrl, isDebugEnabled) StringBuilder sbParams = new StringBuilder() Map paramsMap = execution.getVariable("serviceInputParams") if (paramsMap != null) { sbParams.append("") for (Map.Entry entry : paramsMap.entrySet()) { String paramsXml String paramName = entry.getKey() String paramValue = entry.getValue() paramsXml = """ ${paramName} ${paramValue} """ sbParams.append(paramsXml) } sbParams.append("") } String siParamsXml = sbParams.toString() if (siParamsXml == null) siParamsXml = "" execution.setVariable("siParamsXml", siParamsXml) } catch (BpmnError e) { throw e; } catch (Exception ex){ msg = "Exception in preProcessRequest " + ex.getMessage() utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg) } utils.log("DEBUG"," ***** Exit preProcessRequest *****", isDebugEnabled) } public void preProcessVFCDelete (Execution execution) { } public void postProcessVFCDelete(Execution execution, String response, String method) { } public void preProcessSDNCDelete (Execution execution) { def isDebugEnabled = execution.getVariable("isDebugLogEnabled") utils.log("DEBUG"," ***** preProcessSDNCDelete *****", isDebugEnabled) String msg = "" try { def serviceInstanceId = execution.getVariable("serviceInstanceId") def serviceInstanceName = execution.getVariable("serviceInstanceName") def callbackURL = execution.getVariable("sdncCallbackUrl") def requestId = execution.getVariable("msoRequestId") def serviceId = execution.getVariable("productFamilyId") def subscriptionServiceType = execution.getVariable("subscriptionServiceType") def globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId String serviceModelInfo = execution.getVariable("serviceModelInfo") def modelInvariantUuid = "" def modelVersion = "" def modelUuid = "" def modelName = "" if (!isBlank(serviceModelInfo)) { modelInvariantUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelInvariantUuid") modelVersion = jsonUtil.getJsonValue(serviceModelInfo, "modelVersion") modelUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelUuid") modelName = jsonUtil.getJsonValue(serviceModelInfo, "modelName") if (modelInvariantUuid == null) { modelInvariantUuid = "" } if (modelVersion == null) { modelVersion = "" } if (modelUuid == null) { modelUuid = "" } if (modelName == null) { modelName = "" } } if (serviceInstanceName == null) { serviceInstanceName = "" } if (serviceId == null) { serviceId = "" } def siParamsXml = execution.getVariable("siParamsXml") def serviceType = execution.getVariable("serviceType") if (serviceType == null) { serviceType = "" } def sdncRequestId = UUID.randomUUID().toString() String sdncDelete = """ ${sdncRequestId} ${serviceInstanceId} delete service-topology-operation ${callbackURL} ${serviceType} ${requestId} MSO DeleteServiceInstance ${serviceId} ${subscriptionServiceType} ${modelInvariantUuid} ${modelUuid} ${modelVersion} ${modelName} ${serviceInstanceId} ${globalSubscriberId} ${serviceInstanceName} ${siParamsXml} """ sdncDelete = utils.formatXml(sdncDelete) def sdncRequestId2 = UUID.randomUUID().toString() String sdncDeactivate = sdncDelete.replace(">delete<", ">deactivate<").replace(">${sdncRequestId}<", ">${sdncRequestId2}<") execution.setVariable("sdncDelete", sdncDelete) execution.setVariable("sdncDeactivate", sdncDeactivate) utils.log("DEBUG","sdncDeactivate:\n" + sdncDeactivate, isDebugEnabled) utils.log("DEBUG","sdncDelete:\n" + sdncDelete, isDebugEnabled) } catch (BpmnError e) { throw e; } catch(Exception ex) { msg = "Exception in preProcessSDNCDelete. " + ex.getMessage() utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Exception Occured in preProcessSDNCDelete.\n" + ex.getMessage()) } utils.log("DEBUG"," *****Exit preProcessSDNCDelete *****", isDebugEnabled) } public void postProcessSDNCDelete(Execution execution, String response, String method) { def isDebugEnabled=execution.getVariable("isDebugLogEnabled") utils.log("DEBUG"," ***** postProcessSDNC " + method + " *****", isDebugEnabled) String msg = "" try { WorkflowException workflowException = execution.getVariable("WorkflowException") boolean successIndicator = execution.getVariable("SDNCA_SuccessIndicator") utils.log("DEBUG", "SDNCResponse: " + response, isDebugEnabled) utils.log("DEBUG", "workflowException: " + workflowException, isDebugEnabled) SDNCAdapterUtils sdncAdapterUtils = new SDNCAdapterUtils(this) sdncAdapterUtils.validateSDNCResponse(execution, response, workflowException, successIndicator) if(execution.getVariable(Prefix + 'sdncResponseSuccess') == true){ utils.log("DEBUG","Good response from SDNC Adapter for service-instance " + method + "response:\n" + response, isDebugEnabled) }else{ msg = "Bad Response from SDNC Adapter for service-instance " + method utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 3500, msg) } } catch (BpmnError e) { throw e; } catch(Exception ex) { msg = "Exception in postProcessSDNC " + method + " Exception:" + ex.getMessage() utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg) } utils.log("DEBUG"," *** Exit postProcessSDNC " + method + " ***", isDebugEnabled) } public void postProcessAAIGET(Execution execution) { def isDebugEnabled=execution.getVariable("isDebugLogEnabled") utils.log("DEBUG"," ***** postProcessAAIGET ***** ", isDebugEnabled) String msg = "" try { String serviceInstanceId = execution.getVariable("serviceInstanceId") boolean foundInAAI = execution.getVariable("GENGS_FoundIndicator") String serviceType = "" if(foundInAAI == true){ utils.log("DEBUG","Found Service-instance in AAI", isDebugEnabled) //Extract GlobalSubscriberId String siRelatedLink = execution.getVariable("GENGS_siResourceLink") if (isBlank(siRelatedLink)) { msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg) } else { utils.log("DEBUG","Found Service-instance in AAI. link: " + siRelatedLink, isDebugEnabled) String globalSubscriberId = execution.getVariable("globalSubscriberId") if(isBlank(globalSubscriberId)){ int custStart = siRelatedLink.indexOf("customer/") int custEnd = siRelatedLink.indexOf("/service-subscriptions") globalSubscriberId = siRelatedLink.substring(custStart + 9, custEnd) execution.setVariable("globalSubscriberId", globalSubscriberId) } //Extract Service Type if not provided on request String subscriptionServiceType = execution.getVariable("subscriptionServiceType") if(isBlank(subscriptionServiceType)){ int serviceStart = siRelatedLink.indexOf("service-subscription/") int serviceEnd = siRelatedLink.indexOf("/service-instances/") String serviceTypeEncoded = siRelatedLink.substring(serviceStart + 21, serviceEnd) subscriptionServiceType = UriUtils.decode(serviceTypeEncoded, "UTF-8") execution.setVariable("subscriptionServiceType", subscriptionServiceType) } if (isBlank(globalSubscriberId) || isBlank(subscriptionServiceType)) { msg = "Could not retrive global-customer-id & subscription-service-type from AAI to delete id:" + serviceInstanceId utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg) } } String siData = execution.getVariable("GENGS_service") utils.log("DEBUG", "SI Data", isDebugEnabled) if (isBlank(siData)) { msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg) } else { utils.log("DEBUG", "SI Data" + siData, isDebugEnabled) serviceType = utils.getNodeText1(siData,"service-type") execution.setVariable("serviceType", serviceType) execution.setVariable("serviceRole", utils.getNodeText1(siData,"service-role")) String orchestrationStatus = utils.getNodeText1(siData,"orchestration-status") //Confirm there are no related service instances (vnf/network or volume) if (utils.nodeExists(siData, "relationship-list")) { utils.log("DEBUG", "SI Data relationship-list exists:", isDebugEnabled) InputSource source = new InputSource(new StringReader(siData)); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder() Document serviceXml = docBuilder.parse(source) NodeList nodeList = serviceXml.getElementsByTagName("relationship") for (int x = 0; x < nodeList.getLength(); x++) { Node node = nodeList.item(x) if (node.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) node def e = eElement.getElementsByTagName("related-to").item(0).getTextContent() if(e.equals("generic-vnf") || e.equals("l3-network") || e.equals("allotted-resource") ){ utils.log("DEBUG", "ServiceInstance still has relationship(s) to generic-vnfs, l3-networks or allotted-resources", isDebugEnabled) execution.setVariable("siInUse", true) //there are relationship dependencies to this Service Instance msg = " Stopped deleting Service Instance, it has dependencies. Service instance id: " + serviceInstanceId utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg) }else{ utils.log("DEBUG", "Relationship NOT related to OpenStack", isDebugEnabled) } } } } if ("TRANSPORT".equalsIgnoreCase(serviceType)) { if ("PendingDelete".equals(orchestrationStatus)) { execution.setVariable("skipDeactivate", true) } else { msg = "ServiceInstance of type TRANSPORT must in PendingDelete status to allow Delete. Orchestration-status:" + orchestrationStatus utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg) } } } }else{ boolean succInAAI = execution.getVariable("GENGS_SuccessIndicator") if(succInAAI != true){ utils.log("DEBUG","Error getting Service-instance from AAI", + serviceInstanceId, isDebugEnabled) WorkflowException workflowException = execution.getVariable("WorkflowException") utils.logAudit("workflowException: " + workflowException) if(workflowException != null){ exceptionUtil.buildAndThrowWorkflowException(execution, workflowException.getErrorCode(), workflowException.getErrorMessage()) } else { msg = "Failure in postProcessAAIGET GENGS_SuccessIndicator:" + succInAAI utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg) } } utils.log("DEBUG","Service-instance NOT found in AAI. Silent Success", isDebugEnabled) } } catch (BpmnError e) { throw e; } catch (Exception ex) { msg = "Exception in DoDeleteE2EServiceInstance.postProcessAAIGET. " + ex.getMessage() utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg) } utils.log("DEBUG"," *** Exit postProcessAAIGET *** ", isDebugEnabled) } public void postProcessAAIDEL(Execution execution) { def isDebugEnabled=execution.getVariable("isDebugLogEnabled") utils.log("DEBUG"," ***** postProcessAAIDEL ***** ", isDebugEnabled) String msg = "" try { String serviceInstanceId = execution.getVariable("serviceInstanceId") boolean succInAAI = execution.getVariable("GENDS_SuccessIndicator") if(succInAAI != true){ msg = "Error deleting Service-instance in AAI" + serviceInstanceId utils.log("DEBUG", msg, isDebugEnabled) WorkflowException workflowException = execution.getVariable("WorkflowException") utils.logAudit("workflowException: " + workflowException) if(workflowException != null){ exceptionUtil.buildAndThrowWorkflowException(execution, workflowException.getErrorCode(), workflowException.getErrorMessage()) } else { exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg) } } } catch (BpmnError e) { throw e; } catch (Exception ex) { msg = "Exception in DoDeleteE2EServiceInstance.postProcessAAIDEL. " + ex.getMessage() utils.log("DEBUG", msg, isDebugEnabled) exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg) } utils.log("DEBUG"," *** Exit postProcessAAIDEL *** ", isDebugEnabled) } public void preInitResourcesOperStatus(Execution execution){ def isDebugEnabled = execution.getVariable("isDebugLogEnabled") utils.log("DEBUG", " ======== STARTED preInitResourcesOperStatus Process ======== ", isDebugEnabled) try{ String serviceId = execution.getVariable("serviceInstanceId") String operationId = execution.getVariable("operationId") String operationType = execution.getVariable("operationType") String resourceTemplateUUIDs = "" String result = "processing" String progress = "0" String reason = "" String operationContent = "Prepare service creation" utils.log("DEBUG", "Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId + " operationType:" + oprationType, isDebugEnabled) serviceId = UriUtils.encode(serviceId,"UTF-8") execution.setVariable("serviceInstanceId", serviceId) execution.setVariable("operationId", operationId) execution.setVariable("operationType", operationType) // we use resource instance ids for delete flow as resourceTemplateUUIDs /*[ { "resourceInstanceId":"1111", "resourceType":"vIMS" }, { "resourceInstanceId":"222", "resourceType":"vEPC" }, { "resourceInstanceId":"3333", "resourceType":"overlay" }, { "resourceInstanceId":"4444", "resourceType":"underlay" } ]*/ String serviceRelationShip = execution.getVariable("serviceRelationShip") def jsonSlurper = new JsonSlurper() def jsonOutput = new JsonOutput() List relationShipList = jsonSlurper.parseText(serviceRelationShip) if (relationShipList != null) { relationShipList.each { resourceTemplateUUIDs = resourceTemplateUUIDs + it.resourceInstanceId + ":" } } def dbAdapterEndpoint = execution.getVariable("URN_mso_adapters_openecomp_db_endpoint") execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint) utils.log("DEBUG", "DB Adapter Endpoint is: " + dbAdapterEndpoint, isDebugEnabled) String payload = """ ${serviceId} ${operationId} ${operationType} ${resourceTemplateUUIDs} """ payload = utils.formatXml(payload) execution.setVariable("CVFMI_initResOperStatusRequest", payload) utils.log("DEBUG", "Outgoing initResourceOperationStatus: \n" + payload, isDebugEnabled) utils.logAudit("CreateVfModuleInfra Outgoing initResourceOperationStatus Request: " + payload) }catch(Exception e){ utils.log("ERROR", "Exception Occured Processing preInitResourcesOperStatus. Exception is:\n" + e, isDebugEnabled) execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during preInitResourcesOperStatus Method:\n" + e.getMessage()) } utils.log("DEBUG", "======== COMPLETED preInitResourcesOperStatus Process ======== ", isDebugEnabled) } /** * prepare delete parameters */ public void preResourceDelete(execution, resourceName){ // we use resource instance ids for delete flow as resourceTemplateUUIDs /*[ { "resourceInstanceId":"1111", "resourceType":"vIMS" }, { "resourceInstanceId":"222", "resourceType":"vEPC" }, { "resourceInstanceId":"3333", "resourceType":"overlay" }, { "resourceInstanceId":"4444", "resourceType":"underlay" } ]*/ String serviceRelationShip = execution.getVariable("serviceRelationShip") def jsonSlurper = new JsonSlurper() def jsonOutput = new JsonOutput() List relationShipList = jsonSlurper.parseText(serviceRelationShip) if (relationShipList != null) { relationShipList.each { if(resouceName.equals(it.resouceType)) String resouceTemplateUUID = it.resourceInstanceId String resouceInstanceUUID = it.resouceInstanceId execution.setVariable("resouceTemplateUUID", resouceTemplateUUID) execution.setVariable("resouceInstanceId", resouceInstanceUUID) execution.setResourceType("resourceType", resouceName) } } } }