Internet BGPVPN traffic is not working for IPv6
[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.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
24 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
25 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
26 import org.opendaylight.netvirt.elanmanager.api.IElanService;
27 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
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.adjacency.list.Adjacency;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIpsKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.ExternalGatewayInfo;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.external_gateway_info.ExternalFixedIps;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @Singleton
66 public class NeutronvpnNatManager implements AutoCloseable {
67     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnNatManager.class);
68     private static final int EXTERNAL_NO_CHANGE = 0;
69     private static final int EXTERNAL_ADDED = 1;
70     private static final int EXTERNAL_REMOVED = 2;
71     private static final int EXTERNAL_CHANGED = 3;
72
73     private final DataBroker dataBroker;
74     private final NeutronvpnUtils neutronvpnUtils;
75     private final NeutronvpnManager nvpnManager;
76     private final IElanService elanService;
77
78     @Inject
79     public NeutronvpnNatManager(final DataBroker dataBroker, final NeutronvpnUtils neutronvpnUtils,
80                                   final NeutronvpnManager neutronvpnManager, final IElanService elanService) {
81         this.dataBroker = dataBroker;
82         this.neutronvpnUtils = neutronvpnUtils;
83         this.nvpnManager = neutronvpnManager;
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(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 = origExtGw.getExternalFixedIps();
213                         HashSet<String> origFixedIpSet = new HashSet<>();
214                         for (ExternalFixedIps fixedIps : origExtFixedIps) {
215                             origFixedIpSet.add(fixedIps.getIpAddress().stringValue());
216                         }
217                         List<ExternalFixedIps> newExtFixedIps = newExtGw.getExternalFixedIps();
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();
331             if (rtrList == null) {
332                 rtrList = new ArrayList<>();
333             }
334             rtrList.add(routerId);
335             builder.setRouterIds(rtrList);
336             if (NeutronvpnUtils.isFlatOrVlanNetwork(input)) {
337                 builder.setVpnid(extNetId);
338             }
339
340             Networks networkss = builder.build();
341             // Add Networks object to the ExternalNetworks list
342             LOG.trace("Updating externalnetworks {}", networkss);
343             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier,
344                     networkss);
345             LOG.trace("Updated externalnetworks successfully to CONFIG Datastore");
346             //get vpn external form this network external to setup vpnInternet for ipv6
347             Uuid vpnExternal = neutronvpnUtils.getVpnForNetwork(extNetId);
348             if (vpnExternal == null) {
349                 LOG.debug("addExternalNetworkToRouter : no vpnExternal for Network {}", extNetId);
350             }
351             LOG.debug("addExternalNetworkToRouter : the vpnExternal {}", vpnExternal);
352             //get subnetmap associate to the router, any subnetmap "external" could be existing
353             List<Subnetmap> snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId);
354             LOG.debug("addExternalNetworkToRouter : the vpnExternal {} subnetmap to be set with vpnInternet {}",
355                     vpnExternal, snList);
356             for (Subnetmap sn : snList) {
357                 if (sn.getInternetVpnId() == null) {
358                     continue;
359                 }
360                 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
361                 if (ipVers == IpVersionChoice.IPV6) {
362                     LOG.debug("addExternalNetworkToRouter : setup vpnInternet IPv6 for vpnExternal {} subnetmap {}",
363                             vpnExternal, sn);
364                     nvpnManager.updateVpnInternetForSubnet(sn, vpnExternal, true);
365                 }
366             }
367         } catch (TransactionCommitFailedException | ReadFailedException ex) {
368             LOG.error("Creation of externalnetworks failed for {}",
369                 extNetId.getValue(), ex);
370         }
371     }
372
373     public void removeExternalNetworkFromRouter(Uuid origExtNetId, Router update,
374             List<ExternalFixedIps> origExtFixedIps) {
375         Uuid routerId = update.getUuid();
376
377         // Remove the router to the ExtRouters list
378         removeExternalRouter(update);
379
380         //Remove router entry from floating-ip-info list
381         removeRouterFromFloatingIpInfo(update, dataBroker);
382
383         // Remove the router from External Subnets
384         removeRouterFromExternalSubnets(routerId, origExtNetId, origExtFixedIps);
385
386         // Remove the router from the ExternalNetworks list
387         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
388             .child(Networks.class, new NetworksKey(origExtNetId)).build();
389         Optional<Networks> optionalNets = null;
390         try {
391             optionalNets = SingleTransactionDataBroker.syncReadOptional(dataBroker,
392                                             LogicalDatastoreType.CONFIGURATION, netsIdentifier);
393         } catch (ReadFailedException ex) {
394             LOG.error("removeExternalNetworkFromRouter: Failed to remove provider network {} from router {}",
395                       origExtNetId.getValue(), routerId.getValue(), ex);
396             return;
397         }
398         if (!optionalNets.isPresent()) {
399             LOG.error("removeExternalNetworkFromRouter: Provider Network {} not present in the NVPN datamodel",
400                       origExtNetId.getValue());
401             return;
402         }
403         Networks nets = optionalNets.get();
404         try {
405             NetworksBuilder builder = new NetworksBuilder(nets);
406             List<Uuid> rtrList = builder.getRouterIds();
407             if (rtrList != null) {
408                 rtrList.remove(routerId);
409                 builder.setRouterIds(rtrList);
410                 Networks networkss = builder.build();
411                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
412                         netsIdentifier, networkss);
413                 LOG.trace("removeExternalNetworkFromRouter: Remove router {} from External Networks node {}",
414                           routerId, origExtNetId.getValue());
415             }
416         } catch (TransactionCommitFailedException ex) {
417             LOG.error("removeExternalNetworkFromRouter: Failed to remove provider network {} from router {}",
418                       origExtNetId.getValue(), routerId.getValue(), ex);
419         }
420
421         // Remove the vpnInternetId fromSubnetmap
422         Network net = neutronvpnUtils.getNeutronNetwork(nets.getId());
423         List<Uuid> submapIds = neutronvpnUtils.getPrivateSubnetsToExport(net, /*internetVpnId*/ null);
424         for (Uuid snId : submapIds) {
425             Subnetmap subnetMap = neutronvpnUtils.getSubnetmap(snId);
426             if (subnetMap == null || subnetMap.getInternetVpnId() == null) {
427                 LOG.error("removeExternalNetworkFromRouter: Can not find Subnetmap for SubnetId {} in ConfigDS",
428                           snId.getValue());
429                 continue;
430             }
431             LOG.trace("removeExternalNetworkFromRouter: Remove Internet VPN Id {} from SubnetMap {}",
432                       subnetMap.getInternetVpnId(), subnetMap.getId());
433             IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetMap.getSubnetIp());
434             if (ipVers == IpVersionChoice.IPV6) {
435                 nvpnManager.updateVpnInternetForSubnet(subnetMap, subnetMap.getInternetVpnId(), false);
436                 LOG.debug("removeExternalNetworkFromRouter: Withdraw IPv6 routes from VPN {}",
437                           subnetMap.getInternetVpnId());
438             }
439         }
440     }
441
442     public void addExternalRouter(Router update) {
443         Uuid routerId = update.getUuid();
444         Uuid extNetId = update.getExternalGatewayInfo().getExternalNetworkId();
445         Uuid gatewayPortId = update.getGatewayPortId();
446         // Create and add Routers object for this Router to the ExtRouters list
447
448         // Create a Routers object
449         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
450
451         try {
452             Network input = neutronvpnUtils.getNeutronNetwork(extNetId);
453             ProviderTypes providerNwType = NeutronvpnUtils.getProviderNetworkType(input);
454             if (providerNwType == null) {
455                 LOG.error("Unable to get Network Provider Type for network {}", input.getUuid().getValue());
456                 return;
457             }
458             Optional<Routers> optionalRouters =
459                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
460                             routersIdentifier);
461             LOG.trace("Creating/Updating a new Routers node: {}", routerId.getValue());
462             RoutersBuilder builder = null;
463             if (optionalRouters.isPresent()) {
464                 builder = new RoutersBuilder(optionalRouters.get());
465             } else {
466                 builder = new RoutersBuilder().withKey(new RoutersKey(routerId.getValue()));
467             }
468             builder.setRouterName(routerId.getValue());
469             builder.setNetworkId(extNetId);
470             builder.setEnableSnat(update.getExternalGatewayInfo().isEnableSnat());
471
472             ArrayList<ExternalIps> externalIps = new ArrayList<>();
473             for (ExternalFixedIps fixedIps : update.getExternalGatewayInfo().getExternalFixedIps()) {
474                 addExternalFixedIpToExternalIpsList(externalIps, fixedIps);
475             }
476             builder.setExternalIps(externalIps);
477
478             if (gatewayPortId != null) {
479                 LOG.trace("Setting/Updating gateway Mac for router {}", routerId.getValue());
480                 Port port = neutronvpnUtils.getNeutronPort(gatewayPortId);
481                 if (port != null && port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_GATEWAY_INF)) {
482                     builder.setExtGwMacAddress(port.getMacAddress().getValue());
483                 }
484             }
485             List<Uuid> subList = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
486             builder.setSubnetIds(subList);
487             Routers routers = builder.build();
488             // Add Routers object to the ExtRouters list
489             LOG.trace("Creating extrouters {}", routers);
490             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersIdentifier,
491                     builder.build());
492             LOG.trace("Wrote successfully Routers to CONFIG Datastore");
493
494         } catch (ReadFailedException | TransactionCommitFailedException ex) {
495             LOG.error("Creation of extrouters failed for router {} failed",
496                 routerId.getValue(), ex);
497         }
498     }
499
500     // TODO Clean up the exception handling
501     @SuppressWarnings("checkstyle:IllegalCatch")
502     private void removeExternalRouter(Router update) {
503         Uuid routerId = update.getUuid();
504
505         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
506
507         try {
508             Optional<Routers> optionalRouters =
509                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
510                             routersIdentifier);
511             LOG.trace(" Removing Routers node {}", routerId.getValue());
512             if (optionalRouters.isPresent()) {
513                 RoutersBuilder builder = new RoutersBuilder(optionalRouters.get());
514                 builder.setExternalIps(null);
515                 builder.setSubnetIds(null);
516                 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
517                         routersIdentifier);
518                 LOG.trace("Removed router {} from extrouters", routerId.getValue());
519             }
520         } catch (TransactionCommitFailedException | ReadFailedException ex) {
521             LOG.error("Removing extrouter {} from extrouters failed", routerId.getValue(), ex);
522         }
523     }
524
525     private void removeRouterFromFloatingIpInfo(Router update, DataBroker broker) {
526         Uuid routerId = update.getUuid();
527         InstanceIdentifier.InstanceIdentifierBuilder<RouterPorts> routerPortsIdentifierBuilder = InstanceIdentifier
528                 .builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId.getValue()));
529         try {
530             Optional<RouterPorts> optionalRouterPorts =
531                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
532                             routerPortsIdentifierBuilder.build());
533             if (optionalRouterPorts.isPresent()) {
534                 SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
535                         routerPortsIdentifierBuilder.build());
536             }
537         } catch (ReadFailedException | TransactionCommitFailedException e) {
538             LOG.error("Failed to read from FloatingIpInfo DS for routerid {}", routerId, e);
539         }
540     }
541
542     // TODO Clean up the exception handling
543     @SuppressWarnings("checkstyle:IllegalCatch")
544     private void handleExternalFixedIpsForRouter(Router update) {
545         Uuid routerId = update.getUuid();
546         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
547         try {
548             Optional<Routers> optionalRouters =
549                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
550                             routersIdentifier);
551             LOG.trace("Updating External Fixed IPs Routers node {}", routerId.getValue());
552             if (optionalRouters.isPresent()) {
553                 RoutersBuilder builder = new RoutersBuilder(optionalRouters.get());
554                 List<ExternalIps> externalIps = new ArrayList<>();
555                 for (ExternalFixedIps fixedIps : update.getExternalGatewayInfo().getExternalFixedIps()) {
556                     addExternalFixedIpToExternalIpsList(externalIps, fixedIps);
557                 }
558
559                 builder.setExternalIps(externalIps);
560
561                 updateExternalSubnetsForRouter(routerId, update.getExternalGatewayInfo().getExternalNetworkId(),
562                         update.getExternalGatewayInfo().getExternalFixedIps());
563                 Routers routerss = builder.build();
564                 LOG.trace("Updating external fixed ips for router {} with value {}", routerId.getValue(), routerss);
565                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersIdentifier,
566                         routerss);
567                 LOG.trace("Added External Fixed IPs successfully for Routers to CONFIG Datastore");
568             }
569         } catch (TransactionCommitFailedException | ReadFailedException ex) {
570             LOG.error("Updating extfixedips for {} in extrouters failed", routerId.getValue(), ex);
571         }
572     }
573
574     public void handleSubnetsForExternalRouter(Uuid routerId) {
575         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
576
577         try {
578             Optional<Routers> optionalRouters =
579                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
580                             routersIdentifier);
581             LOG.trace("Updating Internal subnets for Routers node: {}", routerId.getValue());
582             RoutersBuilder builder = null;
583             if (optionalRouters.isPresent()) {
584                 builder = new RoutersBuilder(optionalRouters.get());
585             } else {
586                 LOG.debug("No Routers element found for router {}", routerId.getValue());
587                 return;
588             }
589             List<Uuid> subList = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
590             builder.setSubnetIds(subList);
591             Routers routerss = builder.build();
592             // Add Routers object to the ExtRouters list
593             LOG.trace("Updating extrouters {}", routerss);
594             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
595                     routersIdentifier, routerss);
596             LOG.trace("Updated successfully Routers to CONFIG Datastore");
597         } catch (TransactionCommitFailedException | ReadFailedException ex) {
598             LOG.error("Updation of internal subnets for extrouters failed for router {}",
599                 routerId.getValue(), ex);
600         }
601     }
602
603     private void handleSnatSettingChangeForRouter(Router update) {
604         Uuid routerId = update.getUuid();
605
606         InstanceIdentifier<Routers> routersIdentifier = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
607
608         try {
609             Optional<Routers> optionalRouters =
610                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
611                             routersIdentifier);
612             LOG.trace("Updating Internal subnets for Routers node: {}", routerId.getValue());
613             RoutersBuilder builder = null;
614             if (optionalRouters.isPresent()) {
615                 builder = new RoutersBuilder(optionalRouters.get());
616             } else {
617                 LOG.trace("No Routers element found for router name {}", routerId.getValue());
618                 return;
619             }
620             builder.setEnableSnat(update.getExternalGatewayInfo().isEnableSnat());
621             Routers routerss = builder.build();
622             // Add Routers object to the ExtRouters list
623             LOG.trace("Updating extrouters for snat change {}", routerss);
624             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
625                     routersIdentifier, routerss);
626             LOG.trace("Updated successfully Routers to CONFIG Datastore");
627
628         } catch (TransactionCommitFailedException | ReadFailedException ex) {
629             LOG.error("Updation of snat for extrouters failed for router {}", routerId.getValue(), ex);
630         }
631     }
632
633     public void updateOrAddExternalSubnet(Uuid networkId, Uuid subnetId, List<Uuid> routerIds) {
634         Optional<Subnets> optionalExternalSubnets = neutronvpnUtils.getOptionalExternalSubnets(subnetId);
635         if (optionalExternalSubnets.isPresent()) {
636             LOG.trace("Will update external subnet {} with networkId {} and routerIds {}",
637                     subnetId, networkId, routerIds);
638             updateExternalSubnet(networkId, subnetId, routerIds);
639         } else {
640             LOG.trace("Will add external subnet {} with networkId {} and routerIds {}",
641                     subnetId, networkId, routerIds);
642             addExternalSubnet(networkId, subnetId, routerIds);
643         }
644     }
645
646     public void addExternalSubnet(Uuid networkId, Uuid subnetId, List<Uuid> routerIds) {
647         InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
648                 .child(Subnets.class, new SubnetsKey(subnetId)).build();
649         try {
650             Subnets newExternalSubnets = createSubnets(subnetId, networkId, routerIds);
651             LOG.debug("Creating external subnet {}", newExternalSubnets);
652             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier,
653                     newExternalSubnets);
654         } catch (TransactionCommitFailedException ex) {
655             LOG.error("Creation of External Subnets {} failed", subnetId, ex);
656         }
657     }
658
659     public void updateExternalSubnet(Uuid networkId, Uuid subnetId, List<Uuid> routerIds) {
660         InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
661                 .child(Subnets.class, new SubnetsKey(subnetId)).build();
662         try {
663             Subnets newExternalSubnets = createSubnets(subnetId, networkId, routerIds);
664             LOG.debug("Updating external subnet {}", newExternalSubnets);
665             SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier,
666                     newExternalSubnets);
667         } catch (TransactionCommitFailedException ex) {
668             LOG.error("Update of External Subnets {} failed", subnetId, ex);
669         }
670     }
671
672     public void removeExternalSubnet(Uuid networkId, Uuid subnetId) {
673         removeAdjacencyAndLearnedEntriesforExternalSubnet(networkId, subnetId);
674         InstanceIdentifier<Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
675                 .child(Subnets.class, new SubnetsKey(subnetId)).build();
676         try {
677             LOG.debug("Removing external subnet {}", subnetId);
678             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
679         } catch (TransactionCommitFailedException ex) {
680             LOG.error("Deletion of External Subnets {} failed", subnetId, ex);
681         }
682     }
683
684     public void addRouterIdToExternalSubnet(Uuid networkId, Uuid subnetId, Uuid routerId) {
685         Optional<Subnets> optionalExternalSubnets = neutronvpnUtils.getOptionalExternalSubnets(subnetId);
686         if (optionalExternalSubnets.isPresent()) {
687             Subnets subnets = optionalExternalSubnets.get();
688             List<Uuid> routerIds;
689             if (subnets.getRouterIds() != null) {
690                 routerIds = subnets.getRouterIds();
691             } else {
692                 routerIds = new ArrayList<>();
693             }
694
695             if (subnets.getExternalNetworkId() != null
696                     && subnets.getExternalNetworkId().equals(networkId) && !routerIds.contains(routerId)) {
697                 LOG.debug("Will add routerID {} for external subnet {}.", routerId, subnetId);
698                 routerIds.add(routerId);
699                 updateExternalSubnet(networkId, subnetId, routerIds);
700             }
701         }
702     }
703
704     private static Subnets createSubnets(Uuid subnetId, Uuid networkId, List<Uuid> routerIds) {
705         SubnetsBuilder subnetsBuilder = new SubnetsBuilder();
706         subnetsBuilder.withKey(new SubnetsKey(subnetId));
707         subnetsBuilder.setId(subnetId);
708         subnetsBuilder.setVpnId(subnetId);
709         subnetsBuilder.setExternalNetworkId(networkId);
710         if (routerIds != null) {
711             subnetsBuilder.setRouterIds(routerIds);
712         }
713
714         return subnetsBuilder.build();
715     }
716
717     private void updateExternalSubnetsForRouter(Uuid routerId, Uuid externalNetworkId,
718             List<ExternalFixedIps> externalFixedIps) {
719         LOG.debug("Updating external subnets for router {} for external network ID {}",
720                 routerId, externalNetworkId);
721         Set<Uuid> subnetsUuidsSet = getExternalSubnetsUuidsSetForFixedIps(externalFixedIps);
722         for (Uuid subnetId : subnetsUuidsSet) {
723             addRouterIdToExternalSubnet(externalNetworkId, subnetId, routerId);
724         }
725     }
726
727     private void removeRouterFromExternalSubnets(Uuid routerId, Uuid externalNetworkId,
728             List<ExternalFixedIps> externalFixedIps) {
729         LOG.debug("Removing routerID {} from external subnets of external network{}",
730                 routerId, externalNetworkId);
731
732         List<Subnets> fixedIpsSubnets = getSubnets(getExternalSubnetsUuidsSetForFixedIps(externalFixedIps));
733         for (Subnets subnets : fixedIpsSubnets) {
734             Uuid subnetId = subnets.getId();
735             List<Uuid> routerIds = subnets.getRouterIds();
736             if (routerIds != null) {
737                 if (subnets.getExternalNetworkId() != null
738                         && subnets.getExternalNetworkId().equals(externalNetworkId)
739                         && routerIds.contains(routerId)) {
740                     routerIds.remove(routerId);
741                     LOG.debug("Will remove routerIDs {} from external subnet {} router ID {}",
742                         routerIds, subnetId, routerId);
743                     addExternalSubnet(externalNetworkId, subnetId, routerIds);
744                 }
745             }
746         }
747     }
748
749     private static Set<Uuid> getExternalSubnetsUuidsSetForFixedIps(List<ExternalFixedIps> externalFixedIps) {
750         Set<Uuid> subnetsUuidsSet = new HashSet<>();
751         for (ExternalFixedIps externalFixedIp : externalFixedIps) {
752             subnetsUuidsSet.add(externalFixedIp.getSubnetId());
753         }
754
755         return subnetsUuidsSet;
756     }
757
758     private List<Subnets> getSubnets(Set<Uuid> subnetsUuidsSet) {
759         List<Subnets> subnetsList = new ArrayList<>();
760         for (Uuid subnetId : subnetsUuidsSet) {
761             Optional<Subnets> optionalSubnets = neutronvpnUtils.getOptionalExternalSubnets(subnetId);
762             if (optionalSubnets.isPresent()) {
763                 subnetsList.add(optionalSubnets.get());
764             }
765         }
766
767         return subnetsList;
768     }
769
770     private static void addExternalFixedIpToExternalIpsList(List<ExternalIps> externalIps, ExternalFixedIps fixedIps) {
771         Uuid subnetId = fixedIps.getSubnetId();
772         String ip = fixedIps.getIpAddress().stringValue();
773         ExternalIpsBuilder externalIpsBuilder = new ExternalIpsBuilder();
774         externalIpsBuilder.withKey(new ExternalIpsKey(ip, subnetId));
775         externalIpsBuilder.setIpAddress(ip);
776         externalIpsBuilder.setSubnetId(subnetId);
777         externalIps.add(externalIpsBuilder.build());
778     }
779
780     private void removeAdjacencyAndLearnedEntriesforExternalSubnet(Uuid extNetId, Uuid extSubnetId) {
781         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
782         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
783             LOG.error("No external ports attached to external network {}", extNetId.getValue());
784             return;
785         }
786
787         for (String infName : extElanInterfaces) {
788             InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
789                 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
790             InstanceIdentifier<Adjacencies> adjacenciesIdentifier = vpnIfIdentifier.augmentation(Adjacencies.class);
791             try {
792                 // Looking for existing prefix in MDSAL database
793                 Optional<Adjacencies> optionalAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
794                     LogicalDatastoreType.CONFIGURATION, adjacenciesIdentifier);
795                 if (optionalAdjacencies.isPresent()) {
796                     List<Adjacency> adjacencies = optionalAdjacencies.get().getAdjacency();
797                     Iterator<Adjacency> adjacencyIter = adjacencies.iterator();
798                     while (adjacencyIter.hasNext()) {
799                         Adjacency adjacency = adjacencyIter.next();
800                         if (!adjacency.getSubnetId().equals(extSubnetId)) {
801                             continue;
802                         }
803                         InstanceIdentifier<Adjacency> adjacencyIdentifier =
804                             adjacenciesIdentifier.child(Adjacency.class, new AdjacencyKey(adjacency.getIpAddress()));
805                         SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
806                             adjacencyIdentifier);
807                         LOG.trace("Removed Adjacency for fixedIP {} for port {} on external subnet {} ",
808                             adjacency.getIpAddress(), infName, extSubnetId);
809                         String extNetVpnName = extNetId.getValue();
810                         String learnedSrcIp = adjacency.getIpAddress().split("/")[0];
811                         InstanceIdentifier<LearntVpnVipToPort> id =
812                             NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(extNetVpnName, learnedSrcIp);
813                         Optional<LearntVpnVipToPort> optionalLearntVpnVipToPort = SingleTransactionDataBroker
814                             .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
815                         if (optionalLearntVpnVipToPort.isPresent()) {
816                             neutronvpnUtils.removeLearntVpnVipToPort(extNetVpnName, learnedSrcIp);
817                             LOG.trace("Removed Learnt Entry for fixedIP {} for port {}",
818                                 adjacency.getIpAddress(), infName);
819                         }
820                     }
821                 }
822             } catch (TransactionCommitFailedException | ReadFailedException e) {
823                 LOG.error("exception in removeAdjacencyAndLearnedEntriesforExternalSubnet for interface {}",
824                     infName, e);
825             }
826         }
827     }
828 }