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.onap.so.bpmn.infrastructure.scripts
23 import static org.apache.commons.lang3.StringUtils.*;
25 import javax.xml.parsers.DocumentBuilder
26 import javax.xml.parsers.DocumentBuilderFactory
28 import org.apache.commons.lang3.*
29 import org.camunda.bpm.engine.delegate.BpmnError
30 import org.camunda.bpm.engine.delegate.DelegateExecution
31 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
32 import org.onap.so.bpmn.common.scripts.ExceptionUtil
33 import org.onap.so.bpmn.common.scripts.MsoUtils
34 import org.onap.so.bpmn.common.scripts.SDNCAdapterUtils
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.logger.MsoLogger
39 import org.onap.so.client.aai.entities.uri.AAIResourceUri
40 import org.onap.so.client.aai.entities.uri.AAIUriFactory
41 import org.onap.so.client.aai.AAIObjectType
42 import org.onap.so.client.aai.AAIResourcesClient
43 import org.springframework.web.util.UriUtils;
44 import org.w3c.dom.Document
45 import org.w3c.dom.Element
46 import org.w3c.dom.Node
47 import org.w3c.dom.NodeList
48 import org.xml.sax.InputSource
53 * This groovy class supports the <class>DoDeleteServiceInstance.bpmn</class> process.
56 * @param - msoRequestId
57 * @param - globalSubscriberId - O
58 * @param - subscriptionServiceType - O
59 * @param - serviceInstanceId
60 * @param - serviceInstanceName - O
61 * @param - serviceModelInfo - O
62 * @param - productFamilyId
63 * @param - serviceInputParams (should contain aic_zone for serviceTypes TRANSPORT,ATM)
64 * @param - sdncVersion
65 * @param - failNotFound - TODO
66 * @param - serviceInputParams - TODO
69 * @param - WorkflowException
73 public class DoDeleteServiceInstance extends AbstractServiceTaskProcessor {
74 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, DoDeleteServiceInstance.class);
76 String Prefix="DDELSI_"
77 ExceptionUtil exceptionUtil = new ExceptionUtil()
78 JsonUtils jsonUtil = new JsonUtils()
80 public void preProcessRequest (DelegateExecution execution) {
82 msoLogger.trace("preProcessRequest ")
86 String requestId = execution.getVariable("msoRequestId")
87 execution.setVariable("prefix",Prefix)
90 //requestDetails.subscriberInfo. for AAI GET & PUT & SDNC assignToplology
91 String globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId
92 if (globalSubscriberId == null)
94 execution.setVariable("globalSubscriberId", "")
97 //requestDetails.requestParameters. for AAI PUT & SDNC assignTopology
98 String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
99 if (subscriptionServiceType == null)
101 execution.setVariable("subscriptionServiceType", "")
104 //Generated in parent for AAI PUT
105 String serviceInstanceId = execution.getVariable("serviceInstanceId")
106 if (isBlank(serviceInstanceId)){
107 msg = "Input serviceInstanceId is null"
109 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
112 String sdncCallbackUrl = UrnPropertiesReader.getVariable('mso.workflow.sdncadapter.callback',execution)
113 if (isBlank(sdncCallbackUrl)) {
114 msg = "mso.workflow.sdncadapter.callback is null"
116 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
118 execution.setVariable("sdncCallbackUrl", sdncCallbackUrl)
119 msoLogger.debug("SDNC Callback URL: " + sdncCallbackUrl)
121 StringBuilder sbParams = new StringBuilder()
122 Map<String, String> paramsMap = execution.getVariable("serviceInputParams")
123 if (paramsMap != null)
125 sbParams.append("<service-input-parameters>")
126 for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
128 String paramName = entry.getKey()
129 String paramValue = entry.getValue()
132 <name>${MsoUtils.xmlEscape(paramName)}</name>
133 <value>${MsoUtils.xmlEscape(paramValue)}</value>
136 sbParams.append(paramsXml)
138 sbParams.append("</service-input-parameters>")
140 String siParamsXml = sbParams.toString()
141 if (siParamsXml == null)
143 execution.setVariable("siParamsXml", siParamsXml)
145 } catch (BpmnError e) {
147 } catch (Exception ex){
148 msg = "Exception in preProcessRequest " + ex.getMessage()
150 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
152 msoLogger.trace("Exit preProcessRequest ")
155 public void preProcessSDNCDelete (DelegateExecution execution) {
157 msoLogger.trace("preProcessSDNCDelete ")
161 def serviceInstanceId = execution.getVariable("serviceInstanceId") ?: ""
162 def serviceInstanceName = execution.getVariable("serviceInstanceName") ?: ""
163 def callbackURL = execution.getVariable("sdncCallbackUrl") ?: ""
164 def requestId = execution.getVariable("msoRequestId") ?: ""
165 def serviceId = execution.getVariable("productFamilyId") ?: ""
166 def subscriptionServiceType = execution.getVariable("subscriptionServiceType") ?: ""
167 def globalSubscriberId = execution.getVariable("globalSubscriberId") ?: "" //globalCustomerId
169 String serviceModelInfo = execution.getVariable("serviceModelInfo") ?: ""
170 def modelInvariantUuid = ""
171 def modelVersion = ""
174 if (!isBlank(serviceModelInfo))
176 modelInvariantUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelInvariantUuid") ?: ""
177 modelVersion = jsonUtil.getJsonValue(serviceModelInfo, "modelVersion") ?: ""
178 modelUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelUuid") ?: ""
179 modelName = jsonUtil.getJsonValue(serviceModelInfo, "modelName") ?: ""
183 def siParamsXml = execution.getVariable("siParamsXml") ?: ""
185 // special URL for SDNW, msoAction helps set diff url in SDNCA
186 if("TRANSPORT".equalsIgnoreCase(execution.getVariable("serviceType")))
188 msoAction = "TRANSPORT"
191 def sdncRequestId = UUID.randomUUID().toString()
194 """<sdncadapterworkflow:SDNCAdapterWorkflowRequest xmlns:ns5="http://org.onap/so/request/types/v1"
195 xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
196 xmlns:sdncadapter="http://org.onap/workflow/sdnc/adapter/schema/v1">
197 <sdncadapter:RequestHeader>
198 <sdncadapter:RequestId>${MsoUtils.xmlEscape(sdncRequestId)}</sdncadapter:RequestId>
199 <sdncadapter:SvcInstanceId>${MsoUtils.xmlEscape(serviceInstanceId)}</sdncadapter:SvcInstanceId>
200 <sdncadapter:SvcAction>delete</sdncadapter:SvcAction>
201 <sdncadapter:SvcOperation>service-topology-operation</sdncadapter:SvcOperation>
202 <sdncadapter:CallbackUrl>${MsoUtils.xmlEscape(callbackURL)}</sdncadapter:CallbackUrl>
203 <sdncadapter:MsoAction>${MsoUtils.xmlEscape(msoAction)}</sdncadapter:MsoAction>
204 </sdncadapter:RequestHeader>
205 <sdncadapterworkflow:SDNCRequestData>
206 <request-information>
207 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
212 <request-action>DeleteServiceInstance</request-action>
213 </request-information>
214 <service-information>
215 <service-id>${MsoUtils.xmlEscape(serviceId)}</service-id>
216 <subscription-service-type>${MsoUtils.xmlEscape(subscriptionServiceType)}</subscription-service-type>
217 <onap-model-information>
218 <model-invariant-uuid>${MsoUtils.xmlEscape(modelInvariantUuid)}</model-invariant-uuid>
219 <model-uuid>${MsoUtils.xmlEscape(modelUuid)}</model-uuid>
220 <model-version>${MsoUtils.xmlEscape(modelVersion)}</model-version>
221 <model-name>${MsoUtils.xmlEscape(modelName)}</model-name>
222 </onap-model-information>
223 <service-instance-id>${MsoUtils.xmlEscape(serviceInstanceId)}</service-instance-id>
225 <global-customer-id>${MsoUtils.xmlEscape(globalSubscriberId)}</global-customer-id>
226 </service-information>
227 <service-request-input>
228 <service-instance-name>${MsoUtils.xmlEscape(serviceInstanceName)}</service-instance-name>
230 </service-request-input>
231 </sdncadapterworkflow:SDNCRequestData>
232 </sdncadapterworkflow:SDNCAdapterWorkflowRequest>"""
234 sdncDelete = utils.formatXml(sdncDelete)
235 def sdncRequestId2 = UUID.randomUUID().toString()
236 String sdncDeactivate = sdncDelete.replace(">delete<", ">deactivate<").replace(">${sdncRequestId}<", ">${sdncRequestId2}<")
237 execution.setVariable("sdncDelete", sdncDelete)
238 execution.setVariable("sdncDeactivate", sdncDeactivate)
239 msoLogger.debug("sdncDeactivate:\n" + sdncDeactivate)
240 msoLogger.debug("sdncDelete:\n" + sdncDelete)
242 } catch (BpmnError e) {
244 } catch(Exception ex) {
245 msg = "Exception in preProcessSDNCDelete. " + ex.getMessage()
247 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Exception Occured in preProcessSDNCDelete.\n" + ex.getMessage())
249 msoLogger.debug(" *****Exit preProcessSDNCDelete *****")
252 public void postProcessSDNCDelete(DelegateExecution execution, String response, String method) {
255 msoLogger.trace("postProcessSDNC " + method + " ")
259 WorkflowException workflowException = execution.getVariable("WorkflowException")
260 boolean successIndicator = execution.getVariable("SDNCA_SuccessIndicator")
261 msoLogger.debug("SDNCResponse: " + response)
262 msoLogger.debug("workflowException: " + workflowException)
264 SDNCAdapterUtils sdncAdapterUtils = new SDNCAdapterUtils(this)
265 sdncAdapterUtils.validateSDNCResponse(execution, response, workflowException, successIndicator)
267 if(execution.getVariable(Prefix + 'sdncResponseSuccess') == true){
268 msoLogger.debug("Good response from SDNC Adapter for service-instance " + method + "response:\n" + response)
271 msg = "Bad Response from SDNC Adapter for service-instance " + method
273 exceptionUtil.buildAndThrowWorkflowException(execution, 3500, msg)
275 } catch (BpmnError e) {
277 } catch(Exception ex) {
278 msg = "Exception in postProcessSDNC " + method + " Exception:" + ex.getMessage()
280 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
282 msoLogger.trace("Exit postProcessSDNC " + method + " ")
285 public void postProcessAAIGET(DelegateExecution execution) {
287 msoLogger.trace("postProcessAAIGET ")
292 String serviceInstanceId = execution.getVariable("serviceInstanceId")
293 boolean foundInAAI = execution.getVariable("GENGS_FoundIndicator")
294 String serviceType = ""
296 if(foundInAAI == true){
297 msoLogger.debug("Found Service-instance in AAI")
299 //Extract GlobalSubscriberId
300 String siRelatedLink = execution.getVariable("GENGS_siResourceLink")
301 if (isBlank(siRelatedLink))
303 msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
305 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
309 msoLogger.debug("Found Service-instance in AAI. link: " + siRelatedLink)
310 String globalSubscriberId = execution.getVariable("globalSubscriberId")
311 if(isBlank(globalSubscriberId)){
312 int custStart = siRelatedLink.indexOf("customer/")
313 int custEnd = siRelatedLink.indexOf("/service-subscriptions")
314 globalSubscriberId = siRelatedLink.substring(custStart + 9, custEnd)
315 execution.setVariable("globalSubscriberId", globalSubscriberId)
318 //Extract Service Type if not provided on request
319 String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
320 if(isBlank(subscriptionServiceType)){
321 int serviceStart = siRelatedLink.indexOf("service-subscription/")
322 int serviceEnd = siRelatedLink.indexOf("/service-instances/")
323 String serviceTypeEncoded = siRelatedLink.substring(serviceStart + 21, serviceEnd)
324 subscriptionServiceType = UriUtils.decode(serviceTypeEncoded, "UTF-8")
325 execution.setVariable("subscriptionServiceType", subscriptionServiceType)
328 if (isBlank(globalSubscriberId) || isBlank(subscriptionServiceType))
330 msg = "Could not retrive global-customer-id & subscription-service-type from AAI to delete id:" + serviceInstanceId
332 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
336 String siData = execution.getVariable("GENGS_service")
337 msoLogger.debug("SI Data")
340 msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
342 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
346 msoLogger.debug("SI Data" + siData)
347 serviceType = utils.getNodeText(siData,"service-type")
348 execution.setVariable("serviceType", serviceType)
349 execution.setVariable("serviceRole", utils.getNodeText(siData,"service-role"))
350 String orchestrationStatus = utils.getNodeText(siData,"orchestration-status")
352 //Confirm there are no related service instances (vnf/network or volume)
353 if (utils.nodeExists(siData, "relationship-list")) {
354 msoLogger.debug("SI Data relationship-list exists:")
355 InputSource source = new InputSource(new StringReader(siData));
356 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
357 DocumentBuilder docBuilder = docFactory.newDocumentBuilder()
358 Document serviceXml = docBuilder.parse(source)
360 NodeList nodeList = serviceXml.getElementsByTagName("relationship")
361 for (int x = 0; x < nodeList.getLength(); x++) {
362 Node node = nodeList.item(x)
363 if (node.getNodeType() == Node.ELEMENT_NODE) {
364 Element eElement = (Element) node
365 def e = eElement.getElementsByTagName("related-to").item(0).getTextContent()
366 if(e.equals("generic-vnf") || e.equals("l3-network") || e.equals("allotted-resource") ){
367 msoLogger.debug("ServiceInstance still has relationship(s) to generic-vnfs, l3-networks or allotted-resources")
368 execution.setVariable("siInUse", true)
369 //there are relationship dependencies to this Service Instance
370 msg = " Stopped deleting Service Instance, it has dependencies. Service instance id: " + serviceInstanceId
372 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
374 msoLogger.debug("Relationship NOT related to OpenStack")
380 if ("TRANSPORT".equalsIgnoreCase(serviceType))
382 if ("PendingDelete".equals(orchestrationStatus))
384 execution.setVariable("skipDeactivate", true)
388 msg = "ServiceInstance of type TRANSPORT must in PendingDelete status to allow Delete. Orchestration-status:" + orchestrationStatus
390 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
395 //alacarte SIs are NOT sent to sdnc. exceptions are listed in config variable
396 String svcTypes = UrnPropertiesReader.getVariable("sdnc.si.svc.types",execution) ?: ""
397 msoLogger.debug("SDNC SI serviceTypes:" + svcTypes)
398 List<String> svcList = Arrays.asList(svcTypes.split("\\s*,\\s*"));
399 boolean isSdncService= false
400 for (String listEntry : svcList){
401 if (listEntry.equalsIgnoreCase(serviceType)){
407 //All Macros are sent to SDNC, TRANSPORT(Macro) is sent to SDNW
408 //Alacartes are sent to SDNC if they are listed in config variable above
409 execution.setVariable("sendToSDNC", true)
410 if(execution.getVariable("sdncVersion").equals("1610")) //alacarte
413 execution.setVariable("sendToSDNC", false)
417 msoLogger.debug("isSdncService: " + isSdncService)
418 msoLogger.debug("Send To SDNC: " + execution.getVariable("sendToSDNC"))
419 msoLogger.debug("Service Type: " + execution.getVariable("serviceType"))
423 boolean succInAAI = execution.getVariable("GENGS_SuccessIndicator")
424 if(succInAAI != true){
425 msoLogger.debug("Error getting Service-instance from AAI", + serviceInstanceId)
426 WorkflowException workflowException = execution.getVariable("WorkflowException")
427 msoLogger.debug("workflowException: " + workflowException)
428 if(workflowException != null){
429 exceptionUtil.buildAndThrowWorkflowException(execution, workflowException.getErrorCode(), workflowException.getErrorMessage())
433 msg = "Failure in postProcessAAIGET GENGS_SuccessIndicator:" + succInAAI
435 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
439 msoLogger.debug("Service-instance NOT found in AAI. Silent Success")
441 } catch (BpmnError e) {
443 } catch (Exception ex) {
444 msg = "Exception in DoDeleteServiceInstance.postProcessAAIGET. " + ex.getMessage()
446 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
448 msoLogger.trace("Exit postProcessAAIGET ")
452 * Deletes the service instance in aai
454 public void deleteServiceInstance(DelegateExecution execution) {
455 msoLogger.trace("Entered deleteServiceInstance")
457 String globalCustId = execution.getVariable("globalSubscriberId")
458 String serviceType = execution.getVariable("subscriptionServiceType")
459 String serviceInstanceId = execution.getVariable("serviceInstanceId")
461 AAIResourcesClient resourceClient = new AAIResourcesClient();
462 AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalCustId, serviceType, serviceInstanceId)
463 resourceClient.delete(serviceInstanceUri)
465 msoLogger.trace("Exited deleteServiceInstance")
467 msoLogger.debug("Error occured within deleteServiceInstance method: " + e)
468 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Error occured during deleteServiceInstance from aai")