305e4f3f1cc1aafbf2e8b5d5a5807022146fe8b0
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2018 Huawei Technologies Co., Ltd. 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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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=========================================================
21  */
22 package org.onap.so.bpmn.infrastructure.scripts
23
24 import groovy.json.JsonOutput
25 import groovy.json.JsonSlurper
26 import org.apache.commons.lang3.StringUtils
27 import org.camunda.bpm.engine.delegate.BpmnError
28 import org.camunda.bpm.engine.delegate.DelegateExecution
29 import org.json.JSONArray
30 import org.json.JSONObject
31 import org.onap.aai.domain.yang.RelatedToProperty
32 import org.onap.aai.domain.yang.Relationship
33 import org.onap.aai.domain.yang.RelationshipData
34 import org.onap.aai.domain.yang.ServiceInstance
35 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
36 import org.onap.so.bpmn.common.scripts.ExceptionUtil
37 import org.onap.so.bpmn.common.scripts.MsoUtils
38 import org.onap.so.bpmn.core.UrnPropertiesReader
39 import org.onap.so.bpmn.core.domain.Resource
40 import org.onap.so.bpmn.core.domain.ServiceDecomposition
41 import org.onap.so.bpmn.core.json.JsonUtils
42 import org.onap.so.client.HttpClient
43 import org.onap.so.client.HttpClientFactory
44 import org.onap.so.client.aai.AAIObjectType
45 import org.onap.so.client.aai.AAIResourcesClient
46 import org.onap.so.client.aai.entities.AAIResultWrapper
47 import org.onap.so.client.aai.entities.uri.AAIResourceUri
48 import org.onap.so.client.aai.entities.uri.AAIUriFactory
49 import org.slf4j.Logger
50 import org.slf4j.LoggerFactory
51 import org.onap.so.utils.TargetEntity
52 import org.springframework.web.util.UriUtils
53
54 import javax.ws.rs.NotFoundException
55 import javax.ws.rs.core.Response
56
57
58 import static org.apache.commons.lang3.StringUtils.isBlank
59
60 /**
61  * This groovy class supports the <class>DoDeleteE2EServiceInstance.bpmn</class> process.
62  *
63  * Inputs:
64  * @param - msoRequestId
65  * @param - globalSubscriberId - O
66  * @param - subscriptionServiceType - O
67  * @param - serviceInstanceId
68  * @param - serviceInstanceName - O
69  * @param - serviceInputParams (should contain aic_zone for serviceTypes TRANSPORT,ATM)
70  * @param - sdncVersion
71  * @param - failNotFound - TODO
72  * @param - serviceInputParams - TODO
73  *
74  * @param - delResourceList
75  * @param - serviceRelationShip
76  *
77  * Outputs:
78  * @param - WorkflowException
79  *
80  * Rollback - Deferred
81  */
82 public class DoDeleteE2EServiceInstance extends AbstractServiceTaskProcessor {
83
84         String Prefix="DDEESI_"
85     ExceptionUtil exceptionUtil = new ExceptionUtil()
86     JsonUtils jsonUtil = new JsonUtils()
87     private static final Logger logger = LoggerFactory.getLogger( DoDeleteE2EServiceInstance.class);
88
89
90     public void preProcessRequest (DelegateExecution execution) {
91         logger.debug(" ***** preProcessRequest *****")
92         String msg = ""
93
94         try {
95             String requestId = execution.getVariable("msoRequestId")
96             execution.setVariable("prefix",Prefix)
97
98             //Inputs
99             //requestDetails.subscriberInfo. for AAI GET & PUT & SDNC assignToplology
100             String globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId
101             if (globalSubscriberId == null)
102             {
103                 execution.setVariable("globalSubscriberId", "")
104             }
105
106             //requestDetails.requestParameters. for AAI PUT & SDNC assignTopology
107             String serviceType = execution.getVariable("serviceType")
108             if (serviceType == null)
109             {
110                 execution.setVariable("serviceType", "")
111             }
112
113             //Generated in parent for AAI PUT
114             String serviceInstanceId = execution.getVariable("serviceInstanceId")
115             if (isBlank(serviceInstanceId)){
116                 msg = "Input serviceInstanceId is null"
117                 logger.info(msg)
118                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
119             }
120
121             String sdncCallbackUrl = UrnPropertiesReader.getVariable('mso.workflow.sdncadapter.callback', execution)
122             if (isBlank(sdncCallbackUrl)) {
123                 msg = "URN_mso_workflow_sdncadapter_callback is null"
124                 logger.info(msg)
125                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
126             }
127             execution.setVariable("sdncCallbackUrl", sdncCallbackUrl)
128             logger.info("SDNC Callback URL: " + sdncCallbackUrl)
129
130             StringBuilder sbParams = new StringBuilder()
131             Map<String, String> paramsMap = execution.getVariable("serviceInputParams")
132
133             if (paramsMap != null) {
134                 sbParams.append("<service-input-parameters>")
135                 for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
136                     String paramsXml
137                     String paramName = entry.getKey()
138                     String paramValue = entry.getValue()
139                     paramsXml =
140                             """ <param>
141                                                         <name>${MsoUtils.xmlEscape(paramName)}</name>
142                                                         <value>${MsoUtils.xmlEscape(paramValue)}</value>
143                                                         </param>
144                                                         """
145                     sbParams.append(paramsXml)
146                 }
147                 sbParams.append("</service-input-parameters>")
148             }
149             String siParamsXml = sbParams.toString()
150             if (siParamsXml == null)
151                 siParamsXml = ""
152             execution.setVariable("siParamsXml", siParamsXml)
153
154         } catch (BpmnError e) {
155             throw e;
156         } catch (Exception ex){
157             msg = "Exception in preProcessRequest " + ex.getMessage()
158             logger.error(msg)
159             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
160         }
161         logger.debug("***** Exit preProcessRequest *****")
162     }
163
164     public void postProcessAAIGET(DelegateExecution execution) {
165         logger.debug(" ***** postProcessAAIGET ***** ")
166         String msg = ""
167
168         try {
169             String serviceInstanceId = execution.getVariable('serviceInstanceId')
170             String globalSubscriberId = execution.getVariable('globalSubscriberId')
171             String serviceType = execution.getVariable('serviceType')
172             AAIResourcesClient resourceClient = new AAIResourcesClient()
173             AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalSubscriberId, serviceType, serviceInstanceId)
174             if (!resourceClient.exists(serviceInstanceUri)) {
175                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Service Instance was not found in aai")
176             }
177             AAIResultWrapper wrapper = resourceClient.get(serviceInstanceUri, NotFoundException.class)
178             Optional<ServiceInstance> si = wrapper.asBean(ServiceInstance.class)
179             // found in AAI
180             if (si.isPresent() && StringUtils.isNotEmpty(si.get().getServiceInstanceName())) {
181                 logger.debug("Found Service-instance in AAI")
182                 execution.setVariable("serviceInstanceName", si.get().getServiceInstanceName())
183                 // get model invariant id
184                 // Get Template uuid and version
185                 if ((null != si.get().getModelInvariantId()) && (null != si.get().getModelVersionId())) {
186                     logger.debug("SI Data model-invariant-id and model-version-id exist")
187                     // Set Original Template info
188                     execution.setVariable("model-invariant-id-original", si.get().getModelInvariantId())
189                     execution.setVariable("model-version-id-original", si.get().getModelVersionId())
190                 }
191                 if ((null != si.get().getRelationshipList()) && (null != si.get().getRelationshipList().getRelationship())) {
192                     logger.debug("SI Data relationship-list exists")
193                     List<Relationship> relationshipList = si.get().getRelationshipList().getRelationship()
194                     JSONArray jArray = new JSONArray()
195                     for (Relationship relationship : relationshipList) {
196                         def jObj = getRelationShipData(relationship)
197                         jArray.put(jObj)
198                     }
199                     execution.setVariable("serviceRelationShip", jArray.toString())
200                 }
201             } else {
202                 msg = "Service-instance: " + serviceInstanceId + " NOT found in AAI."
203                 logger.error(msg)
204                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
205             }
206         } catch (BpmnError e) {
207             throw e
208         } catch (NotFoundException e) {
209             logger.debug("Service Instance does not exist AAI")
210             exceptionUtil.buildAndThrowWorkflowException(execution, 404, "Service Instance was not found in aai")
211         } catch (Exception ex) {
212             msg = "Exception in DoDeleteE2EServiceInstance.postProcessAAIGET. " + ex.getMessage()
213             logger.debug(msg)
214             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
215         }
216         logger.debug(" *** Exit postProcessAAIGET *** ")
217     }
218
219     private JSONObject getRelationShipData(Relationship relationship) {
220         JSONObject jObj = new JSONObject()
221         def rt = relationship.getRelatedTo()
222         def rl = relationship.getRelatedLink()
223         logger.debug("ServiceInstance Related NS/Configuration :" + rl)
224         List<RelationshipData> rl_datas = relationship.getRelationshipData()
225         for (RelationshipData rl_data : rl_datas) {
226             def eKey = rl_data.getRelationshipKey()
227             def eValue = rl_data.getRelationshipValue()
228             if ((rt.equals("service-instance") && eKey.equals("service-instance.service-instance-id"))
229                     //for overlay/underlay
230                     || (rt.equals("configuration") && eKey.equals("configuration.configuration-id")
231             )) {
232                 jObj.put("resourceInstanceId", eValue)
233             }
234             // for sp-partner and others
235             else if (eKey.endsWith("-id")) {
236                 jObj.put("resourceInstanceId", eValue)
237                 String resourceName = rt + eValue;
238                 jObj.put("resourceType", resourceName)
239             }
240             jObj.put("resourceLinkUrl", rl)
241         }
242         List<RelatedToProperty> rl_props = relationship.getRelatedToProperty()
243         for (RelatedToProperty rl_prop : rl_props) {
244             def eKey = rl_prop.getPropertyKey()
245             def eValue = rl_prop.getPropertyValue()
246             if ((rt.equals("service-instance") && eKey.equals("service-instance.service-instance-name"))
247                     //for overlay/underlay
248                     || (rt.equals("configuration") && eKey.equals("configuration.configuration-type"))) {
249                 jObj.put("resourceType", eValue)
250             }
251         }
252         logger.debug("Relationship related to Resource:" + jObj.toString())
253         return jObj
254     }
255
256    public void getCurrentNS(DelegateExecution execution){
257        logger.info( "======== Start getCurrentNS Process ======== ")
258
259        def currentIndex = execution.getVariable("currentNSIndex")
260        List<String> nsSequence = execution.getVariable("nsSequence")
261        String nsResourceType =  nsSequence.get(currentIndex)
262
263        // GET AAI by Name, not ID, for process convenient
264        execution.setVariable("GENGS_type", "service-instance")
265        execution.setVariable("GENGS_serviceInstanceId", "")
266        execution.setVariable("GENGS_serviceInstanceName", nsResourceType)
267
268        logger.debug("======== COMPLETED getCurrentNS Process ======== ")
269    }
270
271     public void prepareDecomposeService(DelegateExecution execution) {
272         try {
273             logger.debug(" ***** Inside prepareDecomposeService of create generic e2e service ***** ")
274             String modelInvariantUuid = execution.getVariable("model-invariant-id-original")
275             String modelVersionId = execution.getVariable("model-version-id-original")
276
277             String serviceModelInfo = """{
278             "modelInvariantUuid":"${modelInvariantUuid}",
279             "modelUuid":"${modelVersionId}",
280             "modelVersion":""
281              }"""
282             execution.setVariable("serviceModelInfo", serviceModelInfo)
283
284             logger.debug(" ***** Completed prepareDecomposeService of  create generic e2e service ***** ")
285         } catch (Exception ex) {
286             // try error in method block
287             String exceptionMessage = "Bpmn error encountered in  create generic e2e service flow. Unexpected Error from method prepareDecomposeService() - " + ex.getMessage()
288             logger.error(exceptionMessage)
289             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
290         }
291     }
292
293         private void generateRelatedResourceInfo(String response, JSONObject jObj){
294
295                 def xml = new XmlSlurper().parseText(response)
296                 def rtn = xml.childNodes()
297                 while (rtn.hasNext()) {
298                         groovy.util.slurpersupport.Node node = rtn.next()
299                         def key = node.name()
300                         def value = node.text()
301                         jObj.put(key, value)
302                 }
303         }
304
305         private JSONObject getRelatedResourceInAAI (DelegateExecution execution, JSONObject jObj)
306         {
307                 logger.debug(" ***** Started getRelatedResourceInAAI *****")
308
309         String aai_endpoint = UrnPropertiesReader.getVariable("aai.endpoint", execution)
310                 String urlLink = jObj.get("resourceLinkUrl")
311                 String serviceAaiPath = "${aai_endpoint}${urlLink}"
312
313                 URL url = new URL(serviceAaiPath)
314                 HttpClient client = new HttpClientFactory().newXmlClient(url, TargetEntity.AAI)
315
316
317                 Response response = client.get()
318                 int responseCode = response.getStatus()
319                 execution.setVariable(Prefix + "GeRelatedResourceResponseCode", responseCode)
320                 logger.debug("  Get RelatedResource code is: " + responseCode)
321
322                 String aaiResponse = response.readEntity(String.class)
323                 execution.setVariable(Prefix + "GetRelatedResourceResponse", aaiResponse)
324
325                 //Process Response
326                 if(responseCode == 200 || responseCode == 201 || responseCode == 202 )
327                         //200 OK 201 CREATED 202 ACCEPTED
328                 {
329                         logger.debug("GET RelatedResource Received a Good Response")
330                         execution.setVariable(Prefix + "SuccessIndicator", true)
331                         execution.setVariable(Prefix + "FoundIndicator", true)
332
333                         generateRelatedResourceInfo(aaiResponse, jObj)
334
335                         //get model-invariant-uuid and model-uuid
336                         String modelInvariantId = ""
337                         String modelUuid = ""
338                         String modelCustomizationId = ""
339                         if(jObj.has("model-invariant-id")) {
340                                 modelInvariantId = jObj.get("model-invariant-id")
341                                 modelUuid = jObj.get("model-version-id")
342                                 modelCustomizationId = jObj.get("model-customization-id")
343                         }
344
345                         jObj.put("modelInvariantId", modelInvariantId)
346                         jObj.put("modelVersionId", modelUuid)
347                         jObj.put("modelCustomizationId", modelCustomizationId)
348                 }
349                 else {
350             String exceptionMessage = "Get RelatedResource Received a Bad Response Code. Response Code is: " + responseCode
351                         logger.error(exceptionMessage)
352             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
353         }
354
355                 logger.debug(" ***** Exit getRelatedResourceInAAI *****")
356                 return jObj
357         }
358
359     public void postDecomposeService(DelegateExecution execution) {
360         logger.debug(" ***** Inside postDecomposeService() of  delete generic e2e service flow ***** ")
361         try {
362             ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
363
364             // service model info
365             execution.setVariable("serviceModelInfo", serviceDecomposition.getModelInfo())
366
367             List<Resource> deleteResourceList = serviceDecomposition.getServiceResources()
368             String serviceRelationShip = execution.getVariable("serviceRelationShip")
369             def jsonSlurper = new JsonSlurper()
370             def jsonOutput = new JsonOutput()
371
372             List relationShipList = null
373             if (serviceRelationShip != null) {
374                 relationShipList = jsonSlurper.parseText(serviceRelationShip)
375             }
376
377             List<Resource> deleteRealResourceList = new ArrayList<Resource>()
378
379             //Set the real resource instance id to the decomosed resource list
380             //reset the resource instance id , because in the decompose flow ,its a random one.
381             //match the resource-instance-name and the model name
382             if (relationShipList != null) {
383                 relationShipList.each {
384
385                     JSONObject obj = getRelatedResourceInAAI(execution, (JSONObject)it)
386
387                     for (Resource resource : deleteResourceList) {
388
389                         String modelName = resource.getModelInfo().getModelName()
390
391                         String modelCustomizationUuid = resource.getModelInfo().getModelCustomizationUuid()
392                         if (StringUtils.containsIgnoreCase(obj.get("resourceType"), modelName)) {
393                             resource.setResourceId(obj.get("resourceInstanceId"))
394                             deleteRealResourceList.add(resource)
395                         }
396                         else if (modelCustomizationUuid.equals(obj.get("modelCustomizationId"))) {
397                             resource.setResourceId(obj.get("resourceInstanceId"))
398                             resource.setResourceInstanceName(obj.get("resourceType"))
399                             deleteRealResourceList.add(resource)
400                         }
401                     }
402                 }
403             }
404
405             // only delete real existing resources
406             execution.setVariable("deleteResourceList", deleteRealResourceList)
407             
408             boolean isDeleteResourceListValid = false
409             if(deleteRealResourceList.size() > 0) {
410                 isDeleteResourceListValid = true
411             }
412             execution.setVariable("isDeleteResourceListValid", isDeleteResourceListValid)
413
414             logger.debug("delete resource list : " + deleteRealResourceList)
415         } catch (Exception ex) {
416             String exceptionMessage = "Bpmn error encountered in  create generic e2e service flow. processDecomposition() - " + ex.getMessage()
417             logger.error(exceptionMessage)
418             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
419         }
420         logger.debug(" ***** exit postDecomposeService() of  delete generic e2e service flow ***** ")
421     }
422
423     public void preInitResourcesOperStatus(DelegateExecution execution){
424         logger.debug(" ======== STARTED preInitResourcesOperStatus Process ======== ")
425         try{
426             String serviceId = execution.getVariable("serviceInstanceId")
427             String operationId = execution.getVariable("operationId")
428             String operationType = execution.getVariable("operationType")
429             String resourceTemplateUUIDs = ""
430             String result = "processing"
431             String progress = "0"
432             String reason = ""
433             String operationContent = "Prepare service creation"
434             logger.debug("Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId + " operationType:" + operationType)
435             serviceId = UriUtils.encode(serviceId,"UTF-8")
436             execution.setVariable("serviceInstanceId", serviceId)
437             execution.setVariable("operationId", operationId)
438             execution.setVariable("operationType", operationType)
439             List<Resource> deleteResourceList = execution.getVariable("deleteResourceList")
440
441             String serviceRelationShip = execution.getVariable("serviceRelationShip")
442             for(Resource resource : deleteResourceList){
443                     resourceTemplateUUIDs  = resourceTemplateUUIDs + resource.getModelInfo().getModelCustomizationUuid() + ":"
444             }
445
446             def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
447             execution.setVariable("URN_mso_adapters_openecomp_db_endpoint", dbAdapterEndpoint)
448
449             String payload =
450                     """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
451                         xmlns:ns="http://org.onap.so/requestsdb">
452                         <soapenv:Header/>
453                         <soapenv:Body>
454                             <ns:initResourceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
455                             <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
456                             <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
457                             <operationType>${MsoUtils.xmlEscape(operationType)}</operationType>
458                             <resourceTemplateUUIDs>${MsoUtils.xmlEscape(resourceTemplateUUIDs)}</resourceTemplateUUIDs>
459                         </ns:initResourceOperationStatus>
460                     </soapenv:Body>
461                 </soapenv:Envelope>"""
462
463             payload = utils.formatXml(payload)
464             execution.setVariable("CVFMI_initResOperStatusRequest", payload)
465             logger.debug("Outgoing initResourceOperationStatus: \n" + payload)
466             logger.debug("CreateVfModuleInfra Outgoing initResourceOperationStatus Request: " + payload)
467
468         }catch(Exception e){
469             logger.debug("Exception Occured Processing preInitResourcesOperStatus. Exception is:\n" + e)
470             execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during preInitResourcesOperStatus Method:\n" + e.getMessage())
471         }
472         logger.debug("======== COMPLETED preInitResourcesOperStatus Process ======== ")
473     }
474     
475     public void prepareUpdateServiceOperationStatus(DelegateExecution execution){
476         logger.debug(" ======== STARTED prepareUpdateServiceOperationStatus Process ======== ")
477         try{
478             String serviceId = execution.getVariable("serviceInstanceId")
479             String operationId = execution.getVariable("operationId")
480             String userId = ""
481             String result = execution.getVariable("result")
482             String progress = execution.getVariable("progress")
483             String reason = ""
484             String operationContent = execution.getVariable("operationContent")
485             
486             serviceId = UriUtils.encode(serviceId,"UTF-8")
487
488             def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
489             execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint)
490             logger.debug("DB Adapter Endpoint is: " + dbAdapterEndpoint)
491
492             String payload =
493                     """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
494                         xmlns:ns="http://org.onap.so/requestsdb">
495                         <soapenv:Header/>
496                         <soapenv:Body>
497                             <ns:updateServiceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
498                             <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
499                             <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
500                             <operationType>DELETE</operationType>
501                             <userId>${MsoUtils.xmlEscape(userId)}</userId>
502                             <result>${MsoUtils.xmlEscape(result)}</result>
503                             <operationContent>${MsoUtils.xmlEscape(operationContent)}</operationContent>
504                             <progress>${MsoUtils.xmlEscape(progress)}</progress>
505                             <reason>${MsoUtils.xmlEscape(reason)}</reason>
506                         </ns:updateServiceOperationStatus>
507                     </soapenv:Body>
508                 </soapenv:Envelope>"""
509
510             payload = utils.formatXml(payload)
511             execution.setVariable("CVFMI_updateServiceOperStatusRequest", payload)
512             logger.debug("Outgoing updateServiceOperStatusRequest: \n" + payload)
513
514         }catch(Exception e){
515             logger.error("Exception Occured Processing prepareUpdateServiceOperationStatus. Exception is:\n" + e)
516             execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during prepareUpdateServiceOperationStatus Method:\n" + e.getMessage())
517         }
518         logger.debug("======== COMPLETED prepareUpdateServiceOperationStatus Process ======== ")
519     }
520
521      /**
522       * post config request.
523       */
524      public void postConfigRequest(execution){
525          //to do
526      }
527
528 }