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