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=========================================================
20 package org.openecomp.mso.bpmn.infrastructure.scripts;
22 import static org.apache.commons.lang3.StringUtils.*;
23 import groovy.xml.XmlUtil
26 import org.openecomp.mso.bpmn.core.json.JsonUtils
27 import org.openecomp.mso.bpmn.common.scripts.AbstractServiceTaskProcessor
28 import org.openecomp.mso.bpmn.common.scripts.ExceptionUtil
29 import org.openecomp.mso.bpmn.common.scripts.SDNCAdapterUtils
30 import org.openecomp.mso.bpmn.core.WorkflowException
31 import org.openecomp.mso.rest.APIResponse;
32 import org.openecomp.mso.rest.RESTClient
33 import org.openecomp.mso.rest.RESTConfig
35 import java.util.UUID;
36 import javax.xml.parsers.DocumentBuilder
37 import javax.xml.parsers.DocumentBuilderFactory
39 import org.camunda.bpm.engine.delegate.BpmnError
40 import org.camunda.bpm.engine.delegate.DelegateExecution
41 import org.json.JSONObject;
42 import org.apache.commons.lang3.*
43 import org.apache.commons.codec.binary.Base64;
44 import org.springframework.web.util.UriUtils;
45 import org.w3c.dom.Document
46 import org.w3c.dom.Element
47 import org.w3c.dom.Node
48 import org.w3c.dom.NodeList
49 import org.xml.sax.InputSource
52 * This groovy class supports the <class>DoDeleteServiceInstance.bpmn</class> process.
55 * @param - msoRequestId
56 * @param - globalSubscriberId - O
57 * @param - subscriptionServiceType - O
58 * @param - serviceInstanceId
59 * @param - serviceInstanceName - O
60 * @param - serviceModelInfo - O
61 * @param - productFamilyId
62 * @param - serviceInputParams (should contain aic_zone for serviceTypes TRANSPORT,ATM)
63 * @param - sdncVersion
64 * @param - failNotFound - TODO
65 * @param - serviceInputParams - TODO
68 * @param - WorkflowException
72 public class DoDeleteServiceInstance extends AbstractServiceTaskProcessor {
74 String Prefix="DDELSI_"
75 ExceptionUtil exceptionUtil = new ExceptionUtil()
76 JsonUtils jsonUtil = new JsonUtils()
78 public void preProcessRequest (DelegateExecution execution) {
79 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
80 utils.log("DEBUG"," ***** preProcessRequest *****", isDebugEnabled)
84 String requestId = execution.getVariable("msoRequestId")
85 execution.setVariable("prefix",Prefix)
88 //requestDetails.subscriberInfo. for AAI GET & PUT & SDNC assignToplology
89 String globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId
90 if (globalSubscriberId == null)
92 execution.setVariable("globalSubscriberId", "")
95 //requestDetails.requestParameters. for AAI PUT & SDNC assignTopology
96 String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
97 if (subscriptionServiceType == null)
99 execution.setVariable("subscriptionServiceType", "")
102 //Generated in parent for AAI PUT
103 String serviceInstanceId = execution.getVariable("serviceInstanceId")
104 if (isBlank(serviceInstanceId)){
105 msg = "Input serviceInstanceId is null"
106 utils.log("DEBUG", msg, isDebugEnabled)
107 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
110 String sdncCallbackUrl = execution.getVariable('URN_mso_workflow_sdncadapter_callback')
111 if (isBlank(sdncCallbackUrl)) {
112 msg = "URN_mso_workflow_sdncadapter_callback is null"
113 utils.log("DEBUG", msg, isDebugEnabled)
114 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
116 execution.setVariable("sdncCallbackUrl", sdncCallbackUrl)
117 utils.log("DEBUG","SDNC Callback URL: " + sdncCallbackUrl, isDebugEnabled)
119 StringBuilder sbParams = new StringBuilder()
120 Map<String, String> paramsMap = execution.getVariable("serviceInputParams")
121 if (paramsMap != null)
123 sbParams.append("<service-input-parameters>")
124 for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
126 String paramName = entry.getKey()
127 String paramValue = entry.getValue()
130 <name>${paramName}</name>
131 <value>${paramValue}</value>
134 sbParams.append(paramsXml)
136 sbParams.append("</service-input-parameters>")
138 String siParamsXml = sbParams.toString()
139 if (siParamsXml == null)
141 execution.setVariable("siParamsXml", siParamsXml)
143 } catch (BpmnError e) {
145 } catch (Exception ex){
146 msg = "Exception in preProcessRequest " + ex.getMessage()
147 utils.log("DEBUG", msg, isDebugEnabled)
148 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
150 utils.log("DEBUG"," ***** Exit preProcessRequest *****", isDebugEnabled)
153 public void preProcessSDNCDelete (DelegateExecution execution) {
154 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
155 utils.log("DEBUG"," ***** preProcessSDNCDelete *****", isDebugEnabled)
159 def serviceInstanceId = execution.getVariable("serviceInstanceId") ?: ""
160 def serviceInstanceName = execution.getVariable("serviceInstanceName") ?: ""
161 def callbackURL = execution.getVariable("sdncCallbackUrl") ?: ""
162 def requestId = execution.getVariable("msoRequestId") ?: ""
163 def serviceId = execution.getVariable("productFamilyId") ?: ""
164 def subscriptionServiceType = execution.getVariable("subscriptionServiceType") ?: ""
165 def globalSubscriberId = execution.getVariable("globalSubscriberId") ?: "" //globalCustomerId
167 String serviceModelInfo = execution.getVariable("serviceModelInfo") ?: ""
168 def modelInvariantUuid = ""
169 def modelVersion = ""
172 if (!isBlank(serviceModelInfo))
174 modelInvariantUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelInvariantUuid") ?: ""
175 modelVersion = jsonUtil.getJsonValue(serviceModelInfo, "modelVersion") ?: ""
176 modelUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelUuid") ?: ""
177 modelName = jsonUtil.getJsonValue(serviceModelInfo, "modelName") ?: ""
181 def siParamsXml = execution.getVariable("siParamsXml") ?: ""
183 // special URL for SDNW, msoAction helps set diff url in SDNCA
184 if("TRANSPORT".equalsIgnoreCase(execution.getVariable("serviceType")))
186 msoAction = "TRANSPORT"
189 def sdncRequestId = UUID.randomUUID().toString()
192 """<sdncadapterworkflow:SDNCAdapterWorkflowRequest xmlns:ns5="http://org.openecomp/mso/request/types/v1"
193 xmlns:sdncadapterworkflow="http://org.openecomp/mso/workflow/schema/v1"
194 xmlns:sdncadapter="http://org.openecomp/workflow/sdnc/adapter/schema/v1">
195 <sdncadapter:RequestHeader>
196 <sdncadapter:RequestId>${sdncRequestId}</sdncadapter:RequestId>
197 <sdncadapter:SvcInstanceId>${serviceInstanceId}</sdncadapter:SvcInstanceId>
198 <sdncadapter:SvcAction>delete</sdncadapter:SvcAction>
199 <sdncadapter:SvcOperation>service-topology-operation</sdncadapter:SvcOperation>
200 <sdncadapter:CallbackUrl>${callbackURL}</sdncadapter:CallbackUrl>
201 <sdncadapter:MsoAction>${msoAction}</sdncadapter:MsoAction>
202 </sdncadapter:RequestHeader>
203 <sdncadapterworkflow:SDNCRequestData>
204 <request-information>
205 <request-id>${requestId}</request-id>
210 <request-action>DeleteServiceInstance</request-action>
211 </request-information>
212 <service-information>
213 <service-id>${serviceId}</service-id>
214 <subscription-service-type>${subscriptionServiceType}</subscription-service-type>
215 <ecomp-model-information>
216 <model-invariant-uuid>${modelInvariantUuid}</model-invariant-uuid>
217 <model-uuid>${modelUuid}</model-uuid>
218 <model-version>${modelVersion}</model-version>
219 <model-name>${modelName}</model-name>
220 </ecomp-model-information>
221 <service-instance-id>${serviceInstanceId}</service-instance-id>
223 <global-customer-id>${globalSubscriberId}</global-customer-id>
224 </service-information>
225 <service-request-input>
226 <service-instance-name>${serviceInstanceName}</service-instance-name>
228 </service-request-input>
229 </sdncadapterworkflow:SDNCRequestData>
230 </sdncadapterworkflow:SDNCAdapterWorkflowRequest>"""
232 sdncDelete = utils.formatXml(sdncDelete)
233 def sdncRequestId2 = UUID.randomUUID().toString()
234 String sdncDeactivate = sdncDelete.replace(">delete<", ">deactivate<").replace(">${sdncRequestId}<", ">${sdncRequestId2}<")
235 execution.setVariable("sdncDelete", sdncDelete)
236 execution.setVariable("sdncDeactivate", sdncDeactivate)
237 utils.log("DEBUG","sdncDeactivate:\n" + sdncDeactivate, isDebugEnabled)
238 utils.log("DEBUG","sdncDelete:\n" + sdncDelete, isDebugEnabled)
240 } catch (BpmnError e) {
242 } catch(Exception ex) {
243 msg = "Exception in preProcessSDNCDelete. " + ex.getMessage()
244 utils.log("DEBUG", msg, isDebugEnabled)
245 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Exception Occured in preProcessSDNCDelete.\n" + ex.getMessage())
247 utils.log("DEBUG"," *****Exit preProcessSDNCDelete *****", isDebugEnabled)
250 public void postProcessSDNCDelete(DelegateExecution execution, String response, String method) {
252 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
253 utils.log("DEBUG"," ***** postProcessSDNC " + method + " *****", isDebugEnabled)
257 WorkflowException workflowException = execution.getVariable("WorkflowException")
258 boolean successIndicator = execution.getVariable("SDNCA_SuccessIndicator")
259 utils.log("DEBUG", "SDNCResponse: " + response, isDebugEnabled)
260 utils.log("DEBUG", "workflowException: " + workflowException, isDebugEnabled)
262 SDNCAdapterUtils sdncAdapterUtils = new SDNCAdapterUtils(this)
263 sdncAdapterUtils.validateSDNCResponse(execution, response, workflowException, successIndicator)
265 if(execution.getVariable(Prefix + 'sdncResponseSuccess') == true){
266 utils.log("DEBUG","Good response from SDNC Adapter for service-instance " + method + "response:\n" + response, isDebugEnabled)
269 msg = "Bad Response from SDNC Adapter for service-instance " + method
270 utils.log("DEBUG", msg, isDebugEnabled)
271 exceptionUtil.buildAndThrowWorkflowException(execution, 3500, msg)
273 } catch (BpmnError e) {
275 } catch(Exception ex) {
276 msg = "Exception in postProcessSDNC " + method + " Exception:" + ex.getMessage()
277 utils.log("DEBUG", msg, isDebugEnabled)
278 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
280 utils.log("DEBUG"," *** Exit postProcessSDNC " + method + " ***", isDebugEnabled)
283 public void postProcessAAIGET(DelegateExecution execution) {
284 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
285 utils.log("DEBUG"," ***** postProcessAAIGET ***** ", isDebugEnabled)
290 String serviceInstanceId = execution.getVariable("serviceInstanceId")
291 boolean foundInAAI = execution.getVariable("GENGS_FoundIndicator")
292 String serviceType = ""
295 utils.log("DEBUG","Found Service-instance in AAI", isDebugEnabled)
297 //Extract GlobalSubscriberId
298 String siRelatedLink = execution.getVariable("GENGS_siResourceLink")
299 if (isBlank(siRelatedLink))
301 msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
302 utils.log("DEBUG", msg, isDebugEnabled)
303 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
307 utils.log("DEBUG","Found Service-instance in AAI. link: " + siRelatedLink, isDebugEnabled)
308 String globalSubscriberId = execution.getVariable("globalSubscriberId")
309 if(isBlank(globalSubscriberId)){
310 int custStart = siRelatedLink.indexOf("customer/")
311 int custEnd = siRelatedLink.indexOf("/service-subscriptions")
312 globalSubscriberId = siRelatedLink.substring(custStart + 9, custEnd)
313 execution.setVariable("globalSubscriberId", globalSubscriberId)
316 //Extract Service Type if not provided on request
317 String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
318 if(isBlank(subscriptionServiceType)){
319 int serviceStart = siRelatedLink.indexOf("service-subscription/")
320 int serviceEnd = siRelatedLink.indexOf("/service-instances/")
321 String serviceTypeEncoded = siRelatedLink.substring(serviceStart + 21, serviceEnd)
322 subscriptionServiceType = UriUtils.decode(serviceTypeEncoded, "UTF-8")
323 execution.setVariable("subscriptionServiceType", subscriptionServiceType)
326 if (isBlank(globalSubscriberId) || isBlank(subscriptionServiceType))
328 msg = "Could not retrive global-customer-id & subscription-service-type from AAI to delete id:" + serviceInstanceId
329 utils.log("DEBUG", msg, isDebugEnabled)
330 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
334 String siData = execution.getVariable("GENGS_service")
335 utils.log("DEBUG", "SI Data", isDebugEnabled)
338 msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
339 utils.log("DEBUG", msg, isDebugEnabled)
340 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
344 utils.log("DEBUG", "SI Data" + siData, isDebugEnabled)
345 serviceType = utils.getNodeText1(siData,"service-type")
346 execution.setVariable("serviceType", serviceType)
347 execution.setVariable("serviceRole", utils.getNodeText1(siData,"service-role"))
348 String orchestrationStatus = utils.getNodeText1(siData,"orchestration-status")
350 //Confirm there are no related service instances (vnf/network or volume)
351 if (utils.nodeExists(siData, "relationship-list")) {
352 utils.log("DEBUG", "SI Data relationship-list exists:", isDebugEnabled)
353 InputSource source = new InputSource(new StringReader(siData));
354 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
355 DocumentBuilder docBuilder = docFactory.newDocumentBuilder()
356 Document serviceXml = docBuilder.parse(source)
358 NodeList nodeList = serviceXml.getElementsByTagName("relationship")
359 for (int x = 0; x < nodeList.getLength(); x++) {
360 Node node = nodeList.item(x)
361 if (node.getNodeType() == Node.ELEMENT_NODE) {
362 Element eElement = (Element) node
363 def e = eElement.getElementsByTagName("related-to").item(0).getTextContent()
364 if(e.equals("generic-vnf") || e.equals("l3-network") || e.equals("allotted-resource") ){
365 utils.log("DEBUG", "ServiceInstance still has relationship(s) to generic-vnfs, l3-networks or allotted-resources", isDebugEnabled)
366 execution.setVariable("siInUse", true)
367 //there are relationship dependencies to this Service Instance
368 msg = " Stopped deleting Service Instance, it has dependencies. Service instance id: " + serviceInstanceId
369 utils.log("DEBUG", msg, isDebugEnabled)
370 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
372 utils.log("DEBUG", "Relationship NOT related to OpenStack", isDebugEnabled)
378 if ("TRANSPORT".equalsIgnoreCase(serviceType))
380 if ("PendingDelete".equals(orchestrationStatus))
382 execution.setVariable("skipDeactivate", true)
386 msg = "ServiceInstance of type TRANSPORT must in PendingDelete status to allow Delete. Orchestration-status:" + orchestrationStatus
387 utils.log("DEBUG", msg, isDebugEnabled)
388 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
393 //alacarte SIs are NOT sent to sdnc. exceptions are listed in config variable
394 String svcTypes = execution.getVariable("URN_sdnc_si_svc_types") ?: ""
395 utils.log("DEBUG", "SDNC SI serviceTypes:" + svcTypes, isDebugEnabled)
396 List<String> svcList = Arrays.asList(svcTypes.split("\\s*,\\s*"));
397 boolean isSdncService= false
398 for (String listEntry : svcList){
399 if (listEntry.equalsIgnoreCase(serviceType)){
405 //All Macros are sent to SDNC, TRANSPORT(Macro) is sent to SDNW
406 //Alacartes are sent to SDNC if they are listed in config variable above
407 execution.setVariable("sendToSDNC", true)
408 if(execution.getVariable("sdncVersion").equals("1610")) //alacarte
411 execution.setVariable("sendToSDNC", false)
415 utils.log("DEBUG", "isSdncService: " + isSdncService, isDebugEnabled)
416 utils.log("DEBUG", "Send To SDNC: " + execution.getVariable("sendToSDNC"), isDebugEnabled)
417 utils.log("DEBUG", "Service Type: " + execution.getVariable("serviceType"), isDebugEnabled)
421 boolean succInAAI = execution.getVariable("GENGS_SuccessIndicator")
423 utils.log("DEBUG","Error getting Service-instance from AAI", + serviceInstanceId, isDebugEnabled)
424 WorkflowException workflowException = execution.getVariable("WorkflowException")
425 utils.logAudit("workflowException: " + workflowException)
426 if(workflowException != null){
427 exceptionUtil.buildAndThrowWorkflowException(execution, workflowException.getErrorCode(), workflowException.getErrorMessage())
431 msg = "Failure in postProcessAAIGET GENGS_SuccessIndicator:" + succInAAI
432 utils.log("DEBUG", msg, isDebugEnabled)
433 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
437 utils.log("DEBUG","Service-instance NOT found in AAI. Silent Success", isDebugEnabled)
439 } catch (BpmnError e) {
441 } catch (Exception ex) {
442 msg = "Exception in DoDeleteServiceInstance.postProcessAAIGET. " + ex.getMessage()
443 utils.log("DEBUG", msg, isDebugEnabled)
444 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
446 utils.log("DEBUG"," *** Exit postProcessAAIGET *** ", isDebugEnabled)
449 public void postProcessAAIDEL(DelegateExecution execution) {
450 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
451 utils.log("DEBUG"," ***** postProcessAAIDEL ***** ", isDebugEnabled)
454 String serviceInstanceId = execution.getVariable("serviceInstanceId")
455 boolean succInAAI = execution.getVariable("GENDS_SuccessIndicator")
457 msg = "Error deleting Service-instance in AAI" + serviceInstanceId
458 utils.log("DEBUG", msg, isDebugEnabled)
459 WorkflowException workflowException = execution.getVariable("WorkflowException")
460 utils.logAudit("workflowException: " + workflowException)
461 if(workflowException != null){
462 exceptionUtil.buildAndThrowWorkflowException(execution, workflowException.getErrorCode(), workflowException.getErrorMessage())
466 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
469 } catch (BpmnError e) {
471 } catch (Exception ex) {
472 msg = "Exception in DoDeleteServiceInstance.postProcessAAIDEL. " + ex.getMessage()
473 utils.log("DEBUG", msg, isDebugEnabled)
474 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
476 utils.log("DEBUG"," *** Exit postProcessAAIDEL *** ", isDebugEnabled)