5c030a9f86b4d686cc2255cb44020bb3a0a99087
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2019 Huawei Technologies Co., Ltd. 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
24 import org.camunda.bpm.engine.delegate.BpmnError
25 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.onap.aai.domain.yang.*
27 import org.onap.aaiclient.client.aai.AAIResourcesClient
28 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
29 import org.onap.aaiclient.client.aai.entities.uri.AAIPluralResourceUri
30 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
31 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
32 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
33 import org.onap.logging.filter.base.ErrorCode
34 import org.onap.so.beans.nsmf.CustomerInfo
35 import org.onap.so.beans.nsmf.NetworkType
36 import org.onap.so.beans.nsmf.NssInstance
37 import org.onap.so.beans.nsmf.OperationType
38 import org.onap.so.beans.nsmf.OrchestrationStatusEnum
39 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
40 import org.onap.so.bpmn.common.scripts.ExceptionUtil
41 import org.onap.so.bpmn.common.scripts.MsoUtils
42 import org.onap.so.bpmn.common.scripts.RequestDBUtil
43 import org.onap.so.bpmn.core.WorkflowException
44 import org.onap.so.bpmn.core.json.JsonUtils
45 import org.onap.so.db.request.beans.OperationStatus
46 import org.onap.so.logger.LoggingAnchor
47 import org.onap.so.logger.MessageEnum
48 import org.slf4j.Logger
49 import org.slf4j.LoggerFactory
50
51 import javax.ws.rs.NotFoundException
52 import java.util.function.Consumer
53
54 import static org.apache.commons.lang3.StringUtils.isBlank
55
56 /**
57  * This groovy class supports the <class>ActivateSliceService.bpmn</class> process.
58  * AlaCarte flow for 1702 slice service activate
59  *
60  */
61
62 class ActivateSliceService extends AbstractServiceTaskProcessor {
63
64
65     String Prefix = "ACTSS_"
66
67     ExceptionUtil exceptionUtil = new ExceptionUtil()
68
69     JsonUtils jsonUtil = new JsonUtils()
70
71     RequestDBUtil requestDBUtil = new RequestDBUtil()
72
73     AAIResourcesClient client = getAAIClient()
74
75     private static final Logger logger = LoggerFactory.getLogger(ActivateSliceService.class)
76
77     void preProcessRequest(DelegateExecution execution) {
78         logger.debug(Prefix + "preProcessRequest Start")
79         execution.setVariable("prefix", Prefix)
80         String msg
81
82         try {
83             // check for incoming json message/input
84             String siRequest = Objects.requireNonNull(execution.getVariable("bpmnRequest"))
85             logger.debug(siRequest)
86
87             String requestId = execution.getVariable("mso-request-id")
88             execution.setVariable("msoRequestId", requestId)
89             logger.info("Input Request:" + siRequest + " reqId:" + requestId)
90
91             String serviceInstanceId = execution.getVariable("serviceInstanceId")
92             if (isBlank(serviceInstanceId)) {
93                 msg = "Input serviceInstanceId' is null"
94                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
95             }
96             String source = jsonUtil.getJsonValue(siRequest, "source")
97             execution.setVariable("source", source)
98
99             //subscriberInfo
100             String globalSubscriberId = jsonUtil.getJsonValue(siRequest, "globalSubscriberId")
101             if (isBlank(globalSubscriberId)) {
102                 msg = "Input globalSubscriberId' is null"
103                 logger.info(msg)
104                 execution.setVariable("globalSubscriberId", "5GCustomer")
105             } else {
106                 execution.setVariable("globalSubscriberId", globalSubscriberId)
107             }
108
109             //requestParameters
110             String subscriptionServiceType = jsonUtil.getJsonValue(siRequest, "serviceType")
111             if (isBlank(subscriptionServiceType)) {
112                 msg = "Input subscriptionServiceType is null"
113                 logger.debug(msg)
114                 execution.setVariable("subscriptionServiceType", "5G")
115             } else {
116                 execution.setVariable("subscriptionServiceType", subscriptionServiceType)
117             }
118             String operationId = Objects.requireNonNull(jsonUtil.getJsonValue(siRequest, "operationId"))
119             execution.setVariable("operationId", operationId)
120
121             String operationType = Objects.requireNonNull(execution.getVariable("operationType"))
122             logger.info("operationType is " + execution.getVariable("operationType") )
123
124             CustomerInfo customerInfo = CustomerInfo.builder().operationId(operationId)
125                     .operationType(Objects.requireNonNull(OperationType.getOperationType(operationType)))
126                     .globalSubscriberId(globalSubscriberId).serviceInstanceId(serviceInstanceId)
127                     .subscriptionServiceType(subscriptionServiceType)
128                     .build()
129
130             execution.setVariable("customerInfo", customerInfo)
131
132         } catch (BpmnError e) {
133             throw e
134         } catch (Exception ex) {
135             msg = "Exception in preProcessRequest " + ex.getMessage()
136             logger.info(msg)
137             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
138         }
139         logger.debug(Prefix + "preProcessRequest Exit")
140     }
141
142     /**
143      * Init the service Operation Status
144      */
145     def prepareInitServiceOperationStatus = { DelegateExecution execution ->
146         logger.debug(Prefix + "prepareActivateServiceOperationStatus Start")
147         try {
148             CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
149             String serviceId = customerInfo.getServiceInstanceId()
150             String operationId = customerInfo.getOperationId()
151             String operationType = customerInfo.getOperationType().getType()
152             String userId = customerInfo.getGlobalSubscriberId()
153             String result = "processing"
154             String progress = "0"
155             String reason = ""
156             String operationContent = "Prepare service activation"
157
158             execution.setVariable("e2eserviceInstanceId", serviceId)
159             //execution.setVariable("operationType", operationType)
160
161             OperationStatus initStatus = new OperationStatus()
162             initStatus.setServiceId(serviceId)
163             initStatus.setOperationId(operationId)
164             initStatus.setOperation(operationType)
165             initStatus.setUserId(userId)
166             initStatus.setResult(result)
167             initStatus.setProgress(progress)
168             initStatus.setReason(reason)
169             initStatus.setOperationContent(operationContent)
170
171             requestDBUtil.prepareUpdateOperationStatus(execution, initStatus)
172
173         } catch (Exception e) {
174             logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
175                     "Exception Occured Processing prepareInitServiceOperationStatus.", "BPMN",
176                     ErrorCode.UnknownError.getValue(), "Exception is:\n" + e)
177             execution.setVariable("CVFMI_ErrorResponse",
178                     "Error Occurred during prepareInitServiceOperationStatus Method:\n" + e.getMessage())
179         }
180         logger.debug(Prefix + "prepareInitServiceOperationStatus Exit")
181     }
182
183
184     def sendSyncResponse = { DelegateExecution execution ->
185         logger.debug(Prefix + "sendSyncResponse Start")
186         try {
187             CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
188             String operationId = customerInfo.getOperationId()
189
190             // RESTResponse for API Handler (APIH) Reply Task
191             String Activate5GsliceServiceRestRequest = """{"operationId":"${operationId}"}""".trim()
192             logger.debug(" sendSyncResponse to APIH:" + "\n" + Activate5GsliceServiceRestRequest)
193
194             sendWorkflowResponse(execution, 202, Activate5GsliceServiceRestRequest)
195             execution.setVariable("sentSyncResponse", true)
196         } catch (Exception ex) {
197             String msg = "Exceptuion in sendSyncResponse:" + ex.getMessage()
198             logger.debug(msg)
199             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
200         }
201         logger.debug(Prefix + "sendSyncResponse Exit")
202     }
203
204
205     public sendSyncError = { DelegateExecution execution ->
206         logger.debug("sendSyncError Start")
207         try {
208             String errorMessage
209             if (execution.getVariable("WorkflowException") instanceof WorkflowException) {
210                 WorkflowException wfe = execution.getVariable("WorkflowException") as WorkflowException
211                 errorMessage = wfe.getErrorMessage()
212             } else {
213                 errorMessage = "Sending Sync Error."
214             }
215
216             String buildWorkflowException =
217                     """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
218                                         <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
219                                         <aetgt:ErrorCode>7000</aetgt:ErrorCode>
220                                    </aetgt:WorkflowException>"""
221
222             logger.debug(buildWorkflowException)
223             sendWorkflowResponse(execution, 500, buildWorkflowException)
224
225         } catch (Exception ex) {
226             logger.debug("Sending Sync Error Activity Failed. " + "\n" + ex.getMessage())
227         }
228         logger.debug(Prefix + "sendSyncError Exit")
229     }
230
231     def checkAAIOrchStatusOfE2ESlice = { DelegateExecution execution ->
232         logger.debug(Prefix + "CheckAAIOrchStatus Start")
233         execution.setVariable("isContinue", "false")
234         CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
235         String msg
236         String serviceInstanceId = customerInfo.serviceInstanceId
237         String globalSubscriberId = customerInfo.globalSubscriberId
238         String subscriptionServiceType = customerInfo.subscriptionServiceType
239
240         logger.debug("serviceInstanceId: " + serviceInstanceId)
241
242         //check the e2e slice status
243         try {
244             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business()
245                     .customer(globalSubscriberId)
246                     .serviceSubscription(subscriptionServiceType)
247                     .serviceInstance(serviceInstanceId))
248
249             AAIResultWrapper wrapper = client.get(uri, NotFoundException.class)
250             Optional<ServiceInstance> si = wrapper.asBean(ServiceInstance.class)
251             ServiceInstance serviceInstance = si.orElseThrow()
252
253             boolean isContinue = handleOperation(customerInfo, serviceInstance)
254             execution.setVariable("isContinue", isContinue)
255             customerInfo.setSnssai(serviceInstance.getEnvironmentContext())
256
257             execution.setVariable("customerInfo", customerInfo)
258             execution.setVariable("ssInstance", serviceInstance)
259             execution.setVariable("ssiUri", uri)
260         } catch (BpmnError e) {
261             throw e
262         } catch (Exception ex) {
263             execution.setVariable("isContinue", "false")
264             msg = "Exception in org.onap.so.bpmn.common.scripts.CompleteMsoProcess.CheckAAIOrchStatus, " +
265                     "Requested e2eservice does not exist: " + ex.getMessage()
266             logger.info(msg)
267             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
268         }
269
270         logger.debug(Prefix + "CheckAAIOrchStatus Exit")
271     }
272
273     static boolean handleOperation(CustomerInfo customerInfo, ServiceInstance serviceInstance) {
274         OperationType operationType = customerInfo.operationType
275         OrchestrationStatusEnum status = OrchestrationStatusEnum.getStatus(Objects.requireNonNull(
276                 serviceInstance.getOrchestrationStatus()))
277
278         return ((OrchestrationStatusEnum.ACTIVATED == status && OperationType.DEACTIVATE == operationType)
279             || (OrchestrationStatusEnum.DEACTIVATED == status && OperationType.ACTIVATE == operationType))
280     }
281
282     void checkAAIOrchStatusOfAllocates(DelegateExecution execution) {
283         logger.debug(Prefix + "CheckAAIOrchStatus Start")
284         CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
285         String msg
286         String serviceInstanceId = customerInfo.serviceInstanceId
287         String globalSubscriberId = customerInfo.globalSubscriberId
288         String subscriptionServiceType = customerInfo.subscriptionServiceType
289
290         logger.debug("serviceInstanceId: " + serviceInstanceId)
291
292         //check the NSI is exist or the status of NSI is active or de-active
293         try {
294
295             //get the allotted-resources by e2e slice id
296             AAIPluralResourceUri uriAllotted = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business()
297                     .customer(globalSubscriberId)
298                     .serviceSubscription(subscriptionServiceType)
299                     .serviceInstance(serviceInstanceId)
300                     .allottedResources()
301             )
302
303             AAIResultWrapper wrapperAllotted = client.get(uriAllotted, NotFoundException.class)
304             Optional<AllottedResources> allAllotted = wrapperAllotted.asBean(AllottedResources.class)
305
306             AllottedResources allottedResources = allAllotted.get()
307             List<AllottedResource> AllottedResourceList = allottedResources.getAllottedResource()
308             if (AllottedResourceList.isEmpty()) {
309                 execution.setVariable("isContinue", "false")
310                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500,
311                         "allottedResources in aai is empty")
312             }
313             AllottedResource ar = AllottedResourceList.first()
314             String relatedLink = ar.getRelationshipList().getRelationship().first().getRelatedLink()
315             String nsiServiceId = relatedLink.substring(relatedLink.lastIndexOf("/") + 1, relatedLink.length())
316             customerInfo.setNsiId(nsiServiceId)
317             execution.setVariable("customerInfo", customerInfo)
318             logger.info("the NSI ID is:" + nsiServiceId)
319         } catch (BpmnError e) {
320             throw e
321         } catch (Exception ex) {
322             logger.info("NSI Service doesnt exist")
323             execution.setVariable("isContinue", "false")
324             msg = "Exception in org.onap.so.bpmn.common.scripts.CompleteMsoProcess.CheckAAIOrchStatus " + ex.getMessage()
325             logger.info(msg)
326             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
327         }
328         logger.debug(Prefix + "CheckAAIOrchStatus Exit")
329     }
330
331     void checkAAIOrchStatusOfNSI(DelegateExecution execution) {
332
333         logger.debug(Prefix + "CheckAAIOrchStatus Start")
334         CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
335         String msg = ""
336         String globalSubscriberId = customerInfo.globalSubscriberId
337         String subscriptionServiceType = customerInfo.subscriptionServiceType
338         String nsiServiceId = customerInfo.getNsiId()
339
340         logger.debug("network slice instance id: " + nsiServiceId)
341
342         //check the NSI is exist or the status of NSI is active or de-active
343         try {
344             //Query nsi by nsi id
345
346             //get the NSI id by e2e slice id
347             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business()
348                     .customer(globalSubscriberId)
349                     .serviceSubscription(subscriptionServiceType)
350                     .serviceInstance(nsiServiceId))
351
352             AAIResultWrapper wrapper = client.get(uri, NotFoundException.class)
353             Optional<ServiceInstance> si = wrapper.asBean(ServiceInstance.class)
354
355             ServiceInstance nsInstance = si.get()
356             if (!"nsi".equalsIgnoreCase(nsInstance.getServiceRole().toLowerCase())) {
357                 logger.info("the service id" + nsInstance.getServiceInstanceId() + "is " +
358                         nsInstance.getServiceRole())
359                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
360             }
361             execution.setVariable("nsInstance", nsInstance)
362             execution.setVariable("nsiUri", uri)
363             boolean isContinue = handleOperation(customerInfo, nsInstance)
364             execution.setVariable("isContinue", isContinue)
365
366         } catch (BpmnError e) {
367             throw e
368         } catch (Exception ex) {
369             logger.info("NSI Service doesnt exist")
370             execution.setVariable("isActivate", "false")
371             execution.setVariable("isContinue", "false")
372             msg = "Exception in org.onap.so.bpmn.common.scripts.CompleteMsoProcess.CheckAAIOrchStatus " + ex.getMessage()
373             logger.info(msg)
374             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
375         }
376         logger.debug(Prefix + "CheckAAIOrchStatus Exit")
377     }
378
379     void prepareActivation(DelegateExecution execution) {
380         logger.debug(Prefix + "prepareActivation Start")
381
382         CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
383         String globalSubscriberId = customerInfo.globalSubscriberId
384         String subscriptionServiceType = customerInfo.subscriptionServiceType
385
386         logger.debug(" ***** prepare active NSI/AN/CN/TN slice ***** ")
387
388         Queue<NssInstance> nssInstances = new LinkedList<>()
389         ServiceInstance nsInstance =
390                 execution.getVariable("nsInstance") as ServiceInstance
391         try {
392             //get the TN NSSI id by NSI id, active NSSI TN slicing
393             List<Relationship> relatedList = nsInstance.getRelationshipList().getRelationship()
394             for (Relationship relationship : relatedList) {
395                 String relatedTo = relationship.getRelatedTo()
396                 if (!"service-instance".equalsIgnoreCase(relatedTo)) {
397                     continue
398                 }
399                 String relatioshipurl = relationship.getRelatedLink()
400                 String nssiserviceid = relatioshipurl.substring(relatioshipurl.lastIndexOf("/") + 1,
401                         relatioshipurl.length())
402
403                 AAIResourceUri nsiUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business()
404                         .customer(globalSubscriberId)
405                         .serviceSubscription(subscriptionServiceType)
406                         .serviceInstance(nssiserviceid))
407                 if (!client.exists(nsiUri)) {
408                     exceptionUtil.buildAndThrowWorkflowException(execution, 2500,
409                             "Service Instance was not found in aai")
410                 }
411                 AAIResultWrapper wrapper01 = client.get(nsiUri, NotFoundException.class)
412                 Optional<ServiceInstance> nssiSi = wrapper01.asBean(ServiceInstance.class)
413                 nssiSi.ifPresent(new Consumer<ServiceInstance>() {
414                     @Override
415                     void accept(ServiceInstance instance) {
416                         String env = Objects.requireNonNull(instance.getEnvironmentContext())
417                         NssInstance nssi = NssInstance.builder().nssiId(instance.getServiceInstanceId())
418                                 .modelInvariantId(instance.getModelInvariantId())
419                                 .modelVersionId(instance.getModelVersionId())
420                                 .networkType(NetworkType.fromString(env))
421                                 .operationType(customerInfo.operationType)
422                                 .snssai(customerInfo.snssai)
423                                 .serviceType(instance.getServiceType())
424                                 .build()
425                         nssInstances.offer(nssi)
426                     }
427                 })
428             }
429             execution.setVariable("nssInstances", nssInstances)
430             execution.setVariable("nssInstanceInfos", nssInstances)
431         } catch (Exception e) {
432             String msg = "Requested service does not exist:" + e.getMessage()
433             logger.info("Service doesnt exist")
434             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
435         }
436
437         logger.debug(Prefix + "prepareActivation Exit")
438     }
439
440     void isOperationFinished(DelegateExecution execution) {
441         Queue<NssInstance> nssInstances = execution.getVariable("nssInstances") as Queue<NssInstance>
442         if (nssInstances.isEmpty()) {
443             execution.setVariable("isOperationFinished", "true")
444         }
445     }
446
447     def updateStatusSNSSAIandNSIandNSSI = { DelegateExecution execution ->
448         logger.debug(Prefix + "updateStatusSNSSAIandNSIandNSSI Start")
449         logger.debug(" ***** update SNSSAI NSI NSSI slicing ***** ")
450         ServiceInstance ssInstance = execution.getVariable("ssInstance") as ServiceInstance
451         AAIResourceUri ssUri = execution.getVariable("ssiUri") as AAIResourceUri
452
453         CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
454         OperationType operationType = customerInfo.operationType
455
456         updateStratus(execution, ssInstance, operationType, ssUri)
457         //update the nsi
458         ServiceInstance nsInstance = execution.getVariable("nsInstance") as ServiceInstance
459         AAIResourceUri nsiUri = execution.getVariable("nsiUri") as AAIResourceUri
460
461         updateStratus(execution, nsInstance, operationType, nsiUri)
462
463
464         logger.debug(Prefix + "updateStatusSNSSAIandNSIandNSSI Exit")
465     }
466
467     void updateStratus(DelegateExecution execution, ServiceInstance serviceInstance,
468                        OperationType operationType, AAIResourceUri uri) {
469
470         logger.debug(Prefix + "updateStratus Start")
471
472         try {
473             serviceInstance.setOrchestrationStatus()
474             if (OperationType.ACTIVATE == operationType) {
475                 serviceInstance.setOrchestrationStatus(OrchestrationStatusEnum.ACTIVATED.getValue())
476             } else {
477                 serviceInstance.setOrchestrationStatus(OrchestrationStatusEnum.DEACTIVATED.getValue())
478             }
479             client.update(uri, serviceInstance)
480         } catch (Exception e) {
481             logger.info("Service is already in active state")
482             String msg = "Service is already in active state, " + e.getMessage()
483             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
484         }
485
486         logger.debug(Prefix + "updateStratus Exit")
487     }
488
489     def prepareCompletionRequest = { DelegateExecution execution ->
490         logger.debug(Prefix + "prepareCompletionRequest Start")
491         CustomerInfo customerInfo = execution.getVariable("customerInfo") as CustomerInfo
492         String serviceId = customerInfo.getServiceInstanceId()
493         String operationId = customerInfo.getOperationId()
494         String userId = customerInfo.getGlobalSubscriberId()
495
496         String result = "finished"
497         String progress = "100"
498         String reason = ""
499         String operationContent = "action finished success"
500         String operationType = customerInfo.operationType.getType()
501
502         OperationStatus initStatus = new OperationStatus()
503         initStatus.setServiceId(serviceId)
504         initStatus.setOperationId(operationId)
505         initStatus.setOperation(operationType)
506         initStatus.setUserId(userId)
507         initStatus.setResult(result)
508         initStatus.setProgress(progress)
509         initStatus.setReason(reason)
510         initStatus.setOperationContent(operationContent)
511
512         requestDBUtil.prepareUpdateOperationStatus(execution, initStatus)
513
514         logger.debug(Prefix + "prepareCompletionRequest Exit")
515     }
516 }