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