c559845e122a92b2c04834b5a852d0e98c082ef4
[so.git] / bpmn / so-bpmn-infrastructure-common / src / main / groovy / org / onap / so / bpmn / infrastructure / scripts / DoDeallocateCoreNSSI.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2020  Telecom Italia
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 com.google.gson.JsonObject
25 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.onap.aai.domain.yang.v19.AllottedResource
27 import org.onap.aai.domain.yang.v19.GenericVnf
28 import org.onap.aai.domain.yang.v19.ServiceInstance
29 import org.onap.aai.domain.yang.v19.SliceProfile
30 import org.onap.aai.domain.yang.v19.SliceProfiles
31 import org.onap.aaiclient.client.aai.AAIResourcesClient
32 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
33 import org.onap.aaiclient.client.aai.entities.Relationships
34 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
35 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
36 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
37 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types
38 import org.onap.logging.filter.base.ONAPComponents
39 import org.onap.so.bpmn.common.scripts.ExceptionUtil
40 import org.onap.so.bpmn.common.scripts.MsoUtils
41 import org.onap.so.bpmn.common.scripts.OofUtils
42 import org.onap.so.bpmn.common.scripts.RequestDBUtil
43 import org.onap.so.bpmn.core.UrnPropertiesReader
44 import org.onap.so.bpmn.core.json.JsonUtils
45 import org.onap.so.client.HttpClient
46 import org.onap.so.client.HttpClientFactory
47 import org.onap.so.client.oof.adapter.beans.payload.OofRequest
48 import org.slf4j.Logger
49 import org.slf4j.LoggerFactory
50
51 import javax.ws.rs.core.Response
52
53 import static org.apache.commons.lang3.StringUtils.isBlank
54 import static org.apache.commons.lang3.StringUtils.isBlank
55 import static org.onap.so.bpmn.common.scripts.GenericUtils.isBlank
56 import static org.onap.so.bpmn.common.scripts.GenericUtils.isBlank
57
58 class DoDeallocateCoreNSSI extends DoCommonCoreNSSI {
59     private final String PREFIX ="DoDeallocateCoreNSSI"
60     private final  String ACTION = "Deallocate"
61
62     private ExceptionUtil exceptionUtil = new ExceptionUtil()
63     private RequestDBUtil requestDBUtil = new RequestDBUtil()
64     private MsoUtils utils = new MsoUtils()
65     private JsonUtils jsonUtil = new JsonUtils()
66
67     private static final Logger LOGGER = LoggerFactory.getLogger( DoDeallocateCoreNSSI.class)
68
69
70     @Override
71     void preProcessRequest(DelegateExecution execution) {
72         LOGGER.debug("${getPrefix()} Start preProcessRequest")
73
74         super.preProcessRequest(execution)
75
76         execution.setVariable("operationType", "DEALLOCATE")
77
78         LOGGER.debug("${getPrefix()} Exit preProcessRequest")
79     }
80
81
82
83     /**
84      * Queries OOF for NSSI termination
85      * @param execution
86      */
87     void executeTerminateNSSIQuery(DelegateExecution execution) {
88         LOGGER.debug("${PREFIX} Start executeTerminateNSSIQuery")
89
90         String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
91        // String urlString = UrnPropertiesReader.getVariable("mso.adapters.oof.endpoint", execution)
92
93         //API Path
94         String apiPath =  "/api/oof/terminate/nxi/v1"
95         LOGGER.debug("API path for DoAllocateCoreNSSI: "+apiPath)
96
97         urlString = urlString + apiPath
98
99         //Prepare auth for OOF
100         def authHeader = ""
101         String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
102         String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
103
104         String basicAuthValue = utils.encrypt(basicAuth, msokey)
105      /*   if (basicAuthValue != null) {
106             LOGGER.debug( "Obtained BasicAuth username and password for OOF Adapter: " + basicAuthValue)
107             try {
108                 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
109                 execution.setVariable("BasicAuthHeaderValue", authHeader)
110             } catch (Exception ex) {
111                 LOGGER.error( "Unable to encode username and password string: " + ex)
112                 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to encode username and password string")
113             }
114         } else {
115             LOGGER.error( "Unable to obtain BasicAuth - BasicAuth value null")
116             exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth value null")
117         } */
118
119
120         try {
121             authHeader = utils.getBasicAuth(basicAuthValue, msokey)
122             execution.setVariable("BasicAuthHeaderValue", authHeader)
123         } catch (Exception ex) {
124             LOGGER.error( "Unable to encode username and password string: " + ex)
125             exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to encode username and password string")
126         }
127
128         //Prepare send request to OOF
129         String oofRequest = buildOOFRequest(execution)
130
131         String callOOFResponse = callOOF(urlString, authHeader, oofRequest)
132         LOGGER.debug("callOOFResponse=" + callOOFResponse)
133
134         String errorCode = jsonUtil.getJsonValue(callOOFResponse, "errorCode")
135         if(errorCode == null || errorCode.isEmpty()) { // No error
136             String terminateNSSI = jsonUtil.getJsonValue(callOOFResponse, "terminateResponse")
137             LOGGER.debug("isTerminateNSSI=" + terminateNSSI)
138
139             execution.setVariable("isTerminateNSSI", terminateNSSI)
140         }
141         else {
142             LOGGER.error(jsonUtil.getJsonValue(callOOFResponse, "errorMessage"))
143             exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(errorCode), jsonUtil.getJsonValue(callOOFResponse, "errorMessage"))
144         }
145
146         LOGGER.debug("${PREFIX} Exit executeTerminateNSSIQuery")
147     }
148
149
150     /**
151      * Executes sync call to OOF
152      * @return OOF response
153      */
154     String callOOF(String urlString, String authHeader, String oofRequest) {
155         LOGGER.debug("${PREFIX} Start callOOF")
156
157         String errorCode = ""
158         String errorMessage = ""
159         String response = ""
160
161         try {
162             URL url = new URL(urlString)
163             HttpClient httpClient = getHttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
164             httpClient.addAdditionalHeader("Authorization", authHeader)
165             httpClient.addAdditionalHeader("Content-Type", "application/json")
166
167             Response httpResponse = httpClient.post(oofRequest)
168
169             int responseCode = httpResponse.getStatus()
170             LOGGER.debug("OOF sync response code is: " + responseCode)
171
172             if(responseCode < 200 || responseCode >= 300) { // Wrong code
173                 errorCode = responseCode
174                 errorMessage = "Received a Bad Sync Response from OOF."
175
176                 response =  "{\n" +
177                         " \"errorCode\": \"${errorCode}\",\n" +
178                         " \"errorMessage\": \"${errorMessage}\"\n" +
179                         "}"
180                 //exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
181             }
182
183             if (httpResponse.hasEntity()) {
184                 response = httpResponse.readEntity(String.class)
185             }
186             else {
187                 errorCode = 500
188                 errorMessage = "No response received from OOF."
189
190                 response =  "{\n" +
191                         " \"errorCode\": \"${errorCode}\",\n" +
192                         " \"errorMessage\": \"${errorMessage}\"\n" +
193                         "}"
194             }
195         }
196         catch(Exception e) {
197             errorCode = 400
198             errorMessage = e.getMessage()
199
200             response =  "{\n" +
201                     " \"errorCode\": \"${errorCode}\",\n" +
202                     " \"errorMessage\": \"${errorMessage}\"\n" +
203                     "}"
204         }
205
206         LOGGER.debug("${PREFIX} Exit callOOF")
207
208         return response
209     }
210
211
212     /**
213      * Builds OOF request
214      * @param execution
215      * @return
216      */
217     private String buildOOFRequest(DelegateExecution execution) {
218         LOGGER.debug("${PREFIX} Start buildOOFRequest")
219
220         def currentNSSI = execution.getVariable("currentNSSI")
221
222         String nssiId = currentNSSI['nssiId']
223
224         ServiceInstance nssi = null
225
226         AAIResourcesClient client = getAAIClient()
227
228         // NSSI
229         AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
230         Optional<ServiceInstance> nssiOpt = client.get(ServiceInstance.class, nssiUri)
231
232         if (nssiOpt.isPresent()) {
233             nssi = nssiOpt.get()
234         }
235         else {
236             String msg = "NSSI service instance not found in AAI for nssi id " + nssiId
237             LOGGER.error(msg)
238             exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
239         }
240
241         //Setting correlator as requestId
242         String requestId = execution.getVariable("msoRequestId")
243         execution.setVariable("NSSI_correlator", requestId)
244
245         //Setting messageType for all Core slice as cn
246         String messageType = "cn"
247         execution.setVariable("NSSI_messageType", messageType)
248
249         //Prepare Callback
250         String timeout = execution.getVariable("timeout")
251         if (isBlank(timeout)) {
252             timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
253             if (isBlank(timeout)) {
254                 timeout = "PT30M"
255             }
256         }
257
258         String nxlId = nssi.getServiceInstanceId()
259         String nxlType = "NSSI"
260         String oofRequest = getOofUtils().buildTerminateNxiRequest(requestId, nxlId, nxlType, messageType, nssi.getServiceInstanceId())
261         LOGGER.debug("**** Terminate Nxi Request: "+oofRequest)
262
263         LOGGER.debug("${PREFIX} Exit buildOOFRequest")
264
265         return oofRequest
266     }
267
268
269
270     /**
271      * Invokes deleteServiceOrder external API
272      * @param execution
273      */
274     void deleteServiceOrder(DelegateExecution execution) {
275         LOGGER.debug("${PREFIX} Start deleteServiceOrder")
276
277         def currentNSSI = execution.getVariable("currentNSSI")
278
279         try {
280             //url:/nbi/api/v4/serviceOrder/"
281             def nsmfЕndPoint = UrnPropertiesReader.getVariable("mso.infra.endpoint.url", execution)
282
283             ServiceInstance networkServiceInstance = (ServiceInstance)currentNSSI['networkServiceInstance']
284
285             //String url = String.format("${nbiEndpointUrl}/api/v4/serviceOrder/%s", networkServiceInstance.getServiceInstanceId())
286
287             GenericVnf constituteVnf = (GenericVnf)currentNSSI['constituteVnf']
288
289             // http://so.onap:8080/onap/so/infra/serviceInstantiation/v7/serviceInstances/de6a0aa2-19f2-41fe-b313-a5a9f159acd7/vnfs/3abbb373-8d33-4977-aa4b-2bfee496b6d5
290             String url = String.format("${nsmfЕndPoint}/serviceInstantiation/v7/serviceInstances/%s/vnfs/%s", networkServiceInstance.getServiceInstanceId(), constituteVnf.getVnfId())
291
292             currentNSSI['deleteServiceOrderURL'] = url
293
294             String msoKey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
295             String basicAuth =  UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
296
297             /*String basicAuthValue = encryptBasicAuth(basicAuth, msoKey)
298             def authHeader = ""
299             if (basicAuthValue != null) {
300                 String responseAuthHeader = getAuthHeader(execution, basicAuthValue, msoKey)
301                 String errorCode = jsonUtil.getJsonValue(responseAuthHeader, "errorCode")
302                 if(errorCode == null || errorCode.isEmpty()) { // No error
303                     authHeader = responseAuthHeader
304                 }
305                 else {
306                     exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(errorCode), jsonUtil.getJsonValue(responseAuthHeader, "errorMessage"))
307                 }
308             } else {
309                 LOGGER.error( "Unable to obtain BasicAuth - BasicAuth value null")
310                 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
311                         "value null")
312             } */
313
314             def authHeader = utils.getBasicAuth(basicAuth, msoKey)
315
316             String callDeleteServiceOrderResponse = callDeleteServiceOrder(execution, url, authHeader)
317             String errorCode = jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorCode")
318
319             if(errorCode == null || errorCode.isEmpty()) { // No error
320                 String macroOperationId = jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "requestReferences.requestId")
321                 String requestSelfLink = jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "requestReferences.requestSelfLink")
322
323                 execution.setVariable("macroOperationId",  macroOperationId)
324                 execution.setVariable("requestSelfLink", requestSelfLink)
325
326                 currentNSSI['requestSelfLink'] = requestSelfLink
327             }
328             else {
329                 LOGGER.error(jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorMessage"))
330                 exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(errorCode), jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorMessage"))
331             }
332         } catch (any) {
333             String msg = "Exception in DoDeallocateCoreNSSI.deleteServiceOrder. " + any.getCause()
334             LOGGER.error(msg)
335             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
336         }
337
338         LOGGER.debug("${PREFIX} Exit deleteServiceOrder")
339     }
340
341
342     String callDeleteServiceOrder(DelegateExecution execution, String url, String authHeader) {
343         LOGGER.debug("${PREFIX} Start callDeleteServiceOrder")
344
345         String errorCode = ""
346         String errorMessage = ""
347         String response = ""
348
349         try {
350             HttpClient httpClient = getHttpClientFactory().newJsonClient(new URL(url), ONAPComponents.SO)
351             httpClient.addAdditionalHeader("Authorization", authHeader)
352             httpClient.addAdditionalHeader("Accept", "application/json")
353             Response httpResponse = httpClient.delete()
354
355             int soResponseCode = httpResponse.getStatus()
356             LOGGER.debug("callDeleteServiceInstance: soResponseCode = " + soResponseCode)
357
358             if (soResponseCode >= 200 && soResponseCode < 204 && httpResponse.hasEntity()) {
359                 response = httpResponse.readEntity(String.class)
360
361                 LOGGER.debug("callDeleteServiceInstance: response = " + response)
362             }
363             else {
364                 errorCode = 500
365                 errorMessage = "Response code is " + soResponseCode
366
367                 response =  "{\n" +
368                         " \"errorCode\": \"${errorCode}\",\n" +
369                         " \"errorMessage\": \"${errorMessage}\"\n" +
370                         "}"
371             }
372         }
373         catch (any) {
374             String msg = "Exception in DoDeallocateCoreNSSI.callDeleteServiceOrder. " + any.getCause()
375
376             response =  "{\n" +
377                     " \"errorCode\": \"7000\",\n" +
378                     " \"errorMessage\": \"${msg}\"\n" +
379                     "}"
380         }
381
382         LOGGER.debug("${PREFIX} Exit callDeleteServiceOrder")
383
384         return response
385     }
386
387
388     /**
389      * Removes NSSI association with NSI
390      * @param execution
391      */
392     void removeNSSIAssociationWithNSI(DelegateExecution execution) {
393         LOGGER.debug("${PREFIX} Start removeNSSIAssociationWithNSI")
394
395         AAIResourcesClient client = getAAIClient()
396
397         def currentNSSI = execution.getVariable("currentNSSI")
398
399         String nssiId = currentNSSI['nssiId']
400         String nsiId = currentNSSI['nsiId']
401         String globalSubscriberId = execution.getVariable("globalSubscriberId")
402         String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
403
404         // NSSI
405         AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
406
407
408         String allottedResourceId = null
409
410
411         AAIResultWrapper nssiWrapper = client.get(nssiUri)
412         Optional<Relationships> nssiRelationships = nssiWrapper.getRelationships()
413
414         if (nssiRelationships.isPresent()) {
415             // Allotted Resource
416             for (AAIResourceUri allottedResourceUri : nssiRelationships.get().getRelatedUris(Types.ALLOTTED_RESOURCE)) {
417                 AAIResultWrapper arWrapper = client.get(allottedResourceUri)
418                 Optional<Relationships> arRelationships = arWrapper.getRelationships()
419
420                 if(arRelationships.isPresent()) {
421                     // NSI
422                     for (AAIResourceUri nsiUri : arRelationships.get().getRelatedUris(Types.SERVICE_INSTANCE)) {
423                         Optional<ServiceInstance> nsiOpt = client.get(ServiceInstance.class, nsiUri)
424
425                         if (nsiOpt.isPresent()) {
426                             ServiceInstance nsi = nsiOpt.get()
427                             if(nsi.getServiceRole().equals("nsi")) { // Service instance as NSI
428                                 // Removes NSSI association with NSI
429                                 try {
430                                     client.disconnect(nssiUri, nsiUri)
431                                 }
432                                 catch (Exception e) {
433                                     exceptionUtil.buildAndThrowWorkflowException(execution, 25000, "Exception occured while NSSI association with NSI dosconnect call: " + e.getMessage())
434                                 }
435                             }
436                         }
437                         else {
438                             LOGGER.warn("No NSI found for NSSI id " + nssiId)
439                         }
440                     }
441                 }
442                 else {
443                     LOGGER.warn("No relationships found for Allotted Resource for NSSI id " + nssiId)
444                 }
445
446             }
447         }
448         else {
449             LOGGER.warn("No relationships  found for nssi id = " + nssiId)
450         }
451
452
453         LOGGER.debug("${PREFIX} Exit removeNSSIAssociationWithNSI")
454     }
455
456
457     /**
458      * Delets NSSI Service Instance
459      * @param execution
460      */
461     void deleteNSSIServiceInstance(DelegateExecution execution) {
462         LOGGER.debug("${PREFIX} Start deleteNSSIServiceInstance")
463
464         AAIResourcesClient client = getAAIClient()
465
466         def currentNSSI = execution.getVariable("currentNSSI")
467
468         String nssiId = currentNSSI['nssiId']
469         AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
470
471         try {
472             client.delete(nssiUri)
473         }catch(Exception e){
474             exceptionUtil.buildAndThrowWorkflowException(execution, 25000, "Exception occurred while NSSI Service Instance delete call: " + e.getMessage())
475         }
476
477         LOGGER.debug("${PREFIX} Exit deleteNSSIServiceInstance")
478     }
479
480
481     /**
482      * Gets Delete Service Order progress
483      * @param execution
484      */
485     void getDeleteServiceOrderProgress(DelegateExecution execution) {
486         LOGGER.debug("${getPrefix()} Start getDeleteServiceOrderProgress")
487
488         def currentNSSI = execution.getVariable("currentNSSI")
489
490         String url = currentNSSI['requestSelfLink']
491
492         String msoKey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
493
494         String basicAuth =  UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
495
496         def authHeader = ""
497         String basicAuthValue = utils.getBasicAuth(basicAuth, msoKey)
498
499         getProgress(execution, url, basicAuthValue, "deleteStatus")
500
501         LOGGER.debug("${getPrefix()} Exit getDeleteServiceOrderProgress")
502     }
503
504
505     /**
506      * Calculates a final list of S-NSSAI
507      * @param execution
508      */
509     void calculateSNSSAI(DelegateExecution execution) {
510         LOGGER.debug("${getPrefix()} Start calculateSNSSAI")
511
512         def currentNSSI = execution.getVariable("currentNSSI")
513
514         List<SliceProfile> associatedProfiles = (List<SliceProfile>)currentNSSI['associatedProfiles']
515
516         String givenSliceProfileId = currentNSSI['sliceProfileId']
517
518         List<String> snssais = new ArrayList<>()
519
520         String isTerminateNSSIVar = execution.getVariable("isTerminateNSSI" )
521
522         boolean isTerminateNSSI = Boolean.parseBoolean(isTerminateNSSIVar)
523
524         if(!isTerminateNSSI) { // NSSI should not be terminated
525             LOGGER.debug("calculateSNSSAI: associatedProfiles.size()" + associatedProfiles.size())
526             for (SliceProfile associatedProfile : associatedProfiles) {
527                 if (!associatedProfile.getProfileId().equals(givenSliceProfileId)) { // not given profile id
528                     LOGGER.debug("calculateSNSSAI: associatedProfile.getSNssai()" + associatedProfile.getSNssai())
529                     snssais.add(associatedProfile.getSNssai())
530                 } else {
531                     currentNSSI['sliceProfileS-NSSAI'] = associatedProfile
532                 }
533             }
534         }
535
536         currentNSSI['S-NSSAIs'] = snssais
537
538         LOGGER.debug("${getPrefix()} Exit calculateSNSSAI")
539     }
540
541
542     /**
543      * OofUtils
544      * @return new OofUtils()
545      */
546     OofUtils getOofUtils() {
547         return new OofUtils()
548     }
549
550
551     private String getPrefix() {
552         return PREFIX
553     }
554
555     @Override
556     String getAction() {
557         return ACTION
558     }
559 }