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