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