Wrong additional parameter for OOF's terminateNxiRequest
[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
242         // NSI
243         String nsiId = currentNSSI['nsiId']
244         ServiceInstance nsi = null
245         AAIResourceUri nsiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nsiId))
246         Optional<ServiceInstance> nsiOpt = client.get(ServiceInstance.class, nsiUri)
247         if (nsiOpt.isPresent()) {
248             nsi = nsiOpt.get()
249         }
250         else {
251             String msg = "NSI service instance not found in AAI for nsi id " + nsiId
252             LOGGER.error(msg)
253             exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
254         }
255
256
257         //Setting correlator as requestId
258         String requestId = execution.getVariable("msoRequestId")
259         execution.setVariable("NSSI_correlator", requestId)
260
261         //Setting messageType for all Core slice as cn
262         String messageType = "cn"
263         execution.setVariable("NSSI_messageType", messageType)
264
265         //Prepare Callback
266         String timeout = execution.getVariable("timeout")
267         if (isBlank(timeout)) {
268             timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
269             if (isBlank(timeout)) {
270                 timeout = "PT30M"
271             }
272         }
273
274         String nxlId = nssi.getServiceInstanceId()
275         String nxlType = "NSSI"
276         String oofRequest = getOofUtils().buildTerminateNxiRequest(requestId, nxlId, nxlType, messageType, nsi.getServiceInstanceId())
277         LOGGER.debug("**** Terminate Nxi Request: "+oofRequest)
278
279         LOGGER.debug("${PREFIX} Exit buildOOFRequest")
280
281         return oofRequest
282     }
283
284
285
286     /**
287      * Invokes deleteServiceOrder external API
288      * @param execution
289      */
290     void deleteServiceOrder(DelegateExecution execution) {
291         LOGGER.debug("${PREFIX} Start deleteServiceOrder")
292
293         def currentNSSI = execution.getVariable("currentNSSI")
294
295         try {
296             //url:/nbi/api/v4/serviceOrder/"
297             def nsmfЕndPoint = UrnPropertiesReader.getVariable("mso.infra.endpoint.url", execution)
298
299             ServiceInstance networkServiceInstance = (ServiceInstance)currentNSSI['networkServiceInstance']
300
301             //String url = String.format("${nbiEndpointUrl}/api/v4/serviceOrder/%s", networkServiceInstance.getServiceInstanceId())
302
303             GenericVnf constituteVnf = (GenericVnf)currentNSSI['constituteVnf']
304
305             // http://so.onap:8080/onap/so/infra/serviceInstantiation/v7/serviceInstances/de6a0aa2-19f2-41fe-b313-a5a9f159acd7/vnfs/3abbb373-8d33-4977-aa4b-2bfee496b6d5
306             String url = String.format("${nsmfЕndPoint}/serviceInstantiation/v7/serviceInstances/%s/vnfs/%s", networkServiceInstance.getServiceInstanceId(), constituteVnf.getVnfId())
307
308             LOGGER.debug("url = " + url)
309
310             currentNSSI['deleteServiceOrderURL'] = url
311
312             String msoKey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
313             String basicAuth =  UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
314
315             def authHeader = utils.getBasicAuth(basicAuth, msoKey)
316
317             def requestDetails = ""
318
319             String prepareRequestDetailsResponse = prepareRequestDetails(execution)
320             LOGGER.debug("deleteServiceOrder: prepareRequestDetailsResponse=" + prepareRequestDetailsResponse)
321
322             String errorCode = jsonUtil.getJsonValue(prepareRequestDetailsResponse, "errorCode")
323             LOGGER.debug("deleteServiceOrder: errorCode=" + errorCode)
324             if(errorCode == null || errorCode.isEmpty()) { // No error
325                 requestDetails = prepareRequestDetailsResponse
326             }
327             else {
328                 exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(errorCode), jsonUtil.getJsonValue(prepareRequestDetailsResponse, "errorMessage"))
329             }
330
331             String callDeleteServiceOrderResponse = callDeleteServiceOrder(url, authHeader, requestDetails)
332             errorCode = jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorCode")
333
334             if(errorCode == null || errorCode.isEmpty()) { // No error
335                 String macroOperationId = jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "requestReferences.requestId")
336                 String requestSelfLink = jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "requestReferences.requestSelfLink")
337
338                 execution.setVariable("macroOperationId",  macroOperationId)
339                 execution.setVariable("requestSelfLink", requestSelfLink)
340
341                 currentNSSI['requestSelfLink'] = requestSelfLink
342             }
343             else {
344                 LOGGER.error(jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorMessage"))
345                 exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(errorCode), jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorMessage"))
346             }
347         } catch (any) {
348             String msg = "Exception in DoDeallocateCoreNSSI.deleteServiceOrder. " + any.getCause()
349             LOGGER.error(msg)
350             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
351         }
352
353         LOGGER.debug("${PREFIX} Exit deleteServiceOrder")
354     }
355
356
357     String callDeleteServiceOrder(String url, String authHeader, String requestDetailsStr) {
358         LOGGER.debug("${PREFIX} Start callDeleteServiceOrder")
359
360         String errorCode = ""
361         String errorMessage = ""
362         String response = ""
363
364         LOGGER.debug("callDeleteServiceOrder: url = " + url)
365         LOGGER.debug("callDeleteServiceOrder: authHeader = " + authHeader)
366
367         try {
368             HttpClient httpClient = getHttpClientFactory().newJsonClient(new URL(url), ONAPComponents.SO)
369             httpClient.addAdditionalHeader("Authorization", authHeader)
370             httpClient.addAdditionalHeader("Accept", "application/json")
371             Response httpResponse = httpClient.delete(requestDetailsStr)
372
373             int soResponseCode = httpResponse.getStatus()
374             LOGGER.debug("callDeleteServiceOrder: soResponseCode = " + soResponseCode)
375
376             if (soResponseCode >= 200 && soResponseCode < 204 && httpResponse.hasEntity()) {
377                 response = httpResponse.readEntity(String.class)
378
379                 LOGGER.debug("callDeleteServiceInstance: response = " + response)
380             }
381             else {
382                 errorCode = 500
383                 errorMessage = "Response code is " + soResponseCode
384
385                 response =  "{\n" +
386                         " \"errorCode\": \"${errorCode}\",\n" +
387                         " \"errorMessage\": \"${errorMessage}\"\n" +
388                         "}"
389             }
390         }
391         catch (any) {
392             String msg = "Exception in DoDeallocateCoreNSSI.callDeleteServiceOrder. " + any.getCause()
393
394             response =  "{\n" +
395                     " \"errorCode\": \"7000\",\n" +
396                     " \"errorMessage\": \"${msg}\"\n" +
397                     "}"
398         }
399
400         LOGGER.debug("${PREFIX} Exit callDeleteServiceOrder")
401
402         return response
403     }
404
405
406     /**
407      * Removes NSSI association with NSI
408      * @param execution
409      */
410     void removeNSSIAssociationWithNSI(DelegateExecution execution) {
411         LOGGER.debug("${PREFIX} Start removeNSSIAssociationWithNSI")
412
413         AAIResourcesClient client = getAAIClient()
414
415         def currentNSSI = execution.getVariable("currentNSSI")
416
417         String nssiId = currentNSSI['nssiId']
418         String nsiId = currentNSSI['nsiId']
419         String globalSubscriberId = execution.getVariable("globalSubscriberId")
420         String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
421
422         // NSSI
423         AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
424
425
426         String allottedResourceId = null
427
428
429         AAIResultWrapper nssiWrapper = client.get(nssiUri)
430         Optional<Relationships> nssiRelationships = nssiWrapper.getRelationships()
431
432         if (nssiRelationships.isPresent()) {
433             // Allotted Resource
434             for (AAIResourceUri allottedResourceUri : nssiRelationships.get().getRelatedUris(Types.ALLOTTED_RESOURCE)) {
435                 AAIResultWrapper arWrapper = client.get(allottedResourceUri)
436                 Optional<Relationships> arRelationships = arWrapper.getRelationships()
437
438                 if(arRelationships.isPresent()) {
439                     // NSI
440                     for (AAIResourceUri nsiUri : arRelationships.get().getRelatedUris(Types.SERVICE_INSTANCE)) {
441                         Optional<ServiceInstance> nsiOpt = client.get(ServiceInstance.class, nsiUri)
442
443                         if (nsiOpt.isPresent()) {
444                             ServiceInstance nsi = nsiOpt.get()
445                             if(nsi.getServiceRole().equals("nsi")) { // Service instance as NSI
446                                 // Removes NSSI association with NSI
447                                 try {
448                                     client.disconnect(nssiUri, nsiUri)
449                                 }
450                                 catch (Exception e) {
451                                     exceptionUtil.buildAndThrowWorkflowException(execution, 25000, "Exception occured while NSSI association with NSI dosconnect call: " + e.getMessage())
452                                 }
453                             }
454                         }
455                         else {
456                             LOGGER.warn("No NSI found for NSSI id " + nssiId)
457                         }
458                     }
459                 }
460                 else {
461                     LOGGER.warn("No relationships found for Allotted Resource for NSSI id " + nssiId)
462                 }
463
464             }
465         }
466         else {
467             LOGGER.warn("No relationships  found for nssi id = " + nssiId)
468         }
469
470
471         LOGGER.debug("${PREFIX} Exit removeNSSIAssociationWithNSI")
472     }
473
474
475     /**
476      * Delets NSSI Service Instance
477      * @param execution
478      */
479     void deleteNSSIServiceInstance(DelegateExecution execution) {
480         LOGGER.debug("${PREFIX} Start deleteNSSIServiceInstance")
481
482         AAIResourcesClient client = getAAIClient()
483
484         def currentNSSI = execution.getVariable("currentNSSI")
485
486         String nssiId = currentNSSI['nssiId']
487         AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
488
489         try {
490             client.delete(nssiUri)
491         }catch(Exception e){
492             exceptionUtil.buildAndThrowWorkflowException(execution, 25000, "Exception occurred while NSSI Service Instance delete call: " + e.getMessage())
493         }
494
495         LOGGER.debug("${PREFIX} Exit deleteNSSIServiceInstance")
496     }
497
498
499     /**
500      * Gets Delete Service Order progress
501      * @param execution
502      */
503     void getDeleteServiceOrderProgress(DelegateExecution execution) {
504         LOGGER.debug("${getPrefix()} Start getDeleteServiceOrderProgress")
505
506         def currentNSSI = execution.getVariable("currentNSSI")
507
508         String url = currentNSSI['requestSelfLink']
509
510         String msoKey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
511
512         String basicAuth =  UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
513
514         def authHeader = ""
515         String basicAuthValue = utils.getBasicAuth(basicAuth, msoKey)
516
517         getProgress(execution, url, basicAuthValue, "deleteStatus")
518
519         LOGGER.debug("${getPrefix()} Exit getDeleteServiceOrderProgress")
520     }
521
522
523     /**
524      * Calculates a final list of S-NSSAI
525      * @param execution
526      */
527     void calculateSNSSAI(DelegateExecution execution) {
528         LOGGER.debug("${getPrefix()} Start calculateSNSSAI")
529
530         def currentNSSI = execution.getVariable("currentNSSI")
531
532         List<SliceProfile> associatedProfiles = (List<SliceProfile>)currentNSSI['associatedProfiles']
533
534         String givenSliceProfileId = currentNSSI['sliceProfileId']
535
536         List<String> snssais = new ArrayList<>()
537
538         String isTerminateNSSIVar = execution.getVariable("isTerminateNSSI" )
539
540         boolean isTerminateNSSI = Boolean.parseBoolean(isTerminateNSSIVar)
541
542         if(!isTerminateNSSI) { // NSSI should not be terminated
543             LOGGER.debug("calculateSNSSAI: associatedProfiles.size()" + associatedProfiles.size())
544             for (SliceProfile associatedProfile : associatedProfiles) {
545                 if (!associatedProfile.getProfileId().equals(givenSliceProfileId)) { // not given profile id
546                     LOGGER.debug("calculateSNSSAI: associatedProfile.getSNssai()" + associatedProfile.getSNssai())
547                     snssais.add(associatedProfile.getSNssai())
548                 } else {
549                     currentNSSI['sliceProfileS-NSSAI'] = associatedProfile
550                 }
551             }
552         }
553
554         currentNSSI['S-NSSAIs'] = snssais
555
556         LOGGER.debug("${getPrefix()} Exit calculateSNSSAI")
557     }
558
559
560     /**
561      * OofUtils
562      * @return new OofUtils()
563      */
564     OofUtils getOofUtils() {
565         return new OofUtils()
566     }
567
568
569     private String getPrefix() {
570         return PREFIX
571     }
572
573     @Override
574     String getAction() {
575         return ACTION
576     }
577 }