Support Activate,Deactivate and Terminate feature for NSMF based TN slices
[so.git] / bpmn / so-bpmn-infrastructure-common / src / main / groovy / org / onap / so / bpmn / infrastructure / scripts / DoDeallocateNSSI.groovy
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 import com.fasterxml.jackson.databind.ObjectMapper
23 import org.camunda.bpm.engine.delegate.DelegateExecution
24 import org.onap.aai.domain.yang.SliceProfiles
25 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
26 import org.onap.aaiclient.client.aai.entities.uri.AAIPluralResourceUri
27 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
28 import org.onap.aaiclient.client.aai.entities.uri.AAISimpleUri
29 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
30 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
31 import org.onap.so.beans.nsmf.*
32 import org.onap.so.beans.nsmf.oof.SubnetType
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.NssmfAdapterUtils
36 import org.onap.so.bpmn.common.scripts.RequestDBUtil
37 import org.onap.so.bpmn.core.domain.ServiceDecomposition
38 import org.onap.so.bpmn.core.json.JsonUtils
39 import org.onap.so.db.request.beans.OperationStatus
40 import org.slf4j.Logger
41 import org.slf4j.LoggerFactory
42
43 import javax.ws.rs.NotFoundException
44
45 class DoDeallocateNSSI extends AbstractServiceTaskProcessor
46 {
47     private final String PREFIX ="DoDeallocateNSSI"
48
49     private ExceptionUtil exceptionUtil = new ExceptionUtil()
50     private JsonUtils jsonUtil = new JsonUtils()
51     ObjectMapper objectMapper = new ObjectMapper()
52     private RequestDBUtil requestDBUtil = new RequestDBUtil()
53     private NssmfAdapterUtils nssmfAdapterUtils = new NssmfAdapterUtils(httpClientFactory, jsonUtil)
54
55     private static final Logger LOGGER = LoggerFactory.getLogger( DoDeallocateNSSI.class)
56
57     @Override
58     void preProcessRequest(DelegateExecution execution) {
59         LOGGER.trace(" ***** ${PREFIX} Start preProcessRequest *****")
60
61         def currentNSSI = execution.getVariable("currentNSSI")
62         if (!currentNSSI) {
63             String msg = "currentNSSI is null"
64             LOGGER.error(msg)
65             exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
66         }
67
68         LOGGER.trace("***** ${PREFIX} Exit preProcessRequest *****")
69     }
70
71     /**
72      *
73      * @param execution
74      */
75     void prepareDecomposeService(DelegateExecution execution)
76     {
77         LOGGER.trace(" *****${PREFIX} Start prepareDecomposeService *****")
78         try
79         {
80             def currentNSSI = execution.getVariable("currentNSSI")
81             String modelInvariantUuid = currentNSSI['modelInvariantId']
82             String modelVersionId = currentNSSI['modelVersionId']
83             String serviceModelInfo = """{
84             "modelInvariantUuid":"${modelInvariantUuid}",
85             "modelUuid":"${modelVersionId}",
86             "modelVersion":""
87              }"""
88             execution.setVariable("serviceModelInfo", serviceModelInfo)
89         }
90         catch (any)
91         {
92             String exceptionMessage = "Bpmn error encountered in deallocate nssi. Unexpected Error from method prepareDecomposeService() - " + any.getMessage()
93             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
94         }
95         LOGGER.debug(" ***** ${PREFIX} Exit prepareDecomposeService *****")
96     }
97
98     /**
99      * get vendor Info
100      * @param execution
101      */
102     void processDecomposition(DelegateExecution execution) {
103         LOGGER.debug("*****${PREFIX} start processDecomposition *****")
104
105         try {
106             ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition") as ServiceDecomposition
107             String vendor = serviceDecomposition.getServiceRole()
108             NetworkType domainType = convertServiceCategory(serviceDecomposition.getServiceCategory())
109
110             def currentNSSI = execution.getVariable("currentNSSI")
111             currentNSSI['vendor'] = vendor
112             currentNSSI['domainType'] = domainType
113             LOGGER.info("processDecomposition, current vendor-domainType:" +String.join("-", vendor, domainType.toString()))
114
115         } catch (any) {
116             String exceptionMessage = "Bpmn error encountered in deallocate nssi. processDecomposition() - " + any.getMessage()
117             LOGGER.debug(exceptionMessage)
118             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
119         }
120         LOGGER.debug("*****${PREFIX} Exit processDecomposition *****")
121     }
122
123
124     /**
125      * get subnetType from serviceCategory
126      * @return
127      */
128     private NetworkType convertServiceCategory(String serviceCategory){
129         if(serviceCategory ==~ /CN.*/){
130             return SubnetType.CN.getNetworkType()
131         }
132         if (serviceCategory ==~ /AN.*/){
133             return SubnetType.AN.getNetworkType()
134         }
135         if (serviceCategory ==~ /TN.*BH.*/){
136             return SubnetType.TN_BH.getNetworkType()
137         }
138         if(serviceCategory ==~ /TN.*MH.*/){
139             return SubnetType.TN_MH.getNetworkType()
140         }
141         if(serviceCategory ==~ /TN.*FH.*/){
142             return SubnetType.TN_FH.getNetworkType()
143         }
144         return null
145     }
146     
147     /**
148      * send deallocate request to nssmf
149      * @param execution
150      */
151     void sendRequestToNSSMF(DelegateExecution execution)
152     {
153         LOGGER.debug("*****${PREFIX} start sendRequestToNSSMF *****")
154         def currentNSSI = execution.getVariable("currentNSSI")
155         String snssai= currentNSSI['snssai']
156         String profileId = currentNSSI['profileId']
157         String nssiId = currentNSSI['nssiServiceInstanceId']
158         String nsiId = currentNSSI['nsiServiceInstanceId']
159         String scriptName = execution.getVariable("scriptName")
160
161         String serviceInvariantUuid = currentNSSI['modelInvariantId']
162         String serviceUuid = currentNSSI['modelVersionId']
163         String globalSubscriberId = currentNSSI['globalSubscriberId']
164         String subscriptionServiceType = currentNSSI['serviceType']
165         
166         DeAllocateNssi deAllocateNssi = new DeAllocateNssi()
167         deAllocateNssi.setNsiId(nsiId)
168         deAllocateNssi.setNssiId(nssiId)
169         deAllocateNssi.setTerminateNssiOption(0)
170         deAllocateNssi.setSnssaiList(Arrays.asList(snssai))
171         deAllocateNssi.setScriptName(scriptName)
172         deAllocateNssi.setSliceProfileId(profileId)
173         
174         ServiceInfo serviceInfo = new ServiceInfo()
175         serviceInfo.setServiceInvariantUuid(serviceInvariantUuid)
176         serviceInfo.setServiceUuid(serviceUuid)
177         serviceInfo.setNsiId(nsiId)
178         serviceInfo.setNssiId(nssiId)
179         serviceInfo.setGlobalSubscriberId(globalSubscriberId)
180         serviceInfo.setSubscriptionServiceType(subscriptionServiceType)
181         String serviceInfoString = objectMapper.writeValueAsString(serviceInfo)
182         
183         EsrInfo esrInfo = getEsrInfo(currentNSSI)
184         String esrInfoString = objectMapper.writeValueAsString(esrInfo)
185         
186         execution.setVariable("deAllocateNssi",deAllocateNssi)
187         execution.setVariable("esrInfo", esrInfoString)
188         execution.setVariable("serviceInfo", serviceInfoString)
189         String nssmfRequest = """
190                 {
191                   "deAllocateNssi": ${objectMapper.writeValueAsString(deAllocateNssi)},
192                   "esrInfo":  ${esrInfoString},
193                   "serviceInfo": ${serviceInfoString}
194                 }
195               """
196
197         String urlStr = String.format("/api/rest/provMns/v1/NSS/SliceProfiles/%s", profileId)
198
199         NssiResponse nssmfResponse = nssmfAdapterUtils.sendPostRequestNSSMF(execution, urlStr, nssmfRequest, NssiResponse.class)
200         if (nssmfResponse != null) {
201             currentNSSI['jobId']= nssmfResponse.getJobId() ?: "" 
202             currentNSSI['jobProgress'] = 0            
203             execution.setVariable("currentNSSI", currentNSSI)    
204         } else {
205             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Received a Bad Response from NSSMF.")
206         }
207         LOGGER.debug("*****${PREFIX} Exit sendRequestToNSSMF *****")
208     }
209
210 /**
211      * send to nssmf query progress
212      * @param execution
213      */
214     void prepareJobStatusRequest(DelegateExecution execution)
215     {
216         def currentNSSI = execution.getVariable("currentNSSI")
217         String jobId = currentNSSI['jobId']
218         execution.setVariable("jobId", jobId)
219     }
220
221     
222     /**
223      * send to nssmf query progress
224      * @param execution
225      */
226     void handleJobStatus(DelegateExecution execution)
227     {
228         try 
229         {
230         String jobStatusResponse = execution.getVariable("responseDescriptor")
231         String status = jsonUtil.getJsonValue(jobStatusResponse,"status")
232         def statusDescription = jsonUtil.getJsonValue(jobStatusResponse,"statusDescription")
233         def progress = jsonUtil.getJsonValue(jobStatusResponse,"progress")
234         if(!status.equalsIgnoreCase("failed"))
235         {
236             if(!progress)
237             {
238                 LOGGER.error("job progress is null or empty!")
239                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Received a Bad Job progress from NSSMF.")
240             }
241             def currentNSSI = execution.getVariable("currentNSSI")
242             int oldProgress = currentNSSI['jobProgress']
243             int currentProgress = Integer.parseInt(progress)
244
245             execution.setVariable("isNSSIDeAllocated", (currentProgress == 100))
246             execution.setVariable("isNeedUpdateDB", (oldProgress != currentProgress))
247             currentNSSI['jobProgress'] = currentProgress
248             currentNSSI['status'] = status
249             currentNSSI['statusDescription'] = statusDescription
250
251             String nssiId = currentNSSI['nssiServiceInstanceId']
252             String nsiId = currentNSSI['nsiServiceInstanceId']
253             LOGGER.debug("job status result: nsiId = ${nsiId}, nssiId=${nssiId}, oldProgress=${oldProgress}, progress = ${currentProgress}" )
254         }
255           else {
256             execution.setVariable("isNeedUpdateDB", "true")
257             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Received a Bad Response from NSSMF.")
258         }
259         }
260         catch (any)
261         {
262             String msg = "Received a Bad Response from NSSMF. cause-"+any.getCause()
263             LOGGER.error(any.printStackTrace())
264             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
265         }
266     }
267
268     private EsrInfo getEsrInfo(def currentNSSI)
269     {
270         NetworkType domainType = currentNSSI['domainType']
271         String vendor = currentNSSI['vendor']
272         
273         EsrInfo info = new EsrInfo()
274         info.setNetworkType(domainType)
275         info.setVendor(vendor)
276         return info
277     }
278
279  /**
280      * handle job status
281      * prepare update requestdb
282      * @param execution
283      */
284     void prepareUpdateOperationStatus(DelegateExecution execution)
285     {
286         def currentNSSI = execution.getVariable("currentNSSI")
287         int currentProgress = currentNSSI["jobProgress"]
288         def proportion = currentNSSI['proportion']
289         int progress = (currentProgress as int) == 0 ? 0 : (currentProgress as int) / 100 * (proportion as int)
290         def status = currentNSSI['status']
291
292
293         OperationStatus operationStatus = new OperationStatus()
294         operationStatus.setServiceId(currentNSSI['e2eServiceInstanceId'] as String)
295         operationStatus.setOperationId(currentNSSI['operationId'] as String)
296         operationStatus.setOperation("DELETE")
297         operationStatus.setResult("processing")
298         operationStatus.setProgress(progress as String)
299         operationStatus.setOperationContent(currentNSSI['domainType'].toString() + " " + status.toString())
300         requestDBUtil.prepareUpdateOperationStatus(execution, operationStatus)
301         LOGGER.debug("update operation, currentProgress=${currentProgress}, proportion=${proportion}, progress = ${progress}" )
302     }
303     
304     /**
305      * delete slice profile from aai
306      * @param execution
307      */
308     void delSliceProfileServiceFromAAI(DelegateExecution execution)
309     {
310         LOGGER.debug("*****${PREFIX} start delSliceProfileFromAAI *****")
311         def currentNSSI = execution.getVariable("currentNSSI")
312         String nssiServiceInstanceId = currentNSSI['nssiServiceInstanceId']
313         String profileId = currentNSSI['profileId']
314         String globalSubscriberId = currentNSSI["globalSubscriberId"]
315         String serviceType = currentNSSI['serviceType']
316
317         try
318         {
319             LOGGER.debug("delete nssiServiceInstanceId:${nssiServiceInstanceId}, profileId:${profileId}")
320             AAIResourceUri resourceUri = AAIUriFactory.createResourceUri(
321                 AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(profileId))
322             if (!getAAIClient().exists(resourceUri)) {
323                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Service Instance was not found in aai")
324             }
325             getAAIClient().delete(resourceUri)
326         }
327         catch (any)
328         {
329             String msg = "delete slice profile from aai failed! cause-"+any.getCause()
330             LOGGER.error(any.printStackTrace())
331             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
332         }
333         LOGGER.debug("*****${PREFIX} Exist delSliceProfileFromAAI *****")
334     }
335
336     void delSliceProfileFromAAI(DelegateExecution execution){
337
338         LOGGER.debug("*****${PREFIX} start delSliceProfileFromAAI *****")
339         def currentNSSI = execution.getVariable("currentNSSI")
340         String globalSubscriberId = currentNSSI["globalSubscriberId"]
341         String serviceType = currentNSSI['serviceType']
342         String sliceProfileInstId = currentNSSI['profileId']
343
344         try
345         {
346             AAIPluralResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(sliceProfileInstId).sliceProfiles())
347             AAIResultWrapper wrapper = getAAIClient().get(resourceUri, NotFoundException.class)
348             Optional<SliceProfiles> sliceProfilesOpt =wrapper.asBean(SliceProfiles.class)
349             SliceProfiles sliceProfiles
350             String profileId
351             if(sliceProfilesOpt.isPresent()){
352                 sliceProfiles = sliceProfilesOpt.get()
353                 org.onap.aai.domain.yang.SliceProfile sliceProfile = sliceProfiles.getSliceProfile().get(0)
354                 profileId = sliceProfile ? sliceProfile.getProfileId() : ""
355             }
356             if (profileId){
357                 AAISimpleUri profileUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.business().customer(globalSubscriberId).serviceSubscription(serviceType).serviceInstance(sliceProfileInstId).sliceProfile(profileId))
358                 if (!getAAIClient().exists(profileUri)) {
359                     exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Service Instance was not found in aai")
360                 }
361                 getAAIClient().delete(profileUri)
362             }
363
364         }
365         catch (any)
366         {
367             String msg = "delete service profile from aai failed! cause-"+any.getCause()
368             LOGGER.error(any.printStackTrace())
369             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
370         }
371     }
372 }