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