f87b98ac0272dbed5417119e2f6773bf41af557d
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnNatManager.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.neutronvpn;
9
10 import com.google.common.base.Optional;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Objects;
17 import java.util.Set;
18 import javax.annotation.PreDestroy;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
25 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
26 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
27 import org.opendaylight.netvirt.elanmanager.api.IElanService;
28 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
30 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
31 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
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.adjacency.list.Adjacency;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.ExternalGatewayInfo;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.external_gateway_info.ExternalFixedIps;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67 @Singleton
68 public class NeutronvpnNatManager implements AutoCloseable {
69     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnNatManager.class);
70     private static final int EXTERNAL_NO_CHANGE = 0;
71     private static final int EXTERNAL_ADDED = 1;
72     private static final int EXTERNAL_REMOVED = 2;
73     private static final int EXTERNAL_CHANGED = 3;
74
75     private final DataBroker dataBroker;
76     private final NeutronvpnUtils neutronvpnUtils;
77     private final NeutronvpnManager nvpnManager;
78     private final IElanService elanService;
79
80     @Inject
81     public NeutronvpnNatManager(final DataBroker dataBroker, final NeutronvpnUtils neutronvpnUtils,
82                                   final NeutronvpnManager neutronvpnManager, final IElanService elanService) {
83         this.dataBroker = dataBroker;
84         this.neutronvpnUtils = neutronvpnUtils;
85         this.nvpnManager = neutronvpnManager;
86         this.elanService = elanService;
87     }
88
89     @Override
90     @PreDestroy
91     public void close() {
92         LOG.info("{} close", getClass().getSimpleName());
93     }
94
95     public void handleExternalNetworkForRouter(@Nullable Router original, Router update) {
96         Uuid routerId = update.getUuid();
97         Uuid origExtNetId = null;
98         Uuid updExtNetId = null;
99         List<ExternalFixedIps> origExtFixedIps;
100
101         LOG.trace("handleExternalNetwork for router {}", routerId);
102         int extNetChanged = externalNetworkChanged(original, update);
103         if (extNetChanged != EXTERNAL_NO_CHANGE) {
104             if (extNetChanged == EXTERNAL_ADDED) {
105                 updExtNetId = update.getExternalGatewayInfo().getExternalNetworkId();
106                 LOG.trace("External Network {} addition detected for router {}", updExtNetId.getValue(),
107                         routerId.getValue());
108                 addExternalNetworkToRouter(update);
109                 return;
110             }
111             if (extNetChanged == EXTERNAL_REMOVED) {
112                 origExtNetId = original.getExternalGatewayInfo().getExternalNetworkId();
113                 origExtFixedIps = original.getExternalGatewayInfo().getExternalFixedIps();
114                 LOG.trace("External Network removal detected for router {}", routerId.getValue());
115                 removeExternalNetworkFromRouter(origExtNetId, update, origExtFixedIps);
116                 //gateway mac unset handled as part of gateway clear deleting top-level routers node
117                 return;
118             }
119
120             origExtNetId = original.getExternalGatewayInfo().getExternalNetworkId();
121             origExtFixedIps = original.getExternalGatewayInfo().getExternalFixedIps();
122             updExtNetId = update.getExternalGatewayInfo().getExternalNetworkId();
123             LOG.trace("External Network changed from {} to {} for router {}",
124                 origExtNetId.getValue(), updExtNetId.getValue(), routerId.getValue());
125             removeExternalNetworkFromRouter(origExtNetId, update, origExtFixedIps);
126             addExternalNetworkToRouter(update);
127             return;
128         }
129
130         if (snatSettingChanged(original, update)) {
131             LOG.trace("SNAT settings on gateway changed for router {}", routerId.getValue());
132             handleSnatSettingChangeForRouter(update);
133         }
134
135         if (externalFixedIpsChanged(original, update)) {
136             LOG.trace("External Fixed IPs changed for router {}", routerId.getValue());
137             handleExternalFixedIpsForRouter(update);
138         }
139     }
140
141     private static int externalNetworkChanged(Router original, Router update) {
142         String origExtNet = null;
143         String newExtNet = null;
144         if (original != null && original.getExternalGatewayInfo() != null) {
145             origExtNet = original.getExternalGatewayInfo().getExternalNetworkId().getValue();
146         }
147
148         if (update != null && update.getExternalGatewayInfo() != null) {
149             newExtNet = update.getExternalGatewayInfo().getExternalNetworkId().getValue();
150         }
151
152         if (origExtNet == null) {
153             if (newExtNet == null) {
154                 return EXTERNAL_NO_CHANGE;
155             }
156             return EXTERNAL_ADDED;
157         } else {
158             if (newExtNet == null) {
159                 return EXTERNAL_REMOVED;
160             }
161             if (!origExtNet.equals(newExtNet)) {
162                 return EXTERNAL_CHANGED;
163             }
164             return EXTERNAL_NO_CHANGE;
165         }
166     }
167
168     private static boolean snatSettingChanged(Router orig, Router update) {
169         ExternalGatewayInfo origExtGw = null;
170         ExternalGatewayInfo newExtGw = null;
171         if (orig != null && orig.getExternalGatewayInfo() != null) {
172             origExtGw = orig.getExternalGatewayInfo();
173         }
174
175         if (update != null && update.getExternalGatewayInfo() != null) {
176             newExtGw = update.getExternalGatewayInfo();
177         }
178
179         if (origExtGw == null) {
180             if (newExtGw != null) {
181                 return true;
182             }
183         } else if (newExtGw == null || !Objects.equals(origExtGw.isEnableSnat(), newExtGw.isEnableSnat())) {
184             return true;
185         }
186         return false;
187     }
188
189     private static boolean externalFixedIpsChanged(Router orig, Router update) {
190         ExternalGatewayInfo origExtGw = null;
191         ExternalGatewayInfo newExtGw = null;
192         if (orig != null && orig.getExternalGatewayInfo() != null) {
193             origExtGw = orig.getExternalGatewayInfo();
194         }
195
196         if (update != null && update.getExternalGatewayInfo() != null) {
197             newExtGw = update.getExternalGatewayInfo();
198         }
199
200         if (origExtGw == null && newExtGw != null && newExtGw.getExternalFixedIps() != null && !newExtGw
201                 .getExternalFixedIps().isEmpty()) {
202             return true;
203         }
204
205         if (newExtGw == null && origExtGw != null && origExtGw.getExternalFixedIps() != null && !origExtGw
206                 .getExternalFixedIps().isEmpty()) {
207             return true;
208         }
209
210         if (origExtGw != null && newExtGw != null) {
211             if (origExtGw.getExternalFixedIps() != null) {
212                 if (!origExtGw.getExternalFixedIps().isEmpty()) {
213                     if (newExtGw.getExternalFixedIps() != null && !newExtGw.getExternalFixedIps().isEmpty()) {
214                         List<ExternalFixedIps> origExtFixedIps = origExtGw.getExternalFixedIps();
215                         HashSet<String> origFixedIpSet = new HashSet<>();
216                         for (ExternalFixedIps fixedIps : origExtFixedIps) {
217                             origFixedIpSet.add(fixedIps.getIpAddress().stringValue());
218                         }
219                         List<ExternalFixedIps> newExtFixedIps = newExtGw.getExternalFixedIps();
220                         HashSet<String> updFixedIpSet = new HashSet<>();
221                         for (ExternalFixedIps fixedIps : newExtFixedIps) {
222                             updFixedIpSet.add(fixedIps.getIpAddress().stringValue());
223                         }
224                         // returns true if external subnets have changed
225                         return !origFixedIpSet.equals(updFixedIpSet) ? true : false;
226                     }
227                     return true;
228                 } else if (newExtGw.getExternalFixedIps() != null && !newExtGw.getExternalFixedIps().isEmpty()) {
229                     return true;
230                 }
231             } else if (newExtGw.getExternalFixedIps() != null && !newExtGw.getExternalFixedIps().isEmpty()) {
232                 return true;
233             }
234         }
235         return false;
236     }
237
238     public void addExternalNetwork(Network net) {
239         Uuid extNetId = net.getUuid();
240
241         // Create and add Networks object for this External Network to the ExternalNetworks list
242         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
243             .child(Networks.class, new NetworksKey(extNetId)).build();
244
245         try {
246             LOG.trace(" Creating/Updating a new Networks node {}", extNetId.getValue());
247             Optional<Networks> optionalNets =
248                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
249                             netsIdentifier);
250             if (optionalNets.isPresent()) {
251                 LOG.error("External Network {} already detected to be present", extNetId.getValue());
252                 return;
253             }
254             ProviderTypes provType = NeutronvpnUtils.getProviderNetworkType(net);
255             if (provType == null) {
256                 LOG.error("Unable to get Network Provider Type for network {}", extNetId);
257                 return;
258             }
259             NetworksBuilder builder = null;
260             builder = new NetworksBuilder().withKey(new NetworksKey(extNetId)).setId(extNetId);
261             builder.setVpnid(neutronvpnUtils.getVpnForNetwork(extNetId));
262             builder.setRouterIds(new ArrayList<>());
263             builder.setProviderNetworkType(provType);
264
265             Networks networkss = builder.build();
266             // Add Networks object to the ExternalNetworks list
267             LOG.trace("Creating externalnetworks {}", networkss);
268             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier,
269                     networkss);
270             LOG.trace("Wrote externalnetwork successfully to CONFIG Datastore");
271         } catch (TransactionCommitFailedException | ReadFailedException ex) {
272             LOG.error("Creation of External Network {} failed", extNetId.getValue(), ex);
273         }
274     }
275
276     public void removeExternalNetwork(Network net) {
277         Uuid extNetId = net.getUuid();
278
279         // Create and add Networks object for this External Network to the ExternalNetworks list
280         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
281             .child(Networks.class, new NetworksKey(extNetId)).build();
282
283         try {
284             Optional<Networks> optionalNets =
285                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
286                             netsIdentifier);
287             LOG.trace("Removing Networks node {}", extNetId.getValue());
288             if (!optionalNets.isPresent()) {
289                 LOG.error("External Network {} not available in the datastore", extNetId.getValue());
290                 return;
291             }
292             // Delete Networks object from the ExternalNetworks list
293             LOG.trace("Deleting External Network {}", extNetId.getValue());
294             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier);
295             LOG.trace("Deleted External Network {} successfully from CONFIG Datastore", extNetId.getValue());
296
297         } catch (TransactionCommitFailedException | ReadFailedException ex) {
298             LOG.error("Deletion of External Network {} failed", extNetId.getValue(), ex);
299         }
300     }
301
302     private void addExternalNetworkToRouter(Router update) {
303         Uuid routerId = update.getUuid();
304         Uuid extNetId = update.getExternalGatewayInfo().getExternalNetworkId();
305         List<ExternalFixedIps> externalFixedIps = update.getExternalGatewayInfo().getExternalFixedIps();
306
307         try {
308             Network input = neutronvpnUtils.getNeutronNetwork(extNetId);
309             ProviderTypes providerNwType = NeutronvpnUtils.getProviderNetworkType(input);
310             if (providerNwType == null) {
311                 LOG.error("Unable to get Network Provider Type for network {}", input.getUuid().getValue());
312                 return;
313             }
314             // Add this router to the ExtRouters list
315             addExternalRouter(update);
316
317             // Update External Subnets for this router
318             updateExternalSubnetsForRouter(routerId, extNetId, externalFixedIps);
319
320             // Create and add Networks object for this External Network to the ExternalNetworks list
321             InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
322                 .child(Networks.class, new NetworksKey(extNetId)).build();
323
324             Optional<Networks> optionalNets =
325                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
326                             netsIdentifier);
327             if (!optionalNets.isPresent()) {
328                 LOG.error("External Network {} not present in the NVPN datamodel", extNetId.getValue());
329                 return;
330             }
331             NetworksBuilder builder = new NetworksBuilder(optionalNets.get());
332             List<Uuid> rtrList = builder.getRouterIds();
333             if (rtrList == null) {
334                 rtrList = new ArrayList<>();
335             }
336             rtrList.add(routerId);
337             builder.setRouterIds(rtrList);
338             if (NeutronvpnUtils.isFlatOrVlanNetwork(input)) {
339                 builder.setVpnid(extNetId);
340             }
341
342             Networks networkss = builder.build();
343             // Add Networks object to the ExternalNetworks list
344             LOG.trace("Updating externalnetworks {}", networkss);
345             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier,
346                     networkss);
347             LOG.trace("Updated externalnetworks successfully to CONFIG Datastore");
348         } catch (TransactionCommitFailedException | ReadFailedException ex) {
349             LOG.error("Creation of externalnetworks failed for {}",
350                 extNetId.getValue(), ex);
351         }
352     }
353
354     public void removeExternalNetworkFromRouter(Uuid origExtNetId, Router update,
355             List<ExternalFixedIps> origExtFixedIps) {
356         Uuid routerId = update.getUuid();
357
358         // Remove the router to the ExtRouters list
359         removeExternalRouter(update);
360
361         //Remove router entry from floating-ip-info list
362         removeRouterFromFloatingIpInfo(update, dataBroker);
363
364         // Remove the router from External Subnets
365         removeRouterFromExternalSubnets(routerId, origExtNetId, origExtFixedIps);
366
367         // Remove the router from the ExternalNetworks list
368         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
369             .child(Networks.class, new NetworksKey(origExtNetId)).build();
370         Optional<Networks> optionalNets = null;
371         try {
372             optionalNets = SingleTransactionDataBroker.syncReadOptional(dataBroker,
373                                             LogicalDatastoreType.CONFIGURATION, netsIdentifier);
374         } catch (ReadFailedException ex) {
375             LOG.error("removeExternalNetworkFromRouter: Failed to remove provider network {} from router {}",
376                       origExtNetId.getValue(), routerId.getValue(), ex);
377             return;
378         }
379         if (!optionalNets.isPresent()) {
380             LOG.error("removeExternalNetworkFromRouter: Provider Network {} not present in the NVPN datamodel",
381                       origExtNetId.getValue());
382             return;
383         }
384         Networks nets = optionalNets.get();
385         try {
386             NetworksBuilder builder = new NetworksBuilder(nets);
387             List<Uuid> rtrList = builder.getRouterIds();
388             if (rtrList != null) {
389                 rtrList.remove(routerId);
390                 builder.setRouterIds(rtrList);
391                 Networks networkss = builder.build();
392                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
393                         netsIdentifier, networkss);
394                 LOG.trace("removeExternalNetworkFromRouter: Remove router {} from External Networks node {}",
395                           routerId, origExtNetId.getValue());
396             }
397         } catch (TransactionCommitFailedException ex) {
398             LOG.error("removeExternalNetworkFromRouter: Failed to remove provider network {} from router {}",
399                       origExtNetId.getValue(), routerId.getValue(), ex);
400         }
401     }
402
403     public void addExternalRouter(Router update) {
404         Uuid routerId = update.getUuid();
405         Uuid extNetId = update.getExternalGatewayInfo().getExternalNetworkId();
406         Uuid gatewayPortId = update.getGatewayPortId();
407         // Create and add Routers object for this Router to the ExtRouters list
408
409         // Create a Routers object
410         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
411
412         try {
413             Network input = neutronvpnUtils.getNeutronNetwork(extNetId);
414             ProviderTypes providerNwType = NeutronvpnUtils.getProviderNetworkType(input);
415             if (providerNwType == null) {
416                 LOG.error("Unable to get Network Provider Type for network {}", input.getUuid().getValue());
417                 return;
418             }
419             Optional<Routers> optionalRouters =
420                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
421                             routersIdentifier);
422             LOG.trace("Creating/Updating a new Routers node: {}", routerId.getValue());
423             RoutersBuilder builder = null;
424             if (optionalRouters.isPresent()) {
425                 builder = new RoutersBuilder(optionalRouters.get());
426             } else {
427                 builder = new RoutersBuilder().withKey(new RoutersKey(routerId.getValue()));
428             }
429             builder.setRouterName(routerId.getValue());
430             builder.setNetworkId(extNetId);
431             builder.setEnableSnat(update.getExternalGatewayInfo().isEnableSnat());
432
433             ArrayList<ExternalIps> externalIps = new ArrayList<>();
434             for (ExternalFixedIps fixedIps : update.getExternalGatewayInfo().nonnullExternalFixedIps()) {
435                 addExternalFixedIpToExternalIpsList(externalIps, fixedIps);
436             }
437             builder.setExternalIps(externalIps);
438
439             if (gatewayPortId != null) {
440                 LOG.trace("Setting/Updating gateway Mac for router {}", routerId.getValue());
441                 Port port = neutronvpnUtils.getNeutronPort(gatewayPortId);
442                 if (port != null && port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_GATEWAY_INF)) {
443                     builder.setExtGwMacAddress(port.getMacAddress().getValue());
444                 }
445             }
446             List<Uuid> subList = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
447             builder.setSubnetIds(subList);
448             Routers routers = builder.build();
449             // Add Routers object to the ExtRouters list
450             LOG.trace("Creating extrouters {}", routers);
451             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersIdentifier,
452                     builder.build());
453             LOG.trace("Wrote successfully Routers to CONFIG Datastore");
454
455         } catch (ReadFailedException | TransactionCommitFailedException ex) {
456             LOG.error("Creation of extrouters failed for router {} failed",
457                 routerId.getValue(), ex);
458         }
459     }
460
461     // TODO Clean up the exception handling
462     @SuppressWarnings("checkstyle:IllegalCatch")
463     private void removeExternalRouter(Router update) {
464         Uuid routerId = update.getUuid();
465
466         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
467
468         try {
469             Optional<Routers> optionalRouters =
470                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
471                             routersIdentifier);
472             LOG.trace(" Removing Routers node {}", routerId.getValue());
473             if (optionalRouters.isPresent()) {
474                 RoutersBuilder builder = new RoutersBuilder(optionalRouters.get());
475                 builder.setExternalIps(null);
476                 builder.setSubnetIds(null);
477                 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
478                         routersIdentifier);
479                 LOG.trace("Removed router {} from extrouters", routerId.getValue());
480             }
481         } catch (TransactionCommitFailedException | ReadFailedException ex) {
482             LOG.error("Removing extrouter {} from extrouters failed", routerId.getValue(), ex);
483         }
484     }
485
486     public void removeNeutronRouterDpns(Router router) {
487         Uuid routerId = router.getUuid();
488         InstanceIdentifier<RouterDpnList> iid = InstanceIdentifier.builder(NeutronRouterDpns.class)
489                 .child(RouterDpnList.class, new RouterDpnListKey(routerId.getValue())).build();
490         neutronvpnUtils.asyncReadAndExecute(LogicalDatastoreType.OPERATIONAL, iid, router.getUuid().toString(),
491             (routerDpnListOptional) -> {
492                 if (routerDpnListOptional.isPresent()) {
493                     if (routerDpnListOptional.get().getDpnVpninterfacesList() != null) {
494                         routerDpnListOptional.get().getDpnVpninterfacesList().stream()
495                                 .filter((dpnList) -> (dpnList != null))
496                                 .forEach((dpnList) -> {
497                                     LOG.warn("DPN {} presence exists while deleting router instance {}",
498                                             dpnList.getDpnId(), routerId);
499                                 });
500                         try {
501                             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, iid);
502                         } catch (TransactionCommitFailedException e) {
503                             LOG.warn("Failed to read from NeutronRouterDpn DS for routerid {}", routerId, e);
504                         }
505                     }
506                 }
507                 return null;
508             });
509     }
510
511     private void removeRouterFromFloatingIpInfo(Router update, DataBroker broker) {
512         Uuid routerId = update.getUuid();
513         InstanceIdentifier.InstanceIdentifierBuilder<RouterPorts> routerPortsIdentifierBuilder = InstanceIdentifier
514                 .builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId.getValue()));
515         try {
516             Optional<RouterPorts> optionalRouterPorts =
517                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
518                             routerPortsIdentifierBuilder.build());
519             if (optionalRouterPorts.isPresent()) {
520                 SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
521                         routerPortsIdentifierBuilder.build());
522             }
523         } catch (ReadFailedException | TransactionCommitFailedException e) {
524             LOG.error("Failed to read from FloatingIpInfo DS for routerid {}", routerId, e);
525         }
526     }
527
528     // TODO Clean up the exception handling
529     @SuppressWarnings("checkstyle:IllegalCatch")
530     private void handleExternalFixedIpsForRouter(Router update) {
531         Uuid routerId = update.getUuid();
532         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
533         try {
534             Optional<Routers> optionalRouters =
535                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
536                             routersIdentifier);
537             LOG.trace("Updating External Fixed IPs Routers node {}", routerId.getValue());
538             if (optionalRouters.isPresent()) {
539                 RoutersBuilder builder = new RoutersBuilder(optionalRouters.get());
540                 List<ExternalIps> externalIps = new ArrayList<>();
541                 for (ExternalFixedIps fixedIps : update.getExternalGatewayInfo().getExternalFixedIps()) {
542                     addExternalFixedIpToExternalIpsList(externalIps, fixedIps);
543                 }
544
545                 builder.setExternalIps(externalIps);
546
547                 updateExternalSubnetsForRouter(routerId, update.getExternalGatewayInfo().getExternalNetworkId(),
548                         update.getExternalGatewayInfo().getExternalFixedIps());
549                 Routers routerss = builder.build();
550                 LOG.trace("Updating external fixed ips for router {} with value {}", routerId.getValue(), routerss);
551                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersIdentifier,
552                         routerss);
553                 LOG.trace("Added External Fixed IPs successfully for Routers to CONFIG Datastore");
554             }
555         } catch (TransactionCommitFailedException | ReadFailedException ex) {
556             LOG.error("Updating extfixedips for {} in extrouters failed", routerId.getValue(), ex);
557         }
558     }
559
560     public void handleSubnetsForExternalRouter(Uuid routerId) {
561         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
562
563         try {
564             Optional<Routers> optionalRouters =
565                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
566                             routersIdentifier);
567             LOG.trace("Updating Internal subnets for Routers node: {}", routerId.getValue());
568             RoutersBuilder builder = null;
569             if (optionalRouters.isPresent()) {
570                 builder = new RoutersBuilder(optionalRouters.get());
571             } else {
572                 LOG.debug("No Routers element found for router {}", routerId.getValue());
573                 return;
574             }
575             List<Uuid> subList = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
576             builder.setSubnetIds(subList);
577             Routers routerss = builder.build();
578             // Add Routers object to the ExtRouters list
579             LOG.trace("Updating extrouters {}", routerss);
580             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
581                     routersIdentifier, routerss);
582             LOG.trace("Updated successfully Routers to CONFIG Datastore");
583         } catch (TransactionCommitFailedException | ReadFailedException ex) {
584             LOG.error("Updation of internal subnets for extrouters failed for router {}",
585                 routerId.getValue(), ex);
586         }
587     }
588
589     private void handleSnatSettingChangeForRouter(Router update) {
590         Uuid routerId = update.getUuid();
591
592         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
593
594         try {
595             Optional<Routers> optionalRouters =
596                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
597                             routersIdentifier);
598             LOG.trace("Updating Internal subnets for Routers node: {}", routerId.getValue());
599             RoutersBuilder builder = null;
600             if (optionalRouters.isPresent()) {
601                 builder = new RoutersBuilder(optionalRouters.get());
602             } else {
603                 LOG.trace("No Routers element found for router name {}", routerId.getValue());
604                 return;
605             }
606             builder.setEnableSnat(update.getExternalGatewayInfo().isEnableSnat());
607             Routers routerss = builder.build();
608             // Add Routers object to the ExtRouters list
609             LOG.trace("Updating extrouters for snat change {}", routerss);
610             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
611                     routersIdentifier, routerss);
612             LOG.trace("Updated successfully Routers to CONFIG Datastore");
613
614         } catch (TransactionCommitFailedException | ReadFailedException ex) {
615             LOG.error("Updation of snat for extrouters failed for router {}", routerId.getValue(), ex);
616         }
617     }
618
619     public void updateOrAddExternalSubnet(Uuid networkId, Uuid subnetId, @Nullable List<Uuid> routerIds) {
620         Optional<Subnets> optionalExternalSubnets = neutronvpnUtils.getOptionalExternalSubnets(subnetId);
621         if (optionalExternalSubnets.isPresent()) {
622             LOG.trace("Will update external subnet {} with networkId {} and routerIds {}",
623                     subnetId, networkId, routerIds);
624             updateExternalSubnet(networkId, subnetId, routerIds);
625         } else {
626             LOG.trace("Will add external subnet {} with networkId {} and routerIds {}",
627                     subnetId, networkId, routerIds);
628             addExternalSubnet(networkId, subnetId, routerIds);
629         }
630     }
631
632     public void addExternalSubnet(Uuid networkId, Uuid subnetId, List<Uuid> routerIds) {
633         InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
634                 .child(Subnets.class, new SubnetsKey(subnetId)).build();
635         try {
636             Subnets newExternalSubnets = createSubnets(subnetId, networkId, routerIds);
637             LOG.debug("Creating external subnet {}", newExternalSubnets);
638             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier,
639                     newExternalSubnets);
640         } catch (TransactionCommitFailedException ex) {
641             LOG.error("Creation of External Subnets {} failed", subnetId, ex);
642         }
643     }
644
645     public void updateExternalSubnet(Uuid networkId, Uuid subnetId, @Nullable List<Uuid> routerIds) {
646         InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
647                 .child(Subnets.class, new SubnetsKey(subnetId)).build();
648         try {
649             Subnets newExternalSubnets = createSubnets(subnetId, networkId, routerIds);
650             LOG.debug("Updating external subnet {}", newExternalSubnets);
651             SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier,
652                     newExternalSubnets);
653         } catch (TransactionCommitFailedException ex) {
654             LOG.error("Update of External Subnets {} failed", subnetId, ex);
655         }
656     }
657
658     public void removeExternalSubnet(Uuid networkId, Uuid subnetId) {
659         removeAdjacencyAndLearnedEntriesforExternalSubnet(networkId, subnetId);
660         InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
661                 .child(Subnets.class, new SubnetsKey(subnetId)).build();
662         try {
663             LOG.debug("Removing external subnet {}", subnetId);
664             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
665         } catch (TransactionCommitFailedException ex) {
666             LOG.error("Deletion of External Subnets {} failed", subnetId, ex);
667         }
668     }
669
670     public void addRouterIdToExternalSubnet(Uuid networkId, Uuid subnetId, Uuid routerId) {
671         Optional<Subnets> optionalExternalSubnets = neutronvpnUtils.getOptionalExternalSubnets(subnetId);
672         if (optionalExternalSubnets.isPresent()) {
673             Subnets subnets = optionalExternalSubnets.get();
674             List<Uuid> routerIds;
675             if (subnets.getRouterIds() != null) {
676                 routerIds = subnets.getRouterIds();
677             } else {
678                 routerIds = new ArrayList<>();
679             }
680
681             if (subnets.getExternalNetworkId() != null
682                     && subnets.getExternalNetworkId().equals(networkId) && !routerIds.contains(routerId)) {
683                 LOG.debug("Will add routerID {} for external subnet {}.", routerId, subnetId);
684                 routerIds.add(routerId);
685                 updateExternalSubnet(networkId, subnetId, routerIds);
686             }
687         }
688     }
689
690     private static Subnets createSubnets(Uuid subnetId, Uuid networkId, @Nullable List<Uuid> routerIds) {
691         SubnetsBuilder subnetsBuilder = new SubnetsBuilder();
692         subnetsBuilder.withKey(new SubnetsKey(subnetId));
693         subnetsBuilder.setId(subnetId);
694         subnetsBuilder.setVpnId(subnetId);
695         subnetsBuilder.setExternalNetworkId(networkId);
696         if (routerIds != null) {
697             subnetsBuilder.setRouterIds(routerIds);
698         }
699
700         return subnetsBuilder.build();
701     }
702
703     private void updateExternalSubnetsForRouter(Uuid routerId, Uuid externalNetworkId,
704             List<ExternalFixedIps> externalFixedIps) {
705         LOG.debug("Updating external subnets for router {} for external network ID {}",
706                 routerId, externalNetworkId);
707         Set<Uuid> subnetsUuidsSet = getExternalSubnetsUuidsSetForFixedIps(externalFixedIps);
708         for (Uuid subnetId : subnetsUuidsSet) {
709             addRouterIdToExternalSubnet(externalNetworkId, subnetId, routerId);
710         }
711     }
712
713     private void removeRouterFromExternalSubnets(Uuid routerId, Uuid externalNetworkId,
714             List<ExternalFixedIps> externalFixedIps) {
715         LOG.debug("Removing routerID {} from external subnets of external network{}",
716                 routerId, externalNetworkId);
717
718         List<Subnets> fixedIpsSubnets = getSubnets(getExternalSubnetsUuidsSetForFixedIps(externalFixedIps));
719         for (Subnets subnets : fixedIpsSubnets) {
720             Uuid subnetId = subnets.getId();
721             List<Uuid> routerIds = subnets.getRouterIds();
722             if (routerIds != null) {
723                 if (subnets.getExternalNetworkId() != null
724                         && subnets.getExternalNetworkId().equals(externalNetworkId)
725                         && routerIds.contains(routerId)) {
726                     routerIds.remove(routerId);
727                     LOG.debug("Will remove routerIDs {} from external subnet {} router ID {}",
728                         routerIds, subnetId, routerId);
729                     addExternalSubnet(externalNetworkId, subnetId, routerIds);
730                 }
731             }
732         }
733     }
734
735     private static Set<Uuid> getExternalSubnetsUuidsSetForFixedIps(List<ExternalFixedIps> externalFixedIps) {
736         Set<Uuid> subnetsUuidsSet = new HashSet<>();
737         for (ExternalFixedIps externalFixedIp : externalFixedIps) {
738             subnetsUuidsSet.add(externalFixedIp.getSubnetId());
739         }
740
741         return subnetsUuidsSet;
742     }
743
744     private List<Subnets> getSubnets(Set<Uuid> subnetsUuidsSet) {
745         List<Subnets> subnetsList = new ArrayList<>();
746         for (Uuid subnetId : subnetsUuidsSet) {
747             Optional<Subnets> optionalSubnets = neutronvpnUtils.getOptionalExternalSubnets(subnetId);
748             if (optionalSubnets.isPresent()) {
749                 subnetsList.add(optionalSubnets.get());
750             }
751         }
752
753         return subnetsList;
754     }
755
756     private static void addExternalFixedIpToExternalIpsList(List<ExternalIps> externalIps, ExternalFixedIps fixedIps) {
757         Uuid subnetId = fixedIps.getSubnetId();
758         String ip = fixedIps.getIpAddress().stringValue();
759         ExternalIpsBuilder externalIpsBuilder = new ExternalIpsBuilder();
760         externalIpsBuilder.withKey(new ExternalIpsKey(ip, subnetId));
761         externalIpsBuilder.setIpAddress(ip);
762         externalIpsBuilder.setSubnetId(subnetId);
763         externalIps.add(externalIpsBuilder.build());
764     }
765
766     private void removeAdjacencyAndLearnedEntriesforExternalSubnet(Uuid extNetId, Uuid extSubnetId) {
767         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
768         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
769             LOG.error("No external ports attached to external network {}", extNetId.getValue());
770             return;
771         }
772
773         for (String infName : extElanInterfaces) {
774             InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
775                 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
776             InstanceIdentifier<Adjacencies> adjacenciesIdentifier = vpnIfIdentifier.augmentation(Adjacencies.class);
777             try {
778                 // Looking for existing prefix in MDSAL database
779                 Optional<Adjacencies> optionalAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
780                     LogicalDatastoreType.CONFIGURATION, adjacenciesIdentifier);
781                 if (optionalAdjacencies.isPresent()) {
782                     List<Adjacency> adjacencies = optionalAdjacencies.get().getAdjacency();
783                     Iterator<Adjacency> adjacencyIter = adjacencies.iterator();
784                     while (adjacencyIter.hasNext()) {
785                         Adjacency adjacency = adjacencyIter.next();
786                         if (!adjacency.getSubnetId().equals(extSubnetId)) {
787                             continue;
788                         }
789                         InstanceIdentifier<Adjacency> adjacencyIdentifier =
790                             adjacenciesIdentifier.child(Adjacency.class, new AdjacencyKey(adjacency.getIpAddress()));
791                         SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
792                             adjacencyIdentifier);
793                         LOG.trace("Removed Adjacency for fixedIP {} for port {} on external subnet {} ",
794                             adjacency.getIpAddress(), infName, extSubnetId);
795                         String extNetVpnName = extNetId.getValue();
796                         String learnedSrcIp = adjacency.getIpAddress().split("/")[0];
797                         InstanceIdentifier<LearntVpnVipToPort> id =
798                             NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(extNetVpnName, learnedSrcIp);
799                         Optional<LearntVpnVipToPort> optionalLearntVpnVipToPort = SingleTransactionDataBroker
800                             .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
801                         if (optionalLearntVpnVipToPort.isPresent()) {
802                             neutronvpnUtils.removeLearntVpnVipToPort(extNetVpnName, learnedSrcIp);
803                             LOG.trace("Removed Learnt Entry for fixedIP {} for port {}",
804                                 adjacency.getIpAddress(), infName);
805                         }
806                     }
807                 }
808             } catch (TransactionCommitFailedException | ReadFailedException e) {
809                 LOG.error("exception in removeAdjacencyAndLearnedEntriesforExternalSubnet for interface {}",
810                     infName, e);
811             }
812         }
813     }
814
815
816 }