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