Bug fixes for modify TN NSSI operation
[so.git] / bpmn / so-bpmn-infrastructure-common / src / main / groovy / org / onap / so / bpmn / infrastructure / scripts / DoModifyTnNssi.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2020 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 import com.fasterxml.jackson.databind.ObjectMapper
24 import groovy.json.JsonSlurper
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.onap.aai.domain.yang.*
28 import org.onap.aaiclient.client.aai.AAIResourcesClient
29 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
30 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
31 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
32 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types
33 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
34 import org.onap.so.bpmn.common.scripts.ExceptionUtil
35 import org.onap.so.bpmn.common.scripts.RequestDBUtil
36 import org.onap.so.bpmn.core.json.JsonUtils
37 import org.onap.so.db.request.beans.ResourceOperationStatus
38 import org.slf4j.Logger
39 import org.slf4j.LoggerFactory
40
41 import static org.apache.commons.lang3.StringUtils.*
42
43 public class DoModifyTnNssi extends AbstractServiceTaskProcessor {
44     String Prefix = "TNMOD_"
45
46     ExceptionUtil exceptionUtil = new ExceptionUtil()
47     JsonUtils jsonUtil = new JsonUtils()
48     RequestDBUtil requestDBUtil = new RequestDBUtil()
49     TnNssmfUtils tnNssmfUtils = new TnNssmfUtils()
50     JsonSlurper jsonSlurper = new JsonSlurper()
51     ObjectMapper objectMapper = new ObjectMapper()
52     private static final Logger logger = LoggerFactory.getLogger(DoModifyTnNssi.class)
53
54
55     void preProcessRequest(DelegateExecution execution) {
56         logger.debug("Start preProcessRequest")
57         execution.setVariable("prefix", Prefix)
58         String msg = ""
59
60         try {
61             execution.setVariable("startTime", System.currentTimeMillis())
62             msg = tnNssmfUtils.getExecutionInputParams(execution)
63             logger.debug("Modify TN NSSI input parameters: " + msg)
64
65             execution.setVariable("prefix", Prefix)
66
67             tnNssmfUtils.setSdncCallbackUrl(execution, true)
68             logger.debug("SDNC Callback URL: " + execution.getVariable("sdncCallbackUrl"))
69
70             String additionalPropJsonStr = execution.getVariable("sliceParams")
71             if (isBlank(additionalPropJsonStr)) {
72                 msg = "ERROR: additionalPropJsonStr is null"
73                 logger.debug(msg)
74                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
75             }
76
77             String sliceServiceInstanceId = execution.getVariable("serviceInstanceID")
78             if (isBlank(sliceServiceInstanceId)) {
79                 msg = "ERROR: sliceServiceInstanceId is null"
80                 logger.debug(msg)
81                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
82             }
83             execution.setVariable("sliceServiceInstanceId", sliceServiceInstanceId)
84
85             String sliceServiceInstanceName = execution.getVariable("servicename")
86             execution.setVariable("sliceServiceInstanceName", sliceServiceInstanceName)
87
88             String operationId = UUID.randomUUID().toString()
89             execution.setVariable("operationId", operationId)
90
91             String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
92             String modelUuid = execution.getVariable("modelUuid")
93             if (isEmpty(modelUuid)) {
94                 modelUuid = tnNssmfUtils.getModelUuidFromServiceInstance(execution.getVariable("serviceInstanceID"))
95             }
96
97             def isDebugLogEnabled = true
98             execution.setVariable("isDebugLogEnabled", isDebugLogEnabled)
99             String serviceModelInfo = """{
100             "modelInvariantUuid":"${modelInvariantUuid}",
101             "modelUuid":"${modelUuid}",
102             "modelVersion":""
103              }"""
104             execution.setVariable("serviceModelInfo", serviceModelInfo)
105
106             tnNssmfUtils.setExecVarFromJsonStr(execution, additionalPropJsonStr,
107                     "sliceProfile", "sliceProfile", true)
108
109             tnNssmfUtils.setExecVarFromJsonStr(execution, additionalPropJsonStr,
110                     "transportSliceNetworks", "transportSliceNetworks", true)
111             logger.debug("transportSliceNetworks: " + execution.getVariable("transportSliceNetworks"))
112
113             tnNssmfUtils.setExecVarFromJsonStr(execution, additionalPropJsonStr,
114                     "nsiInfo", "nsiInfo", true)
115
116             if (isBlank(tnNssmfUtils.setExecVarFromJsonIfExists(execution, additionalPropJsonStr,
117                     "enableSdnc", "enableSdnc"))) {
118                 tnNssmfUtils.setEnableSdncConfig(execution)
119             }
120         } catch (BpmnError e) {
121             throw e
122         } catch (Exception ex) {
123             msg = "Exception in preProcessRequest " + ex.getMessage()
124             logger.debug(msg)
125             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
126         }
127         logger.debug("Finish preProcessRequest")
128     }
129
130
131     void deleteServiceInstance(DelegateExecution execution) {
132         try {
133             AAIResourcesClient client = getAAIClient()
134             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(execution.getVariable("globalSubscriberId")).serviceSubscription(execution.getVariable("subscriptionServiceType")).serviceInstance(execution.getVariable("serviceInstanceID")))
135             client.delete(uri)
136         } catch (BpmnError e) {
137             throw e
138         } catch (Exception ex) {
139             String msg = "Exception in DoDeallocateTnNssi.deleteServiceInstance. " + ex.getMessage()
140             logger.info(msg)
141             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
142         }
143     }
144
145
146     void getExistingServiceInstance(DelegateExecution execution) {
147         String serviceInstanceId = execution.getVariable("sliceServiceInstanceId")
148
149         AAIResourcesClient resourceClient = getAAIClient()
150         AAIResourceUri ssServiceuri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(serviceInstanceId))
151
152         try {
153             if (resourceClient.exists(ssServiceuri)) {
154                 ServiceInstance ss = resourceClient.get(ServiceInstance.class, ssServiceuri)
155
156                 AllottedResources ars = ss.getAllottedResources()
157                 List<AllottedResource> arList = ars.getAllottedResource()
158                 List<String> arIdList = new ArrayList<>()
159                 Map<String, String> policyMap = new HashMap<>()
160                 Map<String, List<String>> logicalLinksMap = new HashMap<>()
161                 for (AllottedResource ar : arList) {
162                     String arId = ar.getId()
163                     arIdList.add(arId)
164                     String policyId = tnNssmfUtils.getPolicyIdFromAr(execution, serviceInstanceId, arId, true)
165                     policyMap.put(arId, policyId)
166                     List<String> logicalLinkList = tnNssmfUtils.getLogicalLinkNamesFromAr(execution,
167                             serviceInstanceId, arId, true)
168                     logicalLinksMap.put(arId, logicalLinkList)
169                 }
170                 execution.setVariable("arIdList", arIdList)
171                 execution.setVariable("arPolicyMap", policyMap)
172                 execution.setVariable("arLogicalLinkMap", logicalLinksMap)
173             } else {
174                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Service instance was not found in aai to " +
175                         "associate allotted resource for service :" + serviceInstanceId)
176             }
177         } catch (BpmnError e) {
178             throw e;
179         } catch (Exception ex) {
180             String msg = "Exception in getServiceInstance. " + ex.getMessage()
181             logger.debug(msg)
182             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
183         }
184     }
185
186     void updateTnNssiInAAI(DelegateExecution execution) {
187         getExistingServiceInstance(execution)
188         updateTsciNetworks(execution)
189     }
190
191     void updateServiceInstance(DelegateExecution execution) {
192         String ssInstanceId = execution.getVariable("sliceServiceInstanceId")
193         try {
194             ServiceInstance ss = new ServiceInstance()
195             //ss.setServiceInstanceId(ssInstanceId)
196             String serviceStatus = "modified"
197             ss.setOrchestrationStatus(serviceStatus)
198             AAIResourcesClient client = getAAIClient()
199             AAIResourceUri uri = AAIUriFactory.createResourceUri(
200                     AAIFluentTypeBuilder.business()
201                             .customer(execution.getVariable("globalSubscriberId"))
202                             .serviceSubscription(execution.getVariable("subscriptionServiceType"))
203                             .serviceInstance(ssInstanceId))
204             client.update(uri, ss)
205         } catch (BpmnError e) {
206             throw e
207         } catch (Exception ex) {
208             String msg = "Exception in DoCreateTnNssiInstance.createServiceInstance. " + ex.getMessage()
209             logger.info(msg)
210             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
211         }
212     }
213
214     void updateSliceProfile(DelegateExecution execution) {
215
216         String sliceserviceInstanceId = execution.getVariable("sliceServiceInstanceId")
217         String sliceProfileStr = execution.getVariable("sliceProfile")
218         String sliceProfileId = execution.getVariable("sliceProfileId")
219         SliceProfile sliceProfile = new SliceProfile();
220         sliceProfile.setProfileId(sliceProfileId)
221         sliceProfile.setLatency(Integer.parseInt(jsonUtil.getJsonValue(sliceProfileStr, "latency")))
222         sliceProfile.setResourceSharingLevel(jsonUtil.getJsonValue(sliceProfileStr, "resourceSharingLevel"))
223         sliceProfile.setSNssai(tnNssmfUtils.getFirstSnssaiFromSliceProfile(sliceProfileStr))    //TODO: should be list
224
225         sliceProfile.setE2ELatency(Integer.parseInt(jsonUtil.getJsonValue(sliceProfileStr, "latency")))
226         sliceProfile.setMaxBandwidth(Integer.parseInt(jsonUtil.getJsonValue(sliceProfileStr, "maxBandwidth")))
227
228         //TODO: new API
229         sliceProfile.setReliability(new Object())
230         try {
231             AAIResourcesClient client = getAAIClient()
232             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(execution.getVariable("globalSubscriberId")).serviceSubscription(execution.getVariable("subscriptionServiceType")).serviceInstance(sliceserviceInstanceId).sliceProfile(sliceProfileId))
233             client.update(uri, sliceProfile)
234
235         } catch (BpmnError e) {
236             throw e
237         } catch (Exception ex) {
238             String msg = "Exception in updateSliceProfile. " + ex.getMessage()
239             logger.info(msg)
240             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
241         }
242     }
243
244     String getValidArId(DelegateExecution execution, String arIdStr) {
245         List<String> arIdList = execution.getVariable("arIdList")
246         /*
247          * If arId is not specified by the caller, then we assume the caller
248          * wants to modify the first network (i.e., allotted resource) in the TSCi tree.
249          */
250         String arId = isBlank(arIdStr) ? arIdList.get(0) : arIdStr
251
252         return arId
253     }
254
255     void updateLogicalLinksInAr(DelegateExecution execution, String arId, String linkArrayJsonStr) {
256         try {
257             String serviceInstanceId = execution.getVariable('sliceServiceInstanceId')
258
259             /*
260              * Each TSCi connection-link in linkArrayJsonStr is considered as an "ADD" new
261              * link to allotted-resource. So, if the link already exists under AR, then do
262              * nothing. Otherwise, create logical-link.
263              */
264             List<String> linkStrList = jsonUtil.StringArrayToList(linkArrayJsonStr)
265             for (String linkStr : linkStrList) {
266                 if (logicalLinkExists(execution, arId, linkStr)) {
267                     continue
268                 }
269
270                 createLogicalLinkForAllocatedResource(execution, linkStr, serviceInstanceId, arId)
271             }
272         } catch (BpmnError e) {
273             throw e
274         } catch (Exception ex) {
275             exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
276                     "Exception in updateLogicalLinksInAr" + ex.getMessage())
277         }
278     }
279
280     void updateLogicalLinksInNetwork(DelegateExecution execution, String networkJsonStr) {
281         try {
282             String arId = getValidArId(jsonUtil.getJsonValue(networkJsonStr, "id"))
283             String linkArrayStr = jsonUtil.getJsonValue(networkJsonStr, "connectionLinks")
284             updateLogicalLinksInAr(execution, arId, linkArrayStr)
285         } catch (BpmnError e) {
286             throw e
287         } catch (Exception ex) {
288             exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
289                     "Exception in updateLogicalLinksInNetwork" + ex.getMessage())
290         }
291     }
292
293     void updateTsciNetworks(DelegateExecution execution) {
294         try {
295             List<String> networkStrList = jsonUtil.StringArrayToList(execution.getVariable("transportSliceNetworks"))
296             for (String networkStr : networkStrList) {
297                 updateLogicalLinksInNetwork(execution, networkStr)
298                 updateNetworkPolicy(execution, networkStr)
299             }
300
301         } catch (BpmnError e) {
302             throw e
303         } catch (Exception ex) {
304             exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
305                     "Exception in updateTsciNetworks" + ex.getMessage())
306         }
307     }
308
309     int getMaxBw(DelegateExecution execution) {
310         int maxBw = 0
311         try {
312             String sliceProfileStr = execution.getVariable("sliceProfile")
313             if (isBlank(sliceProfileStr)) {
314                 String msg = "ERROR: getMaxBw: sliceProfile is null"
315                 logger.error(msg)
316                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
317             }
318             String bwStr = jsonUtil.getJsonValue(sliceProfileStr, "maxBandwidth")
319             if (isNotBlank(bwStr)) {
320                 maxBw = Integer.parseInt(bwStr)
321             } else {
322                 logger.error("ERROR: getMaxBw: maxBandwidth is null")
323             }
324         } catch (BpmnError e) {
325             throw e
326         } catch (Exception ex) {
327             exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
328                     "Exception in getMaxBw" + ex.getMessage())
329         }
330
331         return maxBw
332     }
333
334     void updatePolicyMaxBandwidthInAAI(DelegateExecution execution, String policyId, int maxBw) {
335         try {
336             NetworkPolicy networkPolicy = new NetworkPolicy()
337             networkPolicy.setMaxBandwidth(maxBw)
338             AAIResourceUri networkPolicyUri =
339                     AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().networkPolicy(policyId))
340             getAAIClient().update(networkPolicyUri, networkPolicy)
341         } catch (BpmnError e) {
342             throw e
343         } catch (Exception ex) {
344             String msg = "Exception in DoCreateTnNssiInstance.createServiceInstance. " + ex.getMessage()
345             logger.info(msg)
346             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
347         }
348     }
349
350     void updateNetworkPolicy(DelegateExecution execution, String networkJsonStr) {
351         try {
352             int maxBw = getMaxBw(execution)
353
354             String arId = getValidArId(jsonUtil.getJsonValue(networkJsonStr, "id"))
355             Map<String, String> policyMap = execution.getVariable("arPolicyMap")
356             String policyId = policyMap.get(arId)
357             if (isBlank(policyId)) {
358                 String msg = String.format("ERROR: updateNetworkPolicy: policyId not found. arId=%s", arId)
359                 logger.error(msg)
360                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
361             }
362
363             updatePolicyMaxBandwidthInAAI(execution, policyId, maxBw)
364
365         } catch (BpmnError e) {
366             throw e
367         } catch (Exception ex) {
368             exceptionUtil.buildAndThrowWorkflowException(execution, 7000,
369                     "Exception in updateNetworkPolicy" + ex.getMessage())
370         }
371     }
372
373
374     void createLogicalLinkForAllocatedResource(DelegateExecution execution,
375                                                String linkJsonStr, String ssInstanceId,
376                                                String allottedResourceId) {
377         try {
378             AAIResourceUri allottedResourceUri = tnNssmfUtils.buildAllottedResourceUri(execution,
379                     ssInstanceId, allottedResourceId)
380
381             if (!getAAIClient().exists(allottedResourceUri)) {
382                 logger.info("ERROR: createLogicalLinksForAllocatedResource: allottedResource not exist: uri={}",
383                         allottedResourceUri)
384                 return
385             }
386
387             String linkId = jsonUtil.getJsonValue(linkJsonStr, "id")
388             if (isBlank(linkId)) {
389                 linkId = "tn-nssmf-" + UUID.randomUUID().toString()
390             }
391             logger.debug("createLogicalLinkForAllocatedResource: linkId=" + linkId)
392
393             String epA = jsonUtil.getJsonValue(linkJsonStr, "transportEndpointA")
394             String epB = jsonUtil.getJsonValue(linkJsonStr, "transportEndpointB")
395             String modelInvariantId = execution.getVariable("modelInvariantUuid")
396             String modelVersionId = execution.getVariable("modelUuid")
397
398             org.onap.aai.domain.yang.LogicalLink resource = new org.onap.aai.domain.yang.LogicalLink()
399             resource.setLinkId(linkId)
400             resource.setLinkName(epA)
401             resource.setLinkName2(epB)
402             resource.setLinkType("TsciConnectionLink")
403             resource.setInMaint(false)
404
405             //epA is link-name
406             AAIResourceUri logicalLinkUri =
407                     AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.network().logicalLink(epA))
408             getAAIClient().create(logicalLinkUri, resource)
409
410             tnNssmfUtils.attachLogicalLinkToAllottedResource(execution, tnNssmfUtils.AAI_VERSION,
411                     allottedResourceUri, epA);
412         } catch (BpmnError e) {
413             throw e
414         } catch (Exception ex) {
415             String msg = "Exception in DoCreateTnNssiInstance.createLogicalLinksForAllocatedResource: " + ex.getMessage()
416             logger.error(msg)
417             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
418         }
419     }
420
421
422     void preprocessSdncModifyTnNssiRequest(DelegateExecution execution) {
423         def method = getClass().getSimpleName() + '.preprocessSdncModifyTnNssiRequest(' +
424                 'execution=' + execution.getId() + ')'
425         def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
426         logger.trace('Entered ' + method)
427
428         try {
429             String serviceInstanceId = execution.getVariable("sliceServiceInstanceId")
430
431             String sdncRequest = tnNssmfUtils.buildSDNCRequest(execution, serviceInstanceId, "modify")
432
433             execution.setVariable("TNNSSMF_SDNCRequest", sdncRequest)
434             logger.debug("Outgoing SDNCRequest is: \n" + sdncRequest)
435
436         } catch (BpmnError e) {
437             throw e
438         } catch (Exception e) {
439             logger.debug("Exception Occured Processing preprocessSdncModifyTnNssiRequest. Exception is:\n" + e)
440             exceptionUtil.buildAndThrowWorkflowException(execution, 1002, "Error Occured during  preProcessSDNCActivateRequest Method:\n" + e.getMessage())
441         }
442         logger.trace("COMPLETED preprocessSdncModifyTnNssiRequest Process")
443     }
444
445
446     void validateSDNCResponse(DelegateExecution execution, String response, String method) {
447         tnNssmfUtils.validateSDNCResponse(execution, response, method)
448     }
449
450
451     void updateAAIOrchStatus(DelegateExecution execution) {
452         logger.debug("Start updateAAIOrchStatus")
453         String sliceServiceInstanceId = execution.getVariable("sliceServiceInstanceId")
454         String orchStatus = execution.getVariable("orchestrationStatus")
455
456         try {
457             ServiceInstance si = new ServiceInstance()
458             si.setOrchestrationStatus(orchStatus)
459             AAIResourcesClient client = getAAIClient()
460             AAIResourceUri uri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(sliceServiceInstanceId))
461             client.update(uri, si)
462         } catch (BpmnError e) {
463             throw e
464         } catch (Exception ex) {
465             String msg = "Exception in CreateSliceService.updateAAIOrchStatus " + ex.getMessage()
466             logger.info(msg)
467             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
468         }
469
470         logger.debug("Finish updateAAIOrchStatus")
471     }
472
473     void prepareUpdateJobStatus(DelegateExecution execution,
474                                 String status,
475                                 String progress,
476                                 String statusDescription) {
477         String ssInstanceId = execution.getVariable("sliceServiceInstanceId")
478         String modelUuid = execution.getVariable("modelUuid")
479         String jobId = execution.getVariable("jobId")
480         String nsiId = execution.getVariable("nsiId")
481         String operType = "MODIFY"
482
483         ResourceOperationStatus roStatus = tnNssmfUtils.buildRoStatus(modelUuid, ssInstanceId,
484                 jobId, nsiId, operType, status, progress, statusDescription)
485
486         requestDBUtil.prepareUpdateResourceOperationStatus(execution, roStatus)
487     }
488
489     boolean logicalLinkExists(DelegateExecution execution, String arIdStr, String linkJsonStr) {
490         if (isBlank(arIdStr)) {
491             logger.error("ERROR: logicalLinkExists: arIdStr is empty")
492             return false
493         }
494         if (isBlank(linkJsonStr)) {
495             logger.error("ERROR: logicalLinkExists: linkJsonStr is empty")
496             return false
497         }
498
499         Map<String, List<String>> logicalLinksMap = execution.getVariable("arLogicalLinkMap")
500         if (logicalLinksMap == null) {
501             logger.error("ERROR: logicalLinkExists: logicalLinksMap is null")
502             return false
503         }
504
505         List<String> logicalLinkNameList = logicalLinksMap.get(arIdStr)
506         if (logicalLinksMap == null) {
507             logger.error("ERROR: logicalLinkExists: logicalLinkNameList is null. arIdStr=" + arIdStr)
508             return false
509         }
510
511         String linkName = jsonUtil.getJsonValue(linkJsonStr, "transportEndpointA")
512         if (isBlank(linkName)) {
513             logger.error("ERROR: logicalLinkExists: epA is empty")
514             return false
515         }
516
517         return logicalLinkNameList.contains(linkName)
518     }
519 }
520