b94c81b41ffdd22f525b5e4c7b06b47c938bf64d
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  # Copyright (c) 2019, CMCC Technologies Co., Ltd.
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 package org.onap.so.bpmn.infrastructure.scripts
21
22
23 import static org.apache.commons.lang3.StringUtils.isBlank
24 import javax.ws.rs.NotFoundException
25 import javax.ws.rs.core.Response
26 import org.camunda.bpm.engine.delegate.BpmnError
27 import org.camunda.bpm.engine.delegate.DelegateExecution
28 import org.onap.aai.domain.yang.CommunicationServiceProfile
29 import org.onap.aai.domain.yang.CommunicationServiceProfiles
30 import org.onap.aai.domain.yang.Relationship
31 import org.onap.aai.domain.yang.ServiceInstance
32 import org.onap.aaiclient.client.aai.AAIObjectName
33 import org.onap.aaiclient.client.aai.AAIObjectType
34 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
35 import org.onap.aaiclient.client.aai.entities.uri.AAIPluralResourceUri
36 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
37 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
38 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
39 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types
40 import org.onap.logging.filter.base.ONAPComponents
41 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
42 import org.onap.so.bpmn.common.scripts.ExceptionUtil
43 import org.onap.so.bpmn.common.scripts.MsoUtils
44 import org.onap.so.bpmn.common.scripts.RequestDBUtil
45 import org.onap.so.bpmn.core.UrnPropertiesReader
46 import org.onap.so.bpmn.core.WorkflowException
47 import org.onap.so.bpmn.core.json.JsonUtils
48 import org.onap.so.client.HttpClient
49 import org.onap.so.db.request.beans.OperationStatus
50 import org.slf4j.Logger
51 import org.slf4j.LoggerFactory
52
53 class DeleteCommunicationService extends AbstractServiceTaskProcessor {
54     private final String PREFIX ="DeleteCommunicationService"
55     private final Long TIMEOUT = 60 * 60 * 1000
56
57     ExceptionUtil exceptionUtil = new ExceptionUtil()
58     JsonUtils jsonUtil = new JsonUtils()
59     private RequestDBUtil requestDBUtil = new RequestDBUtil()
60     private static final Logger LOGGER = LoggerFactory.getLogger(DeleteCommunicationService.class)
61
62     @Override
63     void preProcessRequest(DelegateExecution execution) {
64         execution.setVariable("prefix",PREFIX)
65         String msg = ""
66
67         LOGGER.trace("Starting preProcessRequest")
68
69         try {
70             // check for incoming json message/input
71             String siRequest = execution.getVariable("bpmnRequest")
72             String requestId = execution.getVariable("mso-request-id")
73             execution.setVariable("msoRequestId", requestId)
74             execution.setVariable("operationType", "DELETE")
75
76             //communication service id
77             String serviceInstanceId = execution.getVariable("serviceInstanceId")
78             if (isBlank(serviceInstanceId)) {
79                 msg = "communication-service id is null"
80                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
81             }
82
83             LOGGER.info("Input Request: ${siRequest}, reqId: ${requestId}, serviceInstanceId: ${serviceInstanceId}")
84
85             //requestParameters
86             checkAndSetRequestParam(siRequest,"globalSubscriberId",false,execution)
87             checkAndSetRequestParam(siRequest,"serviceType",false,execution)
88             checkAndSetRequestParam(siRequest,"operationId",false,execution)
89
90         } catch (BpmnError e) {
91             throw e
92         } catch (any) {
93             msg = "Exception in preProcessRequest " + any.getCause()
94             LOGGER.debug(msg)
95             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
96         }
97         LOGGER.trace("Exit preProcessRequest")
98     }
99
100
101     /**
102      * prepare update operation status
103      * @param execution
104      */
105     void preInitUpdateOperationStatus(DelegateExecution execution){
106         LOGGER.trace(" ======== STARTED initUpdateOperationStatus Process ======== ")
107         try{
108             execution.setVariable("result","processing")
109             execution.setVariable("progress","0")
110             execution.setVariable("operationContent","delete communication service operation start")
111             setOperationStatus(execution)
112
113         }catch(Exception e){
114             LOGGER.error("Exception Occured Processing initUpdateOperationStatus. Exception is:\n" + e)
115             execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during initUpdateOperationStatus Method:\n" + e.getMessage())
116         }
117         LOGGER.trace("======== COMPLETED initUpdateOperationStatus Process ======== ")
118     }
119
120     /**
121      * send sync response
122      * @param execution
123      */
124     void sendSyncResponse(DelegateExecution execution) {
125         LOGGER.debug("Begin sendSyncResponse")
126
127         try {
128             String operationId = execution.getVariable("operationId")
129             String syncResponse = """{"operationId":"${operationId}"}""".trim()
130             sendWorkflowResponse(execution, 202, syncResponse)
131
132         } catch (Exception ex) {
133             String msg  = "Exception in sendSyncResponse: " + ex.getMessage()
134             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
135         }
136         LOGGER.debug("Exit sendSyncResponse")
137     }
138
139     /**
140      * query CommunicationSerive from AAI
141      * save e2eslice-service instance id and service name
142      * @param execution
143      */
144     void queryCommunicationSeriveFromAAI(DelegateExecution execution)
145     {
146         LOGGER.trace(" ***** begin queryCommunicationSeriveFromAAI *****")
147         String serviceInstanceId = execution.getVariable("serviceInstanceId")
148
149         String errorMsg = "query communication service from aai failed"
150         AAIResultWrapper wrapper = queryAAI(execution, Types.SERVICE_INSTANCE, serviceInstanceId, errorMsg)
151         Optional<ServiceInstance> si = wrapper.asBean(ServiceInstance.class)
152         if(si.isPresent())
153         {
154             String serviceInstName = si.get()?.getServiceInstanceName()
155             String e2eSliceServiceInstId
156             if(si.isPresent())
157             {
158                 List<Relationship> relationshipList = si.get().getRelationshipList()?.getRelationship()
159                 for (Relationship relationship : relationshipList)
160                 {
161                     String relatedTo = relationship.getRelatedTo()
162                     if (relatedTo == "service-instance")
163                     {
164                         String relatedLink = relationship.getRelatedLink()?:""
165                         e2eSliceServiceInstId = relatedLink ? relatedLink.substring(relatedLink.lastIndexOf("/") + 1,relatedLink.length()) : ""
166                         break
167                     }
168                 }
169             }
170             execution.setVariable("e2eSliceServiceInstanceId", e2eSliceServiceInstId)
171             execution.setVariable("serviceInstanceName", serviceInstName ?: "")
172             LOGGER.info("communication-service Id: ${serviceInstanceId}, e2eslice-service Id: ${e2eSliceServiceInstId}, serviceName: ${serviceInstName}")
173         }
174         LOGGER.debug(" ***** Exit queryCommunicationSeriveFromAAI *****")
175     }
176
177     /**
178      * query AAI
179      * @param execution
180      * @param aaiObjectName
181      * @param instanceId
182      * @return AAIResultWrapper
183      */
184     private AAIResultWrapper queryAAI(DelegateExecution execution, AAIObjectName aaiObjectName, String instanceId, String errorMsg)
185     {
186         String globalSubscriberId = execution.getVariable("globalSubscriberId")
187         String serviceType = execution.getVariable("serviceType")
188
189         AAIResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(instanceId))
190         if (!getAAIClient().exists(resourceUri)) {
191             exceptionUtil.buildAndThrowWorkflowException(execution, 2500, errorMsg)
192         }
193         AAIResultWrapper wrapper = getAAIClient().get(resourceUri, NotFoundException.class)
194         return wrapper
195     }
196
197
198     /**
199      * 再次调用deleteE2EServiceInstance接口,然后获取到operationid,
200      */
201     void sendRequest2NSMFWF(DelegateExecution execution) {
202         LOGGER.debug("begin preRequestSend2NSMF")
203         try {
204             //url:/onap/so/infra/e2eServiceInstances/v3/{serviceInstanceId}"
205             def NSMF_endpoint = UrnPropertiesReader.getVariable("mso.infra.endpoint.url", execution)
206             String url = "${NSMF_endpoint}/e2eServiceInstances/v3/${execution.getVariable("e2eSliceServiceInstanceId")}"
207
208             String requestBody = """
209                 {
210                     "globalSubscriberId": "${execution.getVariable("globalSubscriberId")}",
211                     "serviceType": "${execution.getVariable("serviceType")}"
212                 }
213             """
214             requestBody.replaceAll("\\s+", "")
215
216             String msoKey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
217             String basicAuth =  UrnPropertiesReader.getVariable("mso.infra.endpoint.auth", execution)
218 //            String basicAuthValue = utils.encrypt(basicAuth, msoKey)
219 //            String encodeString = utils.getBasicAuth(basicAuthValue, msoKey)
220
221             HttpClient httpClient = getHttpClientFactory().newJsonClient(new URL(url), ONAPComponents.SO)
222 //            httpClient.addAdditionalHeader("Authorization", encodeString)
223             httpClient.addAdditionalHeader("Authorization", basicAuth)
224             httpClient.addAdditionalHeader("Accept", "application/json")
225             Response httpResponse = httpClient.delete(requestBody)
226             handleNSSMFWFResponse(httpResponse, execution)
227
228         } catch (BpmnError e) {
229             throw e
230         } catch (any) {
231             String msg = "Exception in DeleteCommunicationService.preRequestSend2NSMF. " + any.getCause()
232             LOGGER.error(msg)
233             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
234         }
235
236         LOGGER.debug("exit preRequestSend2NSMF")
237     }
238
239     /**
240      * prepare update operation status
241      * @param execution
242      */
243     private void handleNSSMFWFResponse(Response httpResponse, DelegateExecution execution){
244         LOGGER.debug(" ======== STARTED prepareUpdateOperationStatus Process ======== ")
245
246         int nsmfResponseCode = httpResponse.getStatus()
247         LOGGER.debug("nsmfResponseCode${nsmfResponseCode}")
248
249         if (nsmfResponseCode >= 200 && nsmfResponseCode < 204 && httpResponse.hasEntity()) {
250             String nsmfResponse = httpResponse.readEntity(String.class)
251             def e2eOperationId = jsonUtil.getJsonValue(nsmfResponse, "operationId")
252             execution.setVariable("e2eOperationId", e2eOperationId)
253             execution.setVariable("progress","20")
254             execution.setVariable("operationContent","waiting nsmf service delete finished")
255
256             execution.setVariable("currentCycle",0)
257             execution.setVariable("isNSMFTimeOut", "no")
258             execution.setVariable("isNSMFWFRspSucceed","yes")
259         }
260         else
261         {
262             String serviceName = execution.getVariable("serviceInstanceName")
263             execution.setVariable("progress", "100")
264             execution.setVariable("result", "error")
265             execution.setVariable("operationContent", "terminate service failure.")
266             execution.setVariable("reason","NSMF WF asynchronous response failed, status Code:${nsmfResponseCode}")
267             execution.setVariable("isNSMFWFRspSucceed","no")
268             LOGGER.error("nsmf async response error,nsmfResponseCode:${nsmfResponseCode},serivceName:${serviceName}")
269         }
270         setOperationStatus(execution)
271         LOGGER.debug("======== COMPLETED prepareUpdateOperationStatus Process ======== ")
272     }
273
274     /**
275      * prepare to call sub process
276      * @param execution
277      */
278     void prepareCallCheckProcessStatus(DelegateExecution execution)
279     {
280         LOGGER.debug(PREFIX + "prepareCallCheckProcessStatus Start")
281
282         def successConditions = new ArrayList<>()
283         successConditions.add("finished")
284         execution.setVariable("successConditions", successConditions)
285
286         def errorConditions = new ArrayList<>()
287         errorConditions.add("error")
288         execution.setVariable("errorConditions", errorConditions)
289
290         execution.setVariable("processServiceType", "communication service")
291         execution.setVariable("subOperationType", "DELETE")
292         execution.setVariable("initProgress", 20)
293         execution.setVariable("endProgress",90)
294
295         execution.setVariable("timeOut", TIMEOUT)
296
297         LOGGER.debug(PREFIX + "prepareCallCheckProcessStatus Exit")
298     }
299
300     /**
301      * delete communication profile from AAI
302      * @param execution
303      */
304     void delCSProfileFromAAI(DelegateExecution execution)
305     {
306         LOGGER.debug("start delete communication service profile from AAI")
307         String globalSubscriberId = execution.getVariable("globalSubscriberId")
308         String serviceType = execution.getVariable("serviceType")
309         String serviceInstanceId = execution.getVariable("serviceInstanceId")
310
311         String profileId
312         try
313         {
314             AAIPluralResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(serviceInstanceId).communicationServiceProfiles())
315             AAIResultWrapper wrapper = getAAIClient().get(resourceUri, NotFoundException.class)
316             Optional<CommunicationServiceProfiles> csProfilesOpt = wrapper.asBean(CommunicationServiceProfiles.class)
317             if(csProfilesOpt.isPresent()){
318                 CommunicationServiceProfiles csProfiles = csProfilesOpt.get()
319                 CommunicationServiceProfile csProfile = csProfiles.getCommunicationServiceProfile().get(0)
320                 profileId = csProfile ? csProfile.getProfileId() : ""
321             }
322             resourceUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(serviceInstanceId).communicationServiceProfile(profileId))
323             if (!getAAIClient().exists(resourceUri)) {
324                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "communication service profile was not found in aai")
325             }
326
327             getAAIClient().delete(resourceUri)
328             LOGGER.debug("end delete communication service profile from AAI")
329         }
330         catch (any)
331         {
332             String msg = "delete communication service profile from aai failed! cause-"+any.getCause()
333             LOGGER.error(any.printStackTrace())
334             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
335         }
336
337     }
338
339     /**
340      * delete communication service from AAI
341      * @param execution
342      */
343     void delCSFromAAI(DelegateExecution execution)
344     {
345         try
346         {
347             LOGGER.debug("start delete communication service from AAI")
348             AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(execution.getVariable("globalSubscriberId")).serviceSubscription(execution.getVariable("serviceType")).serviceInstance(execution.getVariable("serviceInstanceId")))
349             getAAIClient().delete(serviceInstanceUri)
350
351             execution.setVariable("progress", "100")
352             execution.setVariable("result", "finished")
353             execution.setVariable("operationContent", "CSMF completes service terminated.")
354             setOperationStatus(execution)
355             LOGGER.debug("end delete communication service from AAI")
356         }
357         catch (any)
358         {
359             LOGGER.error("Error occured within delCSFromAAI method, cause: ${any.getCause()} ")
360             exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Error occured during delete communication service from aai")
361         }
362     }
363
364     void sendSyncError(DelegateExecution execution)
365     {
366         LOGGER.debug("Starting sendSyncError")
367
368         try {
369             String errorMessage = "Sending Sync Error."
370             if (execution.getVariable("WorkflowException") instanceof WorkflowException) {
371                 WorkflowException wfe = execution.getVariable("WorkflowException")
372                 errorMessage = wfe.getErrorMessage()
373             }
374
375             String buildworkflowException =
376                     """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
377                                         <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
378                                         <aetgt:ErrorCode>7000</aetgt:ErrorCode>
379                                    </aetgt:WorkflowException>"""
380
381             LOGGER.debug(buildworkflowException)
382             sendWorkflowResponse(execution, 500, buildworkflowException)
383
384         } catch (Exception ex) {
385             LOGGER.error("Sending Sync Error Activity Failed. " + "\n" + ex.getMessage())
386         }
387     }
388
389     /**
390      * prepare update operation status
391      * @param execution
392      */
393     void preFailedOperationStatus(DelegateExecution execution)
394     {
395         LOGGER.debug(" ======== STARTED preFailedOperationStatus Process ======== ")
396
397         execution.setVariable("progress", "100")
398         execution.setVariable("result", "error")
399         execution.setVariable("operationContent", "terminate service failure")
400
401         WorkflowException wfex = execution.getVariable("WorkflowException") as WorkflowException
402         String errorMessage = wfex.getErrorMessage()
403         errorMessage = errorMessage.length() > 200 ? errorMessage.substring(0,200) + "......" : errorMessage
404         execution.setVariable("reason", errorMessage)
405         setOperationStatus(execution)
406
407         LOGGER.debug("======== COMPLETED prepareEndOperationStatus Process ======== ")
408     }
409
410     /**
411      * prepare Operation status
412      * @param execution
413      * @param operationType
414      */
415     private void setOperationStatus(DelegateExecution execution)
416     {
417         OperationStatus operationStatus = new OperationStatus()
418         operationStatus.setServiceId(execution.getVariable("serviceInstanceId"))
419         operationStatus.setOperationId(execution.getVariable("operationId"))
420         operationStatus.setUserId(execution.getVariable("globalSubscriberId"))
421         //interface not support update
422         operationStatus.setServiceName(execution.getVariable("serviceInstanceName"))
423         operationStatus.setResult(execution.getVariable("result"))
424         operationStatus.setProgress(execution.getVariable("progress"))
425         operationStatus.setOperationContent(execution.getVariable("operationContent"))
426         operationStatus.setReason(execution.getVariable("reason")?:"")
427         operationStatus.setOperation("DELETE")
428
429         requestDBUtil.prepareUpdateOperationStatus(execution, operationStatus)
430     }
431
432     void prepareFailureStatus(DelegateExecution execution)
433     {
434         execution.setVariable("result", "finished")
435         execution.setVariable("progress", "100")
436         execution.setVariable("operationContent", "terminate service failure.")
437         setOperationStatus(execution)
438         LOGGER.debug("${PREFIX}-prepareFailureStatus,result:${execution.getVariable("result")}, reason: ${execution.getVariable("reason")}")
439     }
440
441     /**
442      * check request json and save parameter to execution
443      * @param siRequest
444      * @param paraName
445      * @param isErrorException
446      * @param execution
447      */
448     private void checkAndSetRequestParam(String siRequest, String paraName, boolean isErrorException, DelegateExecution execution)
449     {
450         String msg = ""
451         String paramValue = jsonUtil.getJsonValue(siRequest, paraName)
452         if (isBlank(paramValue)) {
453             msg = "Input ${paraName} is null"
454             LOGGER.error(msg)
455             if(isErrorException)
456             {
457                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
458             }
459
460         } else {
461             execution.setVariable(paraName, paramValue)
462         }
463     }
464
465 }