Containerization feature of SO
[so.git] / bpmn / so-bpmn-infrastructure-flows / src / main / groovy / org / onap / so / bpmn / infrastructure / scripts / DoDeleteServiceInstance.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.so.bpmn.infrastructure.scripts
22
23 import static org.apache.commons.lang3.StringUtils.*;
24
25 import javax.xml.parsers.DocumentBuilder
26 import javax.xml.parsers.DocumentBuilderFactory
27
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
49
50 import groovy.json.*
51
52 /**
53  * This groovy class supports the <class>DoDeleteServiceInstance.bpmn</class> process.
54  *
55  * Inputs:
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
67  *
68  * Outputs:
69  * @param - WorkflowException
70  *
71  * Rollback - Deferred
72  */
73 public class DoDeleteServiceInstance extends AbstractServiceTaskProcessor {
74         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, DoDeleteServiceInstance.class);
75
76         String Prefix="DDELSI_"
77         ExceptionUtil exceptionUtil = new ExceptionUtil()
78         JsonUtils jsonUtil = new JsonUtils()
79
80         public void preProcessRequest (DelegateExecution execution) {
81
82                 msoLogger.trace("preProcessRequest ")
83                 String msg = ""
84
85                 try {
86                         String requestId = execution.getVariable("msoRequestId")
87                         execution.setVariable("prefix",Prefix)
88
89                         //Inputs
90                         //requestDetails.subscriberInfo. for AAI GET & PUT & SDNC assignToplology
91                         String globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId
92                         if (globalSubscriberId == null)
93                         {
94                                 execution.setVariable("globalSubscriberId", "")
95                         }
96
97                         //requestDetails.requestParameters. for AAI PUT & SDNC assignTopology
98                         String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
99                         if (subscriptionServiceType == null)
100                         {
101                                 execution.setVariable("subscriptionServiceType", "")
102                         }
103
104                         //Generated in parent for AAI PUT
105                         String serviceInstanceId = execution.getVariable("serviceInstanceId")
106                         if (isBlank(serviceInstanceId)){
107                                 msg = "Input serviceInstanceId is null"
108                                 msoLogger.debug(msg)
109                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
110                         }
111
112                         String sdncCallbackUrl = UrnPropertiesReader.getVariable('mso.workflow.sdncadapter.callback',execution)
113                         if (isBlank(sdncCallbackUrl)) {
114                                 msg = "mso.workflow.sdncadapter.callback is null"
115                                 msoLogger.debug(msg)
116                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
117                         }
118                         execution.setVariable("sdncCallbackUrl", sdncCallbackUrl)
119                         msoLogger.debug("SDNC Callback URL: " + sdncCallbackUrl)
120
121                         StringBuilder sbParams = new StringBuilder()
122                         Map<String, String> paramsMap = execution.getVariable("serviceInputParams")
123                         if (paramsMap != null)
124                         {
125                                 sbParams.append("<service-input-parameters>")
126                                 for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
127                                         String paramsXml
128                                         String paramName = entry.getKey()
129                                         String paramValue = entry.getValue()
130                                         paramsXml =
131                                                         """     <param>
132                                                         <name>${MsoUtils.xmlEscape(paramName)}</name>
133                                                         <value>${MsoUtils.xmlEscape(paramValue)}</value>
134                                                         </param>
135                                                         """
136                                         sbParams.append(paramsXml)
137                                 }
138                                 sbParams.append("</service-input-parameters>")
139                         }
140                         String siParamsXml = sbParams.toString()
141                         if (siParamsXml == null)
142                                 siParamsXml = ""
143                         execution.setVariable("siParamsXml", siParamsXml)
144
145                 } catch (BpmnError e) {
146                         throw e;
147                 } catch (Exception ex){
148                         msg = "Exception in preProcessRequest " + ex.getMessage()
149                         msoLogger.debug(msg)
150                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
151                 }
152                 msoLogger.trace("Exit preProcessRequest ")
153         }
154
155         public void preProcessSDNCDelete (DelegateExecution execution) {
156
157                 msoLogger.trace("preProcessSDNCDelete ")
158                 String msg = ""
159
160                 try {
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
168
169                         String serviceModelInfo = execution.getVariable("serviceModelInfo") ?: ""
170                         def modelInvariantUuid = ""
171                         def modelVersion = ""
172                         def modelUuid = ""
173                         def modelName = ""
174                         if (!isBlank(serviceModelInfo))
175                         {
176                                 modelInvariantUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelInvariantUuid") ?: ""
177                                 modelVersion = jsonUtil.getJsonValue(serviceModelInfo, "modelVersion") ?: ""
178                                 modelUuid = jsonUtil.getJsonValue(serviceModelInfo, "modelUuid") ?: ""
179                                 modelName = jsonUtil.getJsonValue(serviceModelInfo, "modelName") ?: ""
180
181                         }
182
183                         def siParamsXml = execution.getVariable("siParamsXml") ?: ""
184                         def msoAction = ""
185                         // special URL for SDNW, msoAction helps set diff url in SDNCA
186                         if("TRANSPORT".equalsIgnoreCase(execution.getVariable("serviceType")))
187                         {
188                                 msoAction = "TRANSPORT"
189                         }
190
191                         def sdncRequestId = UUID.randomUUID().toString()
192
193                         String sdncDelete =
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>
208                                                 <source>MSO</source>
209                                                 <notification-url/>
210                                                 <order-number/>
211                                                 <order-version/>
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>
224                                                 <subscriber-name/>
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>
229                                                 ${siParamsXml}
230                                         </service-request-input>
231                                 </sdncadapterworkflow:SDNCRequestData>
232                                 </sdncadapterworkflow:SDNCAdapterWorkflowRequest>"""
233
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)
241
242                 } catch (BpmnError e) {
243                         throw e;
244                 } catch(Exception ex) {
245                         msg = "Exception in preProcessSDNCDelete. " + ex.getMessage()
246                         msoLogger.debug(msg)
247                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Exception Occured in preProcessSDNCDelete.\n" + ex.getMessage())
248                 }
249                 msoLogger.debug(" *****Exit preProcessSDNCDelete *****")
250         }
251
252         public void postProcessSDNCDelete(DelegateExecution execution, String response, String method) {
253
254
255                 msoLogger.trace("postProcessSDNC " + method + " ")
256                 String msg = ""
257
258                 try {
259                         WorkflowException workflowException = execution.getVariable("WorkflowException")
260                         boolean successIndicator = execution.getVariable("SDNCA_SuccessIndicator")
261                         msoLogger.debug("SDNCResponse: " + response)
262                         msoLogger.debug("workflowException: " + workflowException)
263
264                         SDNCAdapterUtils sdncAdapterUtils = new SDNCAdapterUtils(this)
265                         sdncAdapterUtils.validateSDNCResponse(execution, response, workflowException, successIndicator)
266
267                         if(execution.getVariable(Prefix + 'sdncResponseSuccess') == true){
268                                 msoLogger.debug("Good response from SDNC Adapter for service-instance " + method + "response:\n" + response)
269
270                         }else{
271                                 msg = "Bad Response from SDNC Adapter for service-instance " + method
272                                 msoLogger.debug(msg)
273                                 exceptionUtil.buildAndThrowWorkflowException(execution, 3500, msg)
274                         }
275                 } catch (BpmnError e) {
276                         throw e;
277                 } catch(Exception ex) {
278                         msg = "Exception in postProcessSDNC " + method + " Exception:" + ex.getMessage()
279                         msoLogger.debug(msg)
280                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
281                 }
282                 msoLogger.trace("Exit postProcessSDNC " + method + " ")
283         }
284
285         public void postProcessAAIGET(DelegateExecution execution) {
286
287                 msoLogger.trace("postProcessAAIGET ")
288                 String msg = ""
289
290                 try {
291
292                         String serviceInstanceId = execution.getVariable("serviceInstanceId")
293                         boolean foundInAAI = execution.getVariable("GENGS_FoundIndicator")
294                         String serviceType = ""
295
296                         if(foundInAAI == true){
297                                 msoLogger.debug("Found Service-instance in AAI")
298
299                                 //Extract GlobalSubscriberId
300                                 String siRelatedLink = execution.getVariable("GENGS_siResourceLink")
301                                 if (isBlank(siRelatedLink))
302                                 {
303                                         msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
304                                         msoLogger.debug(msg)
305                                         exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
306                                 }
307                                 else
308                                 {
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)
316                                         }
317
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)
326                                         }
327
328                                         if (isBlank(globalSubscriberId) || isBlank(subscriptionServiceType))
329                                         {
330                                                 msg = "Could not retrive global-customer-id & subscription-service-type from AAI to delete id:" + serviceInstanceId
331                                                 msoLogger.debug(msg)
332                                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
333                                         }
334                                 }
335
336                                 String siData = execution.getVariable("GENGS_service")
337                                 msoLogger.debug("SI Data")
338                                 if (isBlank(siData))
339                                 {
340                                         msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
341                                         msoLogger.debug(msg)
342                                         exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
343                                 }
344                                 else
345                                 {
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")
351
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)
359
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
371                                                                         msoLogger.debug(msg)
372                                                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
373                                                                 }else{
374                                                                         msoLogger.debug("Relationship NOT related to OpenStack")
375                                                                 }
376                                                         }
377                                                 }
378                                         }
379
380                                         if ("TRANSPORT".equalsIgnoreCase(serviceType))
381                                         {
382                                                 if ("PendingDelete".equals(orchestrationStatus))
383                                                 {
384                                                         execution.setVariable("skipDeactivate", true)
385                                                 }
386                                                 else
387                                                 {
388                                                         msg = "ServiceInstance of type TRANSPORT must in PendingDelete status to allow Delete. Orchestration-status:" + orchestrationStatus
389                                                         msoLogger.debug(msg)
390                                                         exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
391                                                 }
392
393                                         }
394
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)){
402                                                         isSdncService = true
403                                                         break;
404                                                 }
405                                         }
406
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
411                                         {
412                                                 if(!isSdncService){
413                                                         execution.setVariable("sendToSDNC", false)
414                                                 }
415                                         }
416
417                                         msoLogger.debug("isSdncService: " + isSdncService)
418                                         msoLogger.debug("Send To SDNC: " + execution.getVariable("sendToSDNC"))
419                                         msoLogger.debug("Service Type: " + execution.getVariable("serviceType"))
420
421                                 }
422                         }else{
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())
430                                         }
431                                         else
432                                         {
433                                                 msg = "Failure in postProcessAAIGET GENGS_SuccessIndicator:" + succInAAI
434                                                 msoLogger.debug(msg)
435                                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
436                                         }
437                                 }
438
439                                 msoLogger.debug("Service-instance NOT found in AAI. Silent Success")
440                         }
441                 } catch (BpmnError e) {
442                         throw e;
443                 } catch (Exception ex) {
444                         msg = "Exception in DoDeleteServiceInstance.postProcessAAIGET. " + ex.getMessage()
445                         msoLogger.debug(msg)
446                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
447                 }
448                 msoLogger.trace("Exit postProcessAAIGET ")
449         }
450
451         /**
452          * Deletes the service instance in aai
453          */
454         public void deleteServiceInstance(DelegateExecution execution) {
455                 msoLogger.trace("Entered deleteServiceInstance")
456                 try {
457                         String globalCustId = execution.getVariable("globalSubscriberId")
458                         String serviceType = execution.getVariable("subscriptionServiceType")
459                         String serviceInstanceId = execution.getVariable("serviceInstanceId")
460
461                         AAIResourcesClient resourceClient = new AAIResourcesClient();
462                         AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalCustId, serviceType, serviceInstanceId)
463                         resourceClient.delete(serviceInstanceUri)
464
465                         msoLogger.trace("Exited deleteServiceInstance")
466                 }catch(Exception e){
467                         msoLogger.debug("Error occured within deleteServiceInstance method: " + e)
468                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Error occured during deleteServiceInstance from aai")
469                 }
470         }
471
472 }