Remove NatUtil::read()
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / RouterDpnChangeListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netvirt.natservice.internal;
9
10 import com.google.common.base.Optional;
11
12 import java.math.BigInteger;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.List;
16 import javax.annotation.PostConstruct;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
22 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
23 import org.opendaylight.genius.mdsalutil.BucketInfo;
24 import org.opendaylight.genius.mdsalutil.FlowEntity;
25 import org.opendaylight.genius.mdsalutil.GroupEntity;
26 import org.opendaylight.genius.mdsalutil.MDSALUtil;
27 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
28 import org.opendaylight.netvirt.elanmanager.api.IElanService;
29 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
30 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig.NatMode;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 @Singleton
46 public class RouterDpnChangeListener
47         extends AsyncDataTreeChangeListenerBase<DpnVpninterfacesList, RouterDpnChangeListener>
48         implements AutoCloseable {
49
50     private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class);
51     private final DataBroker dataBroker;
52     private final IMdsalApiManager mdsalManager;
53     private final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer;
54     private final NaptSwitchHA naptSwitchHA;
55     private final IdManagerService idManager;
56     private final INeutronVpnManager nvpnManager;
57     private final ExternalNetworkGroupInstaller extNetGroupInstaller;
58     private final IElanService elanManager;
59     private SnatServiceManager natServiceManager;
60     private NatMode natMode = NatMode.Controller;
61
62     @Inject
63     public RouterDpnChangeListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
64                                    final SNATDefaultRouteProgrammer snatDefaultRouteProgrammer,
65                                    final NaptSwitchHA naptSwitchHA,
66                                    final IdManagerService idManager,
67                                    final ExternalNetworkGroupInstaller extNetGroupInstaller,
68                                    final INeutronVpnManager nvpnManager,
69                                    final SnatServiceManager natServiceManager,
70                                    final NatserviceConfig config,
71                                    final IElanService elanManager) {
72         super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
73         this.dataBroker = dataBroker;
74         this.mdsalManager = mdsalManager;
75         this.snatDefaultRouteProgrammer = snatDefaultRouteProgrammer;
76         this.naptSwitchHA = naptSwitchHA;
77         this.idManager = idManager;
78         this.extNetGroupInstaller = extNetGroupInstaller;
79         this.nvpnManager = nvpnManager;
80         this.elanManager = elanManager;
81         this.natServiceManager = natServiceManager;
82         if (config != null) {
83             this.natMode = config.getNatMode();
84         }
85     }
86
87     @Override
88     @PostConstruct
89     public void init() {
90         LOG.info("{} init", getClass().getSimpleName());
91         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
92     }
93
94     @Override
95     protected RouterDpnChangeListener getDataTreeChangeListener() {
96         return RouterDpnChangeListener.this;
97     }
98
99     @Override
100     protected InstanceIdentifier<DpnVpninterfacesList> getWildCardPath() {
101         return InstanceIdentifier.create(NeutronRouterDpns.class).child(RouterDpnList.class)
102             .child(DpnVpninterfacesList.class);
103     }
104
105     @Override
106     protected void add(final InstanceIdentifier<DpnVpninterfacesList> identifier, final DpnVpninterfacesList dpnInfo) {
107         LOG.trace("Add event - key: {}, value: {}", identifier, dpnInfo);
108         final String routerId = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
109         BigInteger dpnId = dpnInfo.getDpnId();
110         //check router is associated to external network
111         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
112         Optional<Routers> routerData =
113                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
114                         LogicalDatastoreType.CONFIGURATION, id);
115         if (routerData.isPresent()) {
116             Routers router = routerData.get();
117             Uuid networkId = router.getNetworkId();
118             if (networkId != null) {
119                 if (natMode == NatMode.Conntrack) {
120                     BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
121                     if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
122                         LOG.debug("NAPT switch is not selected.");
123                         return;
124                     }
125                     natServiceManager.notify(router, naptSwitch, dpnId,
126                             SnatServiceManager.Action.SNAT_ROUTER_ENBL);
127                 } else {
128                     LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
129                     Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerId);
130                     Long vpnId;
131                     if (vpnName == null) {
132                         LOG.debug("Internal vpn associated to router {}", routerId);
133                         vpnId = NatUtil.getVpnId(dataBroker, routerId);
134                         if (vpnId == NatConstants.INVALID_ID) {
135                             LOG.error("Invalid vpnId returned for routerName {}", routerId);
136                             return;
137                         }
138                         LOG.debug("Retrieved vpnId {} for router {}", vpnId, routerId);
139                         //Install default entry in FIB to SNAT table
140                         LOG.info("Installing default route in FIB on dpn {} for router {} with vpn {}",
141                                 dpnId, routerId, vpnId);
142                         installDefaultNatRouteForRouterExternalSubnets(dpnId,
143                                 NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
144                         snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
145                     } else {
146                         LOG.debug("External BGP vpn associated to router {}", routerId);
147                         vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
148                         if (vpnId == NatConstants.INVALID_ID) {
149                             LOG.error("Invalid vpnId returned for routerName {}", routerId);
150                             return;
151                         }
152                         Long routId = NatUtil.getVpnId(dataBroker, routerId);
153                         if (routId == NatConstants.INVALID_ID) {
154                             LOG.error("Invalid routId returned for routerName {}", routerId);
155                             return;
156                         }
157                         LOG.debug("Retrieved vpnId {} for router {}", vpnId, routerId);
158                         //Install default entry in FIB to SNAT table
159                         LOG.debug("Installing default route in FIB on dpn {} for routerId {} with vpnId {}...",
160                                 dpnId, routerId, vpnId);
161                         installDefaultNatRouteForRouterExternalSubnets(dpnId,
162                                 NatUtil.getExternalSubnetIdsFromExternalIps(router.getExternalIps()));
163                         snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routId);
164                     }
165                     extNetGroupInstaller.installExtNetGroupEntries(networkId, dpnId);
166
167                     if (router.isEnableSnat()) {
168                         LOG.info("On add - SNAT enabled for router {}", routerId);
169                         handleSNATForDPN(dpnId, routerId, vpnId);
170                     } else {
171                         LOG.info("SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
172                     }
173                 }
174             }
175         } else {
176             LOG.debug("Router {} is not associated with External network", routerId);
177         }
178     }
179
180     @Override
181     protected void remove(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList dpnInfo) {
182         LOG.trace("Remove event - key: {}, value: {}", identifier, dpnInfo);
183         final String routerId = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
184         BigInteger dpnId = dpnInfo.getDpnId();
185         //check router is associated to external network
186         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
187         Optional<Routers> routerData =
188                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
189                         LogicalDatastoreType.CONFIGURATION, id);
190         if (routerData.isPresent()) {
191             Routers router = routerData.get();
192             Uuid networkId = router.getNetworkId();
193             if (networkId != null) {
194                 if (natMode == NatMode.Conntrack) {
195                     BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
196                     if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
197                         LOG.debug("NAPT switch is not selected.");
198                         return;
199                     }
200                     natServiceManager.notify(router, naptSwitch, dpnId,
201                             SnatServiceManager.Action.SNAT_ROUTER_DISBL);
202                 } else {
203                     LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
204                     Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerId);
205                     Long vpnId;
206                     if (vpnName == null) {
207                         LOG.debug("Internal vpn associated to router {}", routerId);
208                         vpnId = NatUtil.getVpnId(dataBroker, routerId);
209                         if (vpnId == NatConstants.INVALID_ID) {
210                             LOG.error("Invalid vpnId returned for routerName {}", routerId);
211                             return;
212                         }
213                         LOG.debug("Retrieved vpnId {} for router {}", vpnId, routerId);
214                         //Remove default entry in FIB
215                         LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
216                         snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId);
217                     } else {
218                         LOG.debug("External vpn associated to router {}", routerId);
219                         vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
220                         if (vpnId == NatConstants.INVALID_ID) {
221                             LOG.error("Invalid vpnId returned for routerName {}", routerId);
222                             return;
223                         }
224                         Long routId = NatUtil.getVpnId(dataBroker, routerId);
225                         if (routId == NatConstants.INVALID_ID) {
226                             LOG.error("Invalid routId returned for routerName {}", routerId);
227                             return;
228                         }
229                         LOG.debug("Retrieved vpnId {} for router {}", vpnId, routerId);
230                         //Remove default entry in FIB
231                         LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
232                         snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routId);
233                     }
234
235                     if (router.isEnableSnat()) {
236                         LOG.info("On remove - SNAT enabled for router {}", routerId);
237                         removeSNATFromDPN(dpnId, routerId, vpnId);
238                     } else {
239                         LOG.info("SNAT is not enabled for router {} to handle removeDPN event {}", routerId, dpnId);
240                     }
241                 }
242             }
243         }
244     }
245
246     @Override
247     protected void update(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList original,
248                           DpnVpninterfacesList update) {
249         LOG.trace("Update event - key: {}, original: {}, update: {}", identifier, original, update);
250     }
251
252     // TODO Clean up the exception handling
253     @SuppressWarnings("checkstyle:IllegalCatch")
254     void handleSNATForDPN(BigInteger dpnId, String routerName, Long routerVpnId) {
255        //Check if primary and secondary switch are selected, If not select the role
256         //Install select group to NAPT switch
257         //Install default miss entry to NAPT switch
258         BigInteger naptSwitch;
259         try {
260             Long routerId = NatUtil.getVpnId(dataBroker, routerName);
261             if (routerId == NatConstants.INVALID_ID) {
262                 LOG.error("Invalid routerId returned for routerName {}", routerName);
263                 return;
264             }
265             BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
266             if (naptId == null || naptId.equals(BigInteger.ZERO) || !naptSwitchHA.getSwitchStatus(naptId)) {
267                 LOG.debug("No NaptSwitch is selected for router {}", routerName);
268                 naptSwitch = dpnId;
269                 boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
270                 if (!naptstatus) {
271                     LOG.error("Failed to update newNaptSwitch {} for routername {}", naptSwitch, routerName);
272                     return;
273                 }
274                 LOG.debug("Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
275
276                 // When NAPT switch is elected during first VM comes up for the given Router
277                 if (elanManager.isOpenStackVniSemanticsEnforced()) {
278                     NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager,
279                             idManager, NatConstants.ODL_VNI_POOL_NAME);
280                 }
281
282                 Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
283                 if (extRouters != null) {
284                     NatUtil.createRouterIdsConfigDS(dataBroker, routerName);
285                     naptSwitchHA.subnetRegisterMapping(extRouters, routerId);
286                 }
287
288                 naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId);
289
290                 // Install miss entry (table 26) pointing to table 46
291                 FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName,
292                         routerVpnId, NatConstants.ADD_FLOW);
293                 if (flowEntity == null) {
294                     LOG.debug("Failed to populate flowentity for router {} with dpnId {}", routerName, dpnId);
295                     return;
296                 }
297                 LOG.debug("Successfully installed flow for dpnId {} router {}", dpnId, routerName);
298                 mdsalManager.installFlow(flowEntity);
299                 //Removing primary flows from old napt switch
300                 if (naptId != null && !naptId.equals(BigInteger.ZERO)) {
301                     LOG.debug("Removing primary flows from old napt switch {} for router {}", naptId, routerName);
302                     naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, naptId, null);
303                 }
304             } else if (naptId.equals(dpnId)) {
305                 LOG.debug("NaptSwitch {} gone down during cluster reboot came alive", naptId);
306             } else {
307                 naptSwitch = naptId;
308                 LOG.debug("Napt switch with Id {} is already elected for router {}", naptId, routerName);
309
310
311                 //installing group
312                 List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId,
313                         routerName, naptSwitch);
314                 if (bucketInfo == null) {
315                     LOG.debug("Failed to populate bucketInfo for dpnId {} routername {} naptSwitch {}",
316                             dpnId, routerName, naptSwitch);
317                     return;
318                 }
319                 naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
320
321                 // Install miss entry (table 26) pointing to group
322                 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
323                 FlowEntity flowEntity =
324                         naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
325                                 routerVpnId, NatConstants.ADD_FLOW);
326                 if (flowEntity == null) {
327                     LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupId {}",
328                             routerName, dpnId, groupId);
329                     return;
330                 }
331                 LOG.debug("Successfully installed flow for dpnId {} router {} group {}",
332                         dpnId, routerName, groupId);
333                 mdsalManager.installFlow(flowEntity);
334             }
335
336         } catch (Exception ex) {
337             LOG.error("Exception in handleSNATForDPN method : {}", ex);
338         }
339     }
340
341     // TODO Clean up the exception handling
342     @SuppressWarnings("checkstyle:IllegalCatch")
343     void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerVpnId) {
344         //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
345         //remove miss entry to NAPT switch
346         //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
347
348         //get ExternalIpIn prior
349         List<String> externalIpCache;
350         //HashMap Label
351         HashMap<String, Long> externalIpLabel;
352         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
353         if (routerId == NatConstants.INVALID_ID) {
354             LOG.error("Invalid routerId returned for routerName {}", routerName);
355             return;
356         }
357         externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
358         ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName);
359         if (extNwProvType == null) {
360             return;
361         }
362         //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
363         if (extNwProvType == ProviderTypes.VXLAN) {
364             externalIpLabel = null;
365         } else {
366             externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
367         }
368         BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
369         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
370             LOG.debug("No naptSwitch is selected for router {}", routerName);
371             return;
372         }
373         try {
374             boolean naptStatus =
375                 naptSwitchHA.isNaptSwitchDown(routerName, dpnId, naptSwitch, routerVpnId, externalIpCache);
376             if (!naptStatus) {
377                 LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
378                     dpnId, routerName);
379                 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
380                 FlowEntity flowEntity = null;
381                 try {
382                     flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
383                         NatConstants.DEL_FLOW);
384                     if (flowEntity == null) {
385                         LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupIs {}",
386                             routerName, dpnId, groupId);
387                         return;
388                     }
389                     LOG.debug("NAT Service : Removing default SNAT miss entry flow entity {}", flowEntity);
390                     mdsalManager.removeFlow(flowEntity);
391
392                 } catch (Exception ex) {
393                     LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",
394                         flowEntity, ex);
395                     return;
396                 }
397                 LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}",
398                     dpnId, routerName);
399
400                 //remove group
401                 GroupEntity groupEntity = null;
402                 try {
403                     groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
404                         GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
405                     LOG.info("NAT Service : Removing NAPT GroupEntity:{}", groupEntity);
406                     mdsalManager.removeGroup(groupEntity);
407                 } catch (Exception ex) {
408                     LOG.debug("NAT Service : Failed to remove group entity {} : {}", groupEntity, ex);
409                     return;
410                 }
411                 LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
412                     dpnId, routerName);
413             } else {
414                 naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, naptSwitch, externalIpLabel);
415                 //remove table 26 flow ppointing to table46
416                 FlowEntity flowEntity = null;
417                 try {
418                     flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
419                         NatConstants.DEL_FLOW);
420                     if (flowEntity == null) {
421                         LOG.debug("Failed to populate flowentity for router {} with dpnId {}", routerName, dpnId);
422                         return;
423                     }
424                     LOG.debug("NAT Service : Removing default SNAT miss entry flow entity for router {} with "
425                         + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
426                     mdsalManager.removeFlow(flowEntity);
427
428                 } catch (Exception ex) {
429                     LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",
430                         flowEntity, ex);
431                     return;
432                 }
433                 LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}",
434                     dpnId, routerName);
435
436                 //best effort to check IntExt model
437                 naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel);
438             }
439         } catch (Exception ex) {
440             LOG.debug("Exception while handling naptSwitch down for router {} : {}", routerName, ex);
441         }
442     }
443
444     private void installDefaultNatRouteForRouterExternalSubnets(BigInteger dpnId, List<Uuid> externalSubnetIds) {
445         if (externalSubnetIds == null) {
446             LOG.debug("NAT Service : No external subnets for router");
447             return;
448         }
449
450         for (Uuid subnetId : externalSubnetIds) {
451             long vpnIdForSubnet = NatUtil.getExternalSubnetVpnId(dataBroker, subnetId);
452             if (vpnIdForSubnet != NatConstants.INVALID_ID) {
453                 LOG.info("NAT Service : Installing default routes in FIB on dpn {} for subnetId {} with vpnId {}",
454                         dpnId, subnetId, vpnIdForSubnet);
455                 snatDefaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnIdForSubnet, subnetId.getValue(),
456                         idManager);
457             } else {
458                 LOG.debug("NAT Service : No vpnID for subnet {} found", subnetId);
459             }
460         }
461     }
462 }