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