Cleanup errors for networks of unsupported type
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnManager.java
1 /*
2  * Copyright © 2015, 2017 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 com.google.common.util.concurrent.ListenableFuture;
12 import com.google.common.util.concurrent.SettableFuture;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.EventListener;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Objects;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.Future;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
29 import org.opendaylight.genius.mdsalutil.MDSALUtil;
30 import org.opendaylight.netvirt.elanmanager.api.IElanService;
31 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
32 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
34 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
35 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
42 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
43 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
44 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
115 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
116 import org.opendaylight.yangtools.yang.common.RpcError;
117 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
118 import org.opendaylight.yangtools.yang.common.RpcResult;
119 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
120 import org.slf4j.Logger;
121 import org.slf4j.LoggerFactory;
122
123 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
124     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
125     private final DataBroker dataBroker;
126     private final NeutronvpnNatManager nvpnNatManager;
127     private final NotificationPublishService notificationPublishService;
128     private final VpnRpcService vpnRpcService;
129     private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
130     private final NeutronvpnConfig neutronvpnConfig;
131     private final IElanService elanService;
132
133     public NeutronvpnManager(
134             final DataBroker dataBroker, final NotificationPublishService notiPublishService,
135             final NeutronvpnNatManager vpnNatMgr, final VpnRpcService vpnRpcSrv, final IElanService elanService,
136             final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
137             final NeutronvpnConfig neutronvpnConfig) {
138         this.dataBroker = dataBroker;
139         nvpnNatManager = vpnNatMgr;
140         notificationPublishService = notiPublishService;
141         vpnRpcService = vpnRpcSrv;
142         this.elanService = elanService;
143         floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
144         LOG.info("neutronvpnConfig: {}", neutronvpnConfig);
145         this.neutronvpnConfig = neutronvpnConfig;
146     }
147
148     @Override
149     public void close() throws Exception {
150         LOG.info("{} close", getClass().getSimpleName());
151     }
152
153     public NeutronvpnConfig getNeutronvpnConfig() {
154         return neutronvpnConfig;
155     }
156
157     // TODO Clean up the exception handling
158     @SuppressWarnings("checkstyle:IllegalCatch")
159     protected void updateSubnetNodeWithFixedIps(Uuid subnetId, Uuid routerId,
160                                                 Uuid routerInterfaceName, String fixedIp,
161                                                 String routerIntfMacAddress) {
162         Subnetmap subnetmap = null;
163         SubnetmapBuilder builder = null;
164         InstanceIdentifier<Subnetmap> id =
165             InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
166         try {
167             synchronized (subnetId.getValue().intern()) {
168                 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
169                 if (sn.isPresent()) {
170                     builder = new SubnetmapBuilder(sn.get());
171                     LOG.debug("WithRouterFixedIPs: Updating existing subnetmap node for subnet ID {}",
172                         subnetId.getValue());
173                 } else {
174                     builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
175                     LOG.debug("WithRouterFixedIPs: creating new subnetmap node for subnet ID {}",
176                         subnetId.getValue());
177                 }
178                 builder.setRouterId(routerId);
179                 builder.setRouterInterfaceName(routerInterfaceName);
180                 builder.setRouterIntfMacAddress(routerIntfMacAddress);
181                 if (fixedIp != null) {
182                     List<String> fixedIps = builder.getRouterInterfaceFixedIps();
183                     if (fixedIps == null) {
184                         fixedIps = new ArrayList<>();
185                     }
186                     fixedIps.add(fixedIp);
187                     builder.setRouterInterfaceFixedIps(fixedIps);
188                 } else {
189                     builder.setRouterInterfaceFixedIps(null);
190                 }
191                 subnetmap = builder.build();
192                 LOG.debug("WithRouterFixedIPs Creating/Updating subnetMap node for Router FixedIps: {} ",
193                     subnetId.getValue());
194                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
195             }
196         } catch (Exception e) {
197             LOG.error("WithRouterFixedIPs: Updation of subnetMap for Router FixedIps failed for node: {}",
198                 subnetId.getValue());
199         }
200     }
201
202     // TODO Clean up the exception handling
203     @SuppressWarnings("checkstyle:IllegalCatch")
204     protected Subnetmap updateSubnetNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId, Uuid routerId,
205                                          Uuid vpnId) {
206         Subnetmap subnetmap = null;
207         SubnetmapBuilder builder = null;
208         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
209                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
210                 .build();
211         try {
212             synchronized (subnetId.getValue().intern()) {
213                 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
214                 if (sn.isPresent()) {
215                     builder = new SubnetmapBuilder(sn.get());
216                     LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
217                 } else {
218                     builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
219                     LOG.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
220                 }
221
222                 if (subnetIp != null) {
223                     builder.setSubnetIp(subnetIp);
224                 }
225                 if (routerId != null) {
226                     builder.setRouterId(routerId);
227                 }
228                 if (networkId != null) {
229                     builder.setNetworkId(networkId);
230                 }
231                 if (vpnId != null) {
232                     builder.setVpnId(vpnId);
233                 }
234                 if (tenantId != null) {
235                     builder.setTenantId(tenantId);
236                 }
237
238                 subnetmap = builder.build();
239                 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
240                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
241             }
242         } catch (Exception e) {
243             LOG.error("Updation of subnetMap failed for node: {}", subnetId.getValue());
244         }
245         return subnetmap;
246     }
247
248     // TODO Clean up the exception handling
249     @SuppressWarnings("checkstyle:IllegalCatch")
250     protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
251         Subnetmap subnetmap = null;
252         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
253                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
254                 .build();
255         try {
256             synchronized (subnetId.getValue().intern()) {
257                 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
258                 if (sn.isPresent()) {
259                     SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
260                     if (routerId != null) {
261                         builder.setRouterId(null);
262                     }
263                     if (networkId != null) {
264                         builder.setNetworkId(null);
265                     }
266                     if (vpnId != null) {
267                         builder.setVpnId(null);
268                     }
269                     if (portId != null && builder.getPortList() != null) {
270                         List<Uuid> portList = builder.getPortList();
271                         portList.remove(portId);
272                         builder.setPortList(portList);
273                     }
274
275                     subnetmap = builder.build();
276                     LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
277                     MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
278                 } else {
279                     LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
280                 }
281             }
282         } catch (Exception e) {
283             LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
284         }
285         return subnetmap;
286     }
287
288     // TODO Clean up the exception handling
289     @SuppressWarnings("checkstyle:IllegalCatch")
290     protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
291         Subnetmap subnetmap = null;
292         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
293                 new SubnetmapKey(subnetId)).build();
294         try {
295             synchronized (subnetId.getValue().intern()) {
296                 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
297                 if (sn.isPresent()) {
298                     SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
299                     if (null != portId) {
300                         List<Uuid> portList = builder.getPortList();
301                         if (null == portList) {
302                             portList = new ArrayList<>();
303                         }
304                         portList.add(portId);
305                         builder.setPortList(portList);
306                         LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
307                                 portId.getValue());
308                     }
309                     if (null != directPortId) {
310                         List<Uuid> directPortList = builder.getDirectPortList();
311                         if (null == directPortList) {
312                             directPortList = new ArrayList<>();
313                         }
314                         directPortList.add(directPortId);
315                         builder.setDirectPortList(directPortList);
316                         LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
317                                 directPortId.getValue());
318                     }
319                     subnetmap = builder.build();
320                     MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
321                 } else {
322                     LOG.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
323                 }
324             }
325         } catch (Exception e) {
326             LOG.error("Updating port list of a given subnetMap failed for node: {} with exception{}",
327                     subnetId.getValue(), e);
328         }
329         return subnetmap;
330     }
331
332     // TODO Clean up the exception handling
333     @SuppressWarnings("checkstyle:IllegalCatch")
334     protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
335         Subnetmap subnetmap = null;
336         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
337                 new SubnetmapKey(subnetId)).build();
338         try {
339             synchronized (subnetId.getValue().intern()) {
340                 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
341                 if (sn.isPresent()) {
342                     SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
343                     if (null != portId && null != builder.getPortList()) {
344                         List<Uuid> portList = builder.getPortList();
345                         portList.remove(portId);
346                         builder.setPortList(portList);
347                         LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
348                                 subnetId.getValue());
349                     }
350                     if (null != directPortId && null != builder.getDirectPortList()) {
351                         List<Uuid> directPortList = builder.getDirectPortList();
352                         directPortList.remove(directPortId);
353                         builder.setDirectPortList(directPortList);
354                         LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
355                                 .getValue(), subnetId.getValue());
356                     }
357                     subnetmap = builder.build();
358                     MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
359                 } else {
360                     LOG.error("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
361                 }
362             }
363         } catch (Exception e) {
364             LOG.error("Removing a port from port list of a subnetmap failed for node: {} with expection {}",
365                     subnetId.getValue(), e);
366         }
367         return subnetmap;
368     }
369
370     // TODO Clean up the exception handling
371     @SuppressWarnings("checkstyle:IllegalCatch")
372     protected void deleteSubnetMapNode(Uuid subnetId) {
373         InstanceIdentifier<Subnetmap> subnetMapIdentifier =
374                 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
375         LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
376         try {
377             synchronized (subnetId.getValue().intern()) {
378                 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
379             }
380         } catch (Exception e) {
381             LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
382         }
383     }
384
385     // TODO Clean up the exception handling
386     @SuppressWarnings("checkstyle:IllegalCatch")
387     private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert,
388                                        VpnInstance.Type type, long l3vni) {
389         VpnInstanceBuilder builder = null;
390         List<VpnTarget> vpnTargetList = new ArrayList<>();
391         boolean isLockAcquired = false;
392         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
393             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
394         try {
395             Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
396                     vpnIdentifier);
397             LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
398             if (optionalVpn.isPresent()) {
399                 builder = new VpnInstanceBuilder(optionalVpn.get());
400                 LOG.debug("updating existing vpninstance node");
401             } else {
402                 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
403                         .setType(type).setL3vni(l3vni);
404             }
405             if (irt != null && !irt.isEmpty()) {
406                 if (ert != null && !ert.isEmpty()) {
407                     List<String> commonRT = new ArrayList<>(irt);
408                     commonRT.retainAll(ert);
409
410                     for (String common : commonRT) {
411                         irt.remove(common);
412                         ert.remove(common);
413                         VpnTarget vpnTarget =
414                                 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
415                                         .setVrfRTType(VpnTarget.VrfRTType.Both).build();
416                         vpnTargetList.add(vpnTarget);
417                     }
418                 }
419                 for (String importRT : irt) {
420                     VpnTarget vpnTarget =
421                             new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
422                                     .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
423                     vpnTargetList.add(vpnTarget);
424                 }
425             }
426
427             if (ert != null && !ert.isEmpty()) {
428                 for (String exportRT : ert) {
429                     VpnTarget vpnTarget =
430                             new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
431                                     .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
432                     vpnTargetList.add(vpnTarget);
433                 }
434             }
435
436             VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
437
438             Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
439
440             if (rd != null && !rd.isEmpty()) {
441                 ipv4vpnBuilder.setRouteDistinguisher(rd);
442             }
443
444             VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
445             isLockAcquired = NeutronvpnUtils.lock(vpnName);
446             LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
447             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
448         } catch (Exception e) {
449             LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
450         } finally {
451             if (isLockAcquired) {
452                 NeutronvpnUtils.unlock(vpnName);
453             }
454         }
455     }
456
457     // TODO Clean up the exception handling
458     @SuppressWarnings("checkstyle:IllegalCatch")
459     private void deleteVpnMapsNode(Uuid vpnid) {
460         boolean isLockAcquired = false;
461         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
462                 .child(VpnMap.class, new VpnMapKey(vpnid))
463                 .build();
464         LOG.debug("removing vpnMaps node: {} ", vpnid.getValue());
465         try {
466             isLockAcquired = NeutronvpnUtils.lock(vpnid.getValue());
467             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
468         } catch (Exception e) {
469             LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnid.getValue());
470         } finally {
471             if (isLockAcquired) {
472                 NeutronvpnUtils.unlock(vpnid.getValue());
473             }
474         }
475     }
476
477     // TODO Clean up the exception handling
478     @SuppressWarnings("checkstyle:IllegalCatch")
479     private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
480         VpnMapBuilder builder;
481         boolean isLockAcquired = false;
482         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
483                 .child(VpnMap.class, new VpnMapKey(vpnId))
484                 .build();
485         try {
486             Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
487                     vpnMapIdentifier);
488             if (optionalVpnMap.isPresent()) {
489                 builder = new VpnMapBuilder(optionalVpnMap.get());
490             } else {
491                 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
492             }
493
494             if (name != null) {
495                 builder.setName(name);
496             }
497             if (tenantId != null) {
498                 builder.setTenantId(tenantId);
499             }
500             if (router != null) {
501                 builder.setRouterId(router);
502             }
503             if (networks != null) {
504                 List<Uuid> nwList = builder.getNetworkIds();
505                 if (nwList == null) {
506                     nwList = new ArrayList<>();
507                 }
508                 nwList.addAll(networks);
509                 builder.setNetworkIds(nwList);
510             }
511
512             isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
513             LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
514             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
515             LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
516         } catch (Exception e) {
517             LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
518         } finally {
519             if (isLockAcquired) {
520                 NeutronvpnUtils.unlock(vpnId.getValue());
521             }
522         }
523     }
524
525     // TODO Clean up the exception handling
526     @SuppressWarnings("checkstyle:IllegalCatch")
527     private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
528         boolean isLockAcquired = false;
529         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
530                 .child(VpnMap.class, new VpnMapKey(vpnId))
531                 .build();
532         Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
533                 vpnMapIdentifier);
534         if (optionalVpnMap.isPresent()) {
535             VpnMap vpnMap = optionalVpnMap.get();
536             VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
537             if (routerId != null) {
538                 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
539                     try {
540                         // remove entire node in case of internal VPN
541                         isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
542                         LOG.debug("removing vpnMaps node: {} ", vpnId);
543                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
544                     } catch (Exception e) {
545                         LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
546                     } finally {
547                         if (isLockAcquired) {
548                             NeutronvpnUtils.unlock(vpnId.getValue());
549                         }
550                     }
551                     return;
552                 }
553                 vpnMapBuilder.setRouterId(null);
554             }
555             if (networkIds != null) {
556                 List<Uuid> vpnNw = vpnMap.getNetworkIds();
557                 for (Uuid nw : networkIds) {
558                     vpnNw.remove(nw);
559                 }
560                 if (vpnNw.isEmpty()) {
561                     LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
562                     vpnMapBuilder.setNetworkIds(null);
563                 } else {
564                     vpnMapBuilder.setNetworkIds(vpnNw);
565                 }
566             }
567
568             try {
569                 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
570                 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
571                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
572                         vpnMapBuilder.build());
573             } catch (Exception e) {
574                 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
575             } finally {
576                 if (isLockAcquired) {
577                     NeutronvpnUtils.unlock(vpnId.getValue());
578                 }
579             }
580         } else {
581             LOG.error("VPN : {} not found", vpnId.getValue());
582         }
583         LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
584     }
585
586     // TODO Clean up the exception handling
587     @SuppressWarnings("checkstyle:IllegalCatch")
588     private void deleteVpnInstance(Uuid vpnId) {
589         boolean isLockAcquired = false;
590         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
591                 .child(VpnInstance.class,
592                         new VpnInstanceKey(vpnId.getValue()))
593                 .build();
594         try {
595             isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
596             LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
597             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
598         } catch (Exception e) {
599             LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
600         } finally {
601             if (isLockAcquired) {
602                 NeutronvpnUtils.unlock(vpnId.getValue());
603             }
604         }
605     }
606
607     protected void createVpnInterface(Uuid vpnId, Uuid routerId, Port port,
608                                       WriteTransaction wrtConfigTxn) {
609         String infName = port.getUuid().getValue();
610         List<Adjacency> adjList = new ArrayList<>();
611         Boolean isRouterInterface = false;
612         if (port.getDeviceOwner() != null) {
613             isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
614         }
615         LOG.trace("createVpnInterface - isRouterInterface:{}", isRouterInterface);
616         Router rtr = null;
617         if (routerId != null) {
618             rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
619         }
620         List<FixedIps> ips = port.getFixedIps();
621         // create adjacency list
622         for (FixedIps ip : ips) {
623             // create vm adjacency
624             String ipValue = String.valueOf(ip.getIpAddress().getValue());
625             String ipPrefix = (ip.getIpAddress().getIpv4Address() != null) ? ipValue + "/32" : ipValue + "/128";
626             Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
627                     .setMacAddress(port.getMacAddress().getValue()).setPrimaryAdjacency(true)
628                     .setSubnetId(ip.getSubnetId()).build();
629             adjList.add(vmAdj);
630             // create extra route adjacency
631             if (rtr != null && rtr.getRoutes() != null) {
632                 List<Routes> routeList = rtr.getRoutes();
633                 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(vpnId, routeList, ipValue);
634                 if (erAdjList != null && !erAdjList.isEmpty()) {
635                     adjList.addAll(erAdjList);
636                 }
637             }
638             NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
639                             .getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
640         }
641         // create vpn-interface on this neutron port
642         Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
643         writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
644         if (routerId != null) {
645             addToNeutronRouterInterfacesMap(routerId, infName);
646         }
647     }
648
649     // TODO Clean up the exception handling
650     @SuppressWarnings("checkstyle:IllegalCatch")
651     protected void deleteVpnInterface(Uuid vpnId, Uuid routerId, Port port, WriteTransaction wrtConfigTxn) {
652         Boolean wrtConfigTxnPresent = true;
653         if (wrtConfigTxn == null) {
654             wrtConfigTxnPresent = false;
655             wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
656         }
657         String infName = port.getUuid().getValue();
658         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
659         try {
660             LOG.debug("Deleting vpn interface {}", infName);
661             wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
662
663             List<FixedIps> ips = port.getFixedIps();
664             for (FixedIps ip : ips) {
665                 String ipValue = String.valueOf(ip.getIpAddress().getValue());
666                 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(),
667                         ipValue, wrtConfigTxn);
668             }
669         } catch (Exception ex) {
670             LOG.error("Deletion of vpninterface {} failed due to {}", infName, ex);
671         }
672         if (routerId != null) {
673             removeFromNeutronRouterInterfacesMap(routerId, infName);
674         }
675         if (!wrtConfigTxnPresent) {
676             wrtConfigTxn.submit();
677         }
678     }
679
680     // TODO Clean up the exception handling
681     @SuppressWarnings("checkstyle:IllegalCatch")
682     protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
683                                       boolean isSubnetIp) {
684         if (vpnId == null || port == null) {
685             return;
686         }
687         boolean isLockAcquired = false;
688         String infName = port.getUuid().getValue();
689         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
690
691         try {
692             WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
693             isLockAcquired = NeutronvpnUtils.lock(infName);
694             Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
695                     .CONFIGURATION, vpnIfIdentifier);
696             if (optionalVpnInterface.isPresent()) {
697                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
698                         .setVpnInstanceName(vpnId.getValue());
699                 LOG.debug("Updating vpn interface {}", infName);
700                 if (!isBeingAssociated) {
701                     Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
702                     List<Adjacency> adjacencyList = (adjs != null) ? adjs.getAdjacency() : new ArrayList<>();
703                     Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
704                     while (adjacencyIter.hasNext()) {
705                         Adjacency adjacency = adjacencyIter.next();
706                         String mipToQuery = adjacency.getIpAddress().split("/")[0];
707                         InstanceIdentifier<LearntVpnVipToPort> id =
708                             NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
709                         Optional<LearntVpnVipToPort> optionalVpnVipToPort =
710                             NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
711                         if (optionalVpnVipToPort.isPresent()) {
712                             LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
713                                 + "from VPN " + "{}", infName, vpnId, oldVpnId);
714                             adjacencyIter.remove();
715                             NeutronvpnUtils.removeLearntVpnVipToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
716                             LOG.trace("Entry for fixedIP {} for port {} on VPN removed from "
717                                 + "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
718                         }
719                     }
720                     Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
721                     vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
722                 }
723                 List<FixedIps> ips = port.getFixedIps();
724                 for (FixedIps ip : ips) {
725                     String ipValue = String.valueOf(ip.getIpAddress().getValue());
726                     if (oldVpnId != null) {
727                         NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(),
728                                 ipValue, writeConfigTxn);
729                     }
730                     NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
731                             .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
732                 }
733                 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
734                         .build());
735                 writeConfigTxn.submit();
736             } else {
737                 LOG.error("VPN Interface {} not found", infName);
738             }
739         } catch (Exception ex) {
740             LOG.error("Updation of vpninterface {} failed due to {}", infName, ex);
741         } finally {
742             if (isLockAcquired) {
743                 NeutronvpnUtils.unlock(infName);
744             }
745         }
746     }
747
748     public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
749                                     List<String> ert, Uuid router, List<Uuid> networks) {
750
751         // Update VPN Instance node
752         updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/);
753
754         // Update local vpn-subnet DS
755         updateVpnMaps(vpn, name, router, tenant, networks);
756
757         if (router != null) {
758             Uuid existingVpn = NeutronvpnUtils.getVpnForRouter(dataBroker, router, true);
759             if (existingVpn != null) {
760                 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
761
762                 // if before reboot, router was already associated to VPN, should not proceed associating router to
763                 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
764                 // preserved upon reboot.
765                 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
766                 // RouterInterfacesMap via #createVPNInterface call.
767                 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
768                     + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
769                 return;
770             }
771             associateRouterToInternalVpn(vpn, router);
772         }
773     }
774
775     /**
776      * Performs the creation of a Neutron L3VPN, associating the new VPN to the
777      * specified Neutron Networks and Routers.
778      *
779      * @param vpn Uuid of the VPN tp be created
780      * @param name Representative name of the new VPN
781      * @param tenant Uuid of the Tenant under which the VPN is going to be created
782      * @param rd Route-distinguisher for the VPN
783      * @param irt A list of Import Route Targets
784      * @param ert A list of Export Route Targets
785      * @param router UUID of the neutron router the VPN may be associated to
786      * @param networks UUID of the neutron network the VPN may be associated to
787      * @param type Type of the VPN Instance
788      * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
789      * @throws Exception if association of L3VPN failed
790      */
791     public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
792                             Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni) throws Exception {
793
794         // Update VPN Instance node
795         updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, type, l3vni);
796
797         // Please note that router and networks will be filled into VPNMaps
798         // by subsequent calls here to associateRouterToVpn and
799         // associateNetworksToVpn
800         updateVpnMaps(vpn, name, null, tenant, null);
801
802         if (router != null) {
803             associateRouterToVpn(vpn, router);
804         }
805         if (networks != null) {
806             List<String> failStrings = associateNetworksToVpn(vpn, networks);
807             if (failStrings != null &&  !failStrings.isEmpty()) {
808                 LOG.error("VPN {} association to networks failed with error message {}. ",
809                         vpn.getValue(), failStrings.get(0));
810                 throw new Exception(failStrings.get(0));
811             }
812         }
813     }
814
815     /**
816      * It handles the invocations to the createVPN RPC method.
817      */
818     @Override
819     // TODO Clean up the exception handling
820     @SuppressWarnings("checkstyle:IllegalCatch")
821     public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
822
823         CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
824         SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
825         List<RpcError> errorList = new ArrayList<>();
826         int failurecount = 0;
827         int warningcount = 0;
828
829         List<L3vpn> vpns = input.getL3vpn();
830         for (L3vpn vpn : vpns) {
831             RpcError error = null;
832             String msg;
833             if (NeutronvpnUtils.doesVpnExist(dataBroker, vpn.getId())) {
834                 msg = String.format("Creation of L3VPN failed for VPN %s due to VPN with the same ID already present",
835                                 vpn.getId().getValue());
836                 LOG.warn(msg);
837                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
838                 errorList.add(error);
839                 warningcount++;
840                 continue;
841             }
842             if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
843                 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
844                         vpn.getId().getValue());
845                 LOG.warn(msg);
846                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
847                 errorList.add(error);
848                 warningcount++;
849                 continue;
850             }
851             VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
852             long l3vni = 0;
853             if (vpn.getL3vni() != null) {
854                 l3vni = vpn.getL3vni();
855             }
856
857             if (vpn.getRouteDistinguisher().size() > 1) {
858                 msg = String.format("Creation of VPN failed for VPN %s due to multiple RD input %s",
859                         vpn.getId().getValue(), vpn.getRouteDistinguisher());
860                 LOG.warn(msg);
861                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
862                 errorList.add(error);
863                 warningcount++;
864                 continue;
865             }
866             List<String> existingRDs = NeutronvpnUtils.getExistingRDs(dataBroker);
867             if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
868                 msg = String.format("Creation of L3VPN failed for VPN %s as another VPN with the same RD %s "
869                     + "is already configured",
870                     vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0));
871                 LOG.warn(msg);
872                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
873                 errorList.add(error);
874                 warningcount++;
875                 continue;
876             }
877             if (vpn.getRouterId() != null) {
878                 if (NeutronvpnUtils.getNeutronRouter(dataBroker, vpn.getRouterId()) == null) {
879                     msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
880                             vpn.getId().getValue(), vpn.getRouterId().getValue());
881                     LOG.warn(msg);
882                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
883                     errorList.add(error);
884                     warningcount++;
885                     continue;
886                 }
887                 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, vpn.getRouterId(), true);
888                 if (vpnId != null) {
889                     msg = String.format("Creation of L3VPN failed for VPN %s due to router %s already associated to "
890                                     + "another VPN %s", vpn.getId().getValue(), vpn.getRouterId().getValue(),
891                             vpnId.getValue());
892                     LOG.warn(msg);
893                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
894                     errorList.add(error);
895                     warningcount++;
896                     continue;
897                 }
898             }
899             if (vpn.getNetworkIds() != null) {
900                 for (Uuid nw : vpn.getNetworkIds()) {
901                     Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
902                     Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
903                     if (network == null) {
904                         msg = String.format("Creation of L3VPN failed for VPN %s due to network not found %s",
905                                 vpn.getId().getValue(), nw.getValue());
906                         LOG.warn(msg);
907                         error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
908                         errorList.add(error);
909                         warningcount++;
910                     } else if (vpnId != null) {
911                         msg = String.format("Creation of L3VPN failed for VPN %s due to network %s already associated"
912                                         + " to another VPN %s", vpn.getId().getValue(), nw.getValue(),
913                                 vpnId.getValue());
914                         LOG.warn(msg);
915                         error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
916                         errorList.add(error);
917                         warningcount++;
918                     }
919                 }
920                 if (error != null) {
921                     continue;
922                 }
923             }
924             try {
925                 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
926                         vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
927                         vpnInstanceType, l3vni);
928             } catch (Exception ex) {
929                 msg = String.format("Creation of VPN failed for VPN %s", vpn.getId().getValue());
930                 LOG.error(msg, ex);
931                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
932                 errorList.add(error);
933                 failurecount++;
934             }
935         }
936         // if at least one succeeds; result is success
937         // if none succeeds; result is failure
938         if (failurecount + warningcount == vpns.size()) {
939             result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
940         } else {
941             List<String> errorResponseList = new ArrayList<>();
942             if (!errorList.isEmpty()) {
943                 for (RpcError rpcError : errorList) {
944                     String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
945                             .getErrorType(), rpcError.getTag(), rpcError.getMessage());
946                     errorResponseList.add(errorResponse);
947                 }
948             } else {
949                 errorResponseList.add("Operation successful with no errors");
950             }
951             opBuilder.setResponse(errorResponseList);
952             result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
953         }
954         return result;
955     }
956
957     /**
958      * It handles the invocations to the neutronvpn:getL3VPN RPC method.
959      */
960     @Override
961     // TODO Clean up the exception handling
962     @SuppressWarnings("checkstyle:IllegalCatch")
963     public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
964
965         GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
966         SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
967         Uuid inputVpnId = input.getId();
968         List<VpnInstance> vpns = new ArrayList<>();
969
970         try {
971             if (inputVpnId == null) {
972                 // get all vpns
973                 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
974                         .build();
975                 Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
976                         .CONFIGURATION, vpnsIdentifier);
977                 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
978                     for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
979                         // eliminating implicitly created (router and VLAN provider external network specific) VPNs
980                         // from getL3VPN output
981                         if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
982                             vpns.add(vpn);
983                         }
984                     }
985                 } else {
986                     // No VPN present
987                     result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
988                     return result;
989                 }
990             } else {
991                 String name = inputVpnId.getValue();
992                 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
993                         .child(VpnInstance.class, new VpnInstanceKey(name)).build();
994                 // read VpnInstance Info
995                 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
996                         vpnIdentifier);
997                 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
998                 // getL3VPN output
999                 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1000                     vpns.add(optionalVpn.get());
1001                 } else {
1002                     String message = String.format("GetL3VPN failed because VPN %s is not present", name);
1003                     LOG.error(message);
1004                     result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL,
1005                             "invalid-value", message).build());
1006                 }
1007             }
1008             List<L3vpnInstances> l3vpnList = new ArrayList<>();
1009             for (VpnInstance vpnInstance : vpns) {
1010                 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1011                 // create VpnMaps id
1012                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1013
1014                 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1015                 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1016
1017                 List<String> ertList = new ArrayList<>();
1018                 List<String> irtList = new ArrayList<>();
1019
1020                 for (VpnTarget vpnTarget : vpnTargetList) {
1021                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1022                         ertList.add(vpnTarget.getVrfRTValue());
1023                     }
1024                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1025                         irtList.add(vpnTarget.getVrfRTValue());
1026                     }
1027                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1028                         ertList.add(vpnTarget.getVrfRTValue());
1029                         irtList.add(vpnTarget.getVrfRTValue());
1030                     }
1031                 }
1032
1033                 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1034                 if (vpnInstance.getL3vni() != null) {
1035                     l3vpn.setL3vni(vpnInstance.getL3vni());
1036                 }
1037                 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1038                         .class, new VpnMapKey(vpnId)).build();
1039                 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1040                         vpnMapIdentifier);
1041                 if (optionalVpnMap.isPresent()) {
1042                     VpnMap vpnMap = optionalVpnMap.get();
1043                     l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1044                             .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1045                 }
1046                 l3vpnList.add(l3vpn.build());
1047             }
1048
1049             opBuilder.setL3vpnInstances(l3vpnList);
1050             result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1051
1052         } catch (Exception ex) {
1053             String message = String.format("GetVPN failed due to %s", ex.getMessage());
1054             LOG.error(message, ex);
1055             result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
1056         }
1057         return result;
1058     }
1059
1060     /**
1061      * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1062      */
1063     @Override
1064     // TODO Clean up the exception handling
1065     @SuppressWarnings("checkstyle:IllegalCatch")
1066     public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1067
1068         DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1069         SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1070         List<RpcError> errorList = new ArrayList<>();
1071
1072         int failurecount = 0;
1073         int warningcount = 0;
1074         List<Uuid> vpns = input.getId();
1075         for (Uuid vpn : vpns) {
1076             RpcError error;
1077             String msg;
1078             try {
1079                 InstanceIdentifier<VpnInstance> vpnIdentifier =
1080                         InstanceIdentifier.builder(VpnInstances.class)
1081                             .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1082                 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1083                         .CONFIGURATION, vpnIdentifier);
1084                 if (optionalVpn.isPresent()) {
1085                     removeVpn(vpn);
1086                 } else {
1087                     msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
1088                     LOG.warn(msg);
1089                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
1090                     errorList.add(error);
1091                     warningcount++;
1092                 }
1093             } catch (Exception ex) {
1094                 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
1095                 LOG.error(msg, ex);
1096                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1097                 errorList.add(error);
1098                 failurecount++;
1099             }
1100         }
1101         // if at least one succeeds; result is success
1102         // if none succeeds; result is failure
1103         if (failurecount + warningcount == vpns.size()) {
1104             result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1105         } else {
1106             List<String> errorResponseList = new ArrayList<>();
1107             if (!errorList.isEmpty()) {
1108                 for (RpcError rpcError : errorList) {
1109                     String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
1110                             .getErrorType(), rpcError.getTag(), rpcError.getMessage());
1111                     errorResponseList.add(errorResponse);
1112                 }
1113             } else {
1114                 errorResponseList.add("Operation successful with no errors");
1115             }
1116             opBuilder.setResponse(errorResponseList);
1117             result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1118         }
1119         return result;
1120     }
1121
1122     public void createVpnInstanceForSubnet(Uuid subnetId) {
1123         LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1124         createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1125     }
1126
1127     public void removeVpnInstanceForSubnet(Uuid subnetId) {
1128         LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1129         removeVpn(subnetId);
1130     }
1131
1132     protected void addSubnetToVpn(final Uuid vpnId, Uuid subnet) {
1133         LOG.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
1134         Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1135         VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1136         if (vpnMap == null) {
1137             LOG.error("No vpnMap for vpnId {}, cannot add subnet {} to VPN", vpnId.getValue(), subnet.getValue());
1138             return;
1139         }
1140
1141         final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1142         // Check if there are ports on this subnet and add corresponding
1143         // vpn-interfaces
1144         List<Uuid> portList = sn.getPortList();
1145         if (portList != null) {
1146             for (final Uuid portId : sn.getPortList()) {
1147                 LOG.debug("adding vpn-interface for port {}", portId.getValue());
1148                 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1149                 portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1150                     WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1151                     List<ListenableFuture<Void>> futures = new ArrayList<>();
1152                     createVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
1153                             wrtConfigTxn);
1154                     futures.add(wrtConfigTxn.submit());
1155                     return futures;
1156                 });
1157             }
1158         }
1159     }
1160
1161     protected void updateVpnForSubnet(Uuid vpnId, Uuid subnet, boolean isBeingAssociated) {
1162         LOG.debug("Updating VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
1163         // Read the subnet first to see if its already associated to a VPN
1164         Uuid oldVpnId = null;
1165         InstanceIdentifier<Subnetmap> snId = InstanceIdentifier.builder(Subnetmaps.class)
1166             .child(Subnetmap.class, new SubnetmapKey(subnet)).build();
1167         Subnetmap sn = null;
1168         Optional<Subnetmap> optSn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, snId);
1169         if (optSn.isPresent()) {
1170             sn = optSn.get();
1171             oldVpnId = sn.getVpnId();
1172             List<String> ips = sn.getRouterInterfaceFixedIps();
1173             for (String ipValue : ips) {
1174                 // Update the association of router-interface to external vpn
1175                 String portName =
1176                     NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, oldVpnId.getValue(), ipValue);
1177                 if (portName != null) {
1178                     updateVpnInterface(vpnId, oldVpnId,
1179                         NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(portName)),
1180                         isBeingAssociated, true);
1181                 }
1182             }
1183         }
1184         sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1185         // Check for ports on this subnet and update association of
1186         // corresponding vpn-interfaces to external vpn
1187         List<Uuid> portList = sn.getPortList();
1188         if (portList != null) {
1189             for (Uuid port : sn.getPortList()) {
1190                 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1191                     port.getValue(), isBeingAssociated);
1192                 updateVpnInterface(vpnId, oldVpnId, NeutronvpnUtils.getNeutronPort(dataBroker, port),
1193                         isBeingAssociated, false);
1194             }
1195         }
1196     }
1197
1198     public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1199         return InstanceIdentifier.builder(RouterInterfacesMap.class)
1200                 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1201     }
1202
1203     protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1204         synchronized (routerId.getValue().intern()) {
1205             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1206             Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1207                     .CONFIGURATION, routerInterfacesId);
1208             Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1209                 .setInterfaceId(interfaceName).build();
1210             if (optRouterInterfaces.isPresent()) {
1211                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1212                         .class, new InterfacesKey(interfaceName)), routerInterface);
1213             } else {
1214                 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1215                 List<Interfaces> interfaces = new ArrayList<>();
1216                 interfaces.add(routerInterface);
1217                 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1218                         .class, new InterfacesKey(interfaceName)), routerInterface);
1219             }
1220         }
1221     }
1222
1223     protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1224         synchronized (routerId.getValue().intern()) {
1225             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1226             Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1227                     .CONFIGURATION, routerInterfacesId);
1228             Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1229                 .setInterfaceId(interfaceName).build();
1230             if (optRouterInterfaces.isPresent()) {
1231                 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1232                 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1233                 if (interfaces != null && interfaces.remove(routerInterface)) {
1234                     if (interfaces.isEmpty()) {
1235                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1236                     } else {
1237                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1238                                 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1239                     }
1240                 }
1241             }
1242         }
1243     }
1244
1245     /**
1246      * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1247      * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1248      * route will be ignored.
1249      *
1250      * @param vpnName the VPN identifier
1251      * @param interVpnLinkRoutes The list of static routes
1252      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1253      */
1254     public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1255                                   HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1256         for (Routes route : interVpnLinkRoutes) {
1257             String nexthop = String.valueOf(route.getNexthop().getValue());
1258             String destination = String.valueOf(route.getDestination().getValue());
1259             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1260             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1261                 AddStaticRouteInput rpcInput =
1262                         new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1263                                 .setVpnInstanceName(vpnName.getValue())
1264                                 .build();
1265                 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1266                 RpcResult<AddStaticRouteOutput> rpcResult;
1267                 try {
1268                     rpcResult = labelOuputFtr.get();
1269                     if (rpcResult.isSuccessful()) {
1270                         LOG.debug("Label generated for destination {} is: {}",
1271                                 destination, rpcResult.getResult().getLabel());
1272                     } else {
1273                         LOG.warn("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1274                                 destination, nexthop, rpcResult.getErrors());
1275                     }
1276                 } catch (InterruptedException | ExecutionException e) {
1277                     LOG.warn("Error happened while invoking addStaticRoute RPC: ", e);
1278                 }
1279             } else {
1280                 // Any other case is a fault.
1281                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1282                         String.valueOf(route.getDestination().getValue()), nexthop);
1283                 continue;
1284             }
1285         }
1286     }
1287
1288     /**
1289      * Removes the corresponding static routes from the specified VPN. These static routes point to an
1290      * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1291      *
1292      * @param vpnName the VPN identifier
1293      * @param interVpnLinkRoutes The list of static routes
1294      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1295      */
1296     public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1297                                      HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1298         for (Routes route : interVpnLinkRoutes) {
1299             String nexthop = String.valueOf(route.getNexthop().getValue());
1300             String destination = String.valueOf(route.getDestination().getValue());
1301             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1302             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1303                 RemoveStaticRouteInput rpcInput =
1304                         new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1305                                 .setVpnInstanceName(vpnName.getValue())
1306                                 .build();
1307                 vpnRpcService.removeStaticRoute(rpcInput);
1308             } else {
1309                 // Any other case is a fault.
1310                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1311                         String.valueOf(route.getDestination().getValue()), nexthop);
1312                 continue;
1313             }
1314         }
1315     }
1316
1317     /*
1318      * Returns true if the specified nexthop is the other endpoint in an
1319      * InterVpnLink, regarding one of the VPN's point of view.
1320      */
1321     private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1322         return
1323                 interVpnLink != null
1324                         && ((interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1325                         && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop))
1326                         || (interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1327                         && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)));
1328     }
1329
1330     protected List<Adjacency> getAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList, String fixedIp) {
1331         List<Adjacency> adjList = new ArrayList<>();
1332         Map<String, List<String>> adjMap = new HashMap<>();
1333         for (Routes route : routeList) {
1334             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1335                 LOG.error("Incorrect input received for extra route. {}", route);
1336             } else {
1337                 String nextHop = String.valueOf(route.getNexthop().getValue());
1338                 String destination = String.valueOf(route.getDestination().getValue());
1339                 if (!nextHop.equals(fixedIp)) {
1340                     LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1341                     continue;
1342                 }
1343                 LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} ", destination,
1344                         vpnId.getValue(), nextHop);
1345                 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1346                 if (!hops.contains(nextHop)) {
1347                     hops.add(nextHop);
1348                 }
1349             }
1350         }
1351
1352         for (String destination : adjMap.keySet()) {
1353             Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1354                 .setNextHopIpList(adjMap.get(destination)).setKey(new AdjacencyKey(destination)).build();
1355             adjList.add(erAdj);
1356         }
1357         return  adjList;
1358     }
1359
1360     // TODO Clean up the exception handling
1361     @SuppressWarnings("checkstyle:IllegalCatch")
1362     protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1363         for (Routes route : routeList) {
1364             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1365                 LOG.error("Incorrect input received for extra route. {}", route);
1366             } else {
1367                 String nextHop = String.valueOf(route.getNexthop().getValue());
1368                 String destination = String.valueOf(route.getDestination().getValue());
1369                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1370                         nextHop);
1371                 if (infName != null) {
1372                     LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
1373                         destination, vpnId.getValue(), nextHop, infName);
1374                     boolean isLockAcquired = false;
1375                     try {
1376                         InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
1377                                 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1378                         InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
1379                             .child(Adjacency.class, new AdjacencyKey(destination));
1380                         Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1381                             .setNextHopIpList(Collections.singletonList(nextHop)).setKey(new AdjacencyKey(destination))
1382                             .build();
1383                         isLockAcquired = NeutronvpnUtils.lock(infName);
1384                         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, erAdj);
1385                     } catch (Exception e) {
1386                         LOG.error("exception in adding extra route with destination: {}, next hop: {}",
1387                             destination, nextHop, e);
1388                     } finally {
1389                         if (isLockAcquired) {
1390                             NeutronvpnUtils.unlock(infName);
1391                         }
1392                     }
1393                 } else {
1394                     LOG.debug("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1395                         + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1396                 }
1397             }
1398         }
1399     }
1400
1401     // TODO Clean up the exception handling
1402     @SuppressWarnings("checkstyle:IllegalCatch")
1403     protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
1404         for (Routes route : routeList) {
1405             if (route != null && route.getNexthop() != null && route.getDestination() != null) {
1406                 boolean isLockAcquired = false;
1407                 String nextHop = String.valueOf(route.getNexthop().getValue());
1408                 String destination = String.valueOf(route.getDestination().getValue());
1409                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1410                         nextHop);
1411                 if (infName == null) {
1412                     LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
1413                             + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1414                     // Proceed to remove the next extra-route
1415                     continue;
1416                 }
1417                 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
1418                         destination, vpnId.getValue(), nextHop, infName);
1419
1420                 InstanceIdentifier<Adjacency> adjacencyIdentifier =
1421                         InstanceIdentifier.builder(VpnInterfaces.class)
1422                                 .child(VpnInterface.class, new VpnInterfaceKey(infName))
1423                                 .augmentation(Adjacencies.class)
1424                                 .child(Adjacency.class, new AdjacencyKey(destination))
1425                                 .build();
1426
1427                 // Looking for existing prefix in MDSAL database
1428                 Optional<Adjacency> adjacency = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1429                         adjacencyIdentifier);
1430                 boolean updateNextHops = false;
1431                 List<String> nextHopList = new ArrayList<>();
1432                 if (adjacency.isPresent()) {
1433                     List<String> nhListRead = adjacency.get().getNextHopIpList();
1434                     if (nhListRead.size() > 1) { // ECMP case
1435                         for (String nextHopRead : nhListRead) {
1436                             if (nextHopRead.equals(nextHop)) {
1437                                 updateNextHops = true;
1438                             } else {
1439                                 nextHopList.add(nextHopRead);
1440                             }
1441                         }
1442                     }
1443                 }
1444
1445                 try {
1446                     isLockAcquired = NeutronvpnUtils.lock(infName);
1447                     if (updateNextHops) {
1448                         // An update must be done, not including the current next hop
1449                         InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
1450                                 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1451                         Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
1452                                 .setNextHopIpList(nextHopList)
1453                                 .setKey(new AdjacencyKey(destination))
1454                                 .build();
1455                         Adjacencies erAdjs =
1456                                 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
1457                         VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
1458                                 .addAugmentation(Adjacencies.class, erAdjs).build();
1459                         MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
1460                     } else {
1461                         // Remove the whole route
1462                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1463                         LOG.trace("extra route {} deleted successfully", route);
1464                     }
1465                 } catch (Exception e) {
1466                     LOG.error("exception in deleting extra route: {}" + e);
1467                 } finally {
1468                     if (isLockAcquired) {
1469                         NeutronvpnUtils.unlock(infName);
1470                     }
1471                 }
1472             } else {
1473                 LOG.error("Incorrect input received for extra route. {}", route);
1474             }
1475         }
1476     }
1477
1478     protected void removeVpn(Uuid id) {
1479         // read VPNMaps
1480         VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, id);
1481         Uuid router = (vpnMap != null) ? vpnMap.getRouterId() : null;
1482         // dissociate router
1483         if (router != null) {
1484             dissociateRouterFromVpn(id, router);
1485         }
1486         // dissociate networks
1487         if (!id.equals(router)) {
1488             dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
1489         }
1490         // remove entire vpnMaps node
1491         deleteVpnMapsNode(id);
1492
1493         // remove vpn-instance
1494         deleteVpnInstance(id);
1495     }
1496
1497     protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet) {
1498         LOG.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
1499         VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1500         if (vpnMap == null) {
1501             LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1502                     vpnId.getValue(), subnet.getValue());
1503             return;
1504         }
1505
1506         final Uuid routerId = vpnMap.getRouterId();
1507         Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1508         if (sn != null) {
1509             // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1510             List<Uuid> portList = sn.getPortList();
1511             if (portList != null) {
1512                 for (final Uuid portId : sn.getPortList()) {
1513                     LOG.debug("removing vpn-interface for port {}", portId.getValue());
1514                     final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1515                     portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1516                         WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1517                         List<ListenableFuture<Void>> futures = new ArrayList<>();
1518                         Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1519                         if (port != null) {
1520                             deleteVpnInterface(vpnId, routerId, port, wrtConfigTxn);
1521                         } else {
1522                             LOG.error("Cannot proceed with deleteVpnInterface for port {} in subnet {} since port is "
1523                                 + "absent in Neutron config DS", portId.getValue(), subnet.getValue());
1524                         }
1525                         futures.add(wrtConfigTxn.submit());
1526                         return futures;
1527                     });
1528                 }
1529             }
1530             // update subnet-vpn association
1531             removeFromSubnetNode(subnet, null, null, vpnId, null);
1532         } else {
1533             LOG.warn("Subnetmap for subnet {} not found", subnet.getValue());
1534         }
1535     }
1536
1537     // TODO Clean up the exception handling
1538     @SuppressWarnings("checkstyle:IllegalCatch")
1539     protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
1540         updateVpnMaps(vpnId, null, routerId, null, null);
1541         LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
1542         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1543         if (routerSubnets != null) {
1544             for (Uuid subnetId : routerSubnets) {
1545                 updateVpnForSubnet(vpnId, subnetId, true);
1546             }
1547         }
1548         try {
1549             checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
1550             LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
1551                     vpnId.getValue());
1552         } catch (Exception e) {
1553             LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
1554                     .getValue(), vpnId.getValue(), e);
1555         }
1556     }
1557
1558     protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
1559         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1560         LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
1561         for (Uuid subnet : routerSubnets) {
1562             addSubnetToVpn(vpnId, subnet);
1563         }
1564     }
1565
1566     // TODO Clean up the exception handling
1567     @SuppressWarnings("checkstyle:IllegalCatch")
1568     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
1569
1570         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1571         if (routerSubnets != null) {
1572             for (Uuid subnetId : routerSubnets) {
1573                 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
1574                 updateVpnForSubnet(routerId, subnetId, false);
1575             }
1576         }
1577         clearFromVpnMaps(vpnId, routerId, null);
1578         try {
1579             checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
1580             LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
1581                     vpnId.getValue());
1582         } catch (Exception e) {
1583             LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
1584                     .getValue(), vpnId.getValue(), e);
1585         }
1586     }
1587
1588     protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
1589         List<String> failedNwList = new ArrayList<>();
1590         List<Uuid> passedNwList = new ArrayList<>();
1591         if (!networks.isEmpty()) {
1592             // process corresponding subnets for VPN
1593             for (Uuid nw : networks) {
1594                 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1595                 NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
1596                 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
1597                     LOG.error("MultiSegmented networks not supported in VPN. Failed to associate network {} on vpn {}",
1598                             nw.getValue(), vpn.getValue());
1599                     failedNwList.add(String.format("Failed to associate network %s on vpn %s as it is multisegmented.",
1600                             nw.getValue(), vpn.getValue()));
1601                     continue;
1602                 }
1603                 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1604                 if (network == null) {
1605                     failedNwList.add(String.format("network %s not found", nw.getValue()));
1606                 } else if (vpnId != null) {
1607                     failedNwList.add(String.format("network %s already associated to another VPN %s", nw.getValue(),
1608                             vpnId.getValue()));
1609                 } else {
1610                     List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1611                     LOG.debug("Adding network subnets...{}", networkSubnets);
1612                     if (networkSubnets != null) {
1613                         for (Uuid subnet : networkSubnets) {
1614                             // check if subnet added as router interface to some router
1615                             Uuid subnetVpnId = NeutronvpnUtils.getVpnForSubnet(dataBroker, subnet);
1616                             if (subnetVpnId == null) {
1617                                 addSubnetToVpn(vpn, subnet);
1618                                 passedNwList.add(nw);
1619                             } else {
1620                                 failedNwList.add(String.format("subnet %s already added as router interface bound to "
1621                                     + "internal/external VPN %s", subnet.getValue(), subnetVpnId.getValue()));
1622                             }
1623                         }
1624                     }
1625                     if (NeutronvpnUtils.getIsExternal(network)) {
1626                         nvpnNatManager.addExternalNetworkToVpn(network, vpn);
1627                     }
1628                 }
1629             }
1630             updateVpnMaps(vpn, null, null, null, passedNwList);
1631         }
1632         return failedNwList;
1633     }
1634
1635     protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
1636         List<String> failedNwList = new ArrayList<>();
1637         List<Uuid> passedNwList = new ArrayList<>();
1638         if (networks != null && !networks.isEmpty()) {
1639             // process corresponding subnets for VPN
1640             for (Uuid nw : networks) {
1641                 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1642                 if (network == null) {
1643                     failedNwList.add(String.format("network %s not found", nw.getValue()));
1644                 } else {
1645                     Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1646                     if (vpn.equals(vpnId)) {
1647                         List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1648                         LOG.debug("Removing network subnets...");
1649                         if (networkSubnets != null) {
1650                             for (Uuid subnet : networkSubnets) {
1651                                 removeSubnetFromVpn(vpn, subnet);
1652                                 passedNwList.add(nw);
1653                             }
1654                         }
1655                     } else {
1656                         if (vpnId == null) {
1657                             failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
1658                                     .getValue()));
1659                         } else {
1660                             failedNwList.add(String.format("input network %s associated to a another vpn %s instead "
1661                                 + "of the one given as input", nw.getValue(), vpnId.getValue()));
1662                         }
1663                     }
1664                     if (NeutronvpnUtils.getIsExternal(network)) {
1665                         nvpnNatManager.removeExternalNetworkFromVpn(network);
1666                     }
1667                 }
1668             }
1669             clearFromVpnMaps(vpn, null, passedNwList);
1670         }
1671         return failedNwList;
1672     }
1673
1674     /**
1675      * It handles the invocations to the neutronvpn:associateNetworks RPC method.
1676      */
1677     @Override
1678     // TODO Clean up the exception handling
1679     @SuppressWarnings("checkstyle:IllegalCatch")
1680     public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1681
1682         AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
1683         SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
1684         LOG.debug("associateNetworks {}", input);
1685         StringBuilder returnMsg = new StringBuilder();
1686         Uuid vpnId = input.getVpnId();
1687
1688         try {
1689             if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1690                 List<Uuid> netIds = input.getNetworkId();
1691                 if (netIds != null && !netIds.isEmpty()) {
1692                     List<String> failed = associateNetworksToVpn(vpnId, netIds);
1693                     if (!failed.isEmpty()) {
1694                         returnMsg.append(failed);
1695                     }
1696                 }
1697             } else {
1698                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1699             }
1700             if (returnMsg.length() != 0) {
1701                 String message = String.format("associate Networks to vpn %s failed due to %s",
1702                         vpnId.getValue(), returnMsg);
1703                 LOG.error(message);
1704                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
1705                         message);
1706                 opBuilder.setResponse(errorResponse);
1707                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
1708             } else {
1709                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
1710             }
1711         } catch (Exception ex) {
1712             String message = String.format("associate Networks to vpn %s failed due to %s",
1713                     input.getVpnId().getValue(), ex.getMessage());
1714             LOG.error(message, ex);
1715             result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1716                     .build());
1717         }
1718         LOG.debug("associateNetworks returns..");
1719         return result;
1720     }
1721
1722     /**
1723      * It handles the invocations to the neutronvpn:associateRouter RPC method.
1724      */
1725     @Override
1726     // TODO Clean up the exception handling
1727     @SuppressWarnings("checkstyle:IllegalCatch")
1728     public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1729
1730         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1731         LOG.debug("associateRouter {}", input);
1732         StringBuilder returnMsg = new StringBuilder();
1733         Uuid vpnId = input.getVpnId();
1734         Uuid routerId = input.getRouterId();
1735         try {
1736             VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1737             Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1738             if (vpnMap != null) {
1739                 if (rtr != null) {
1740                     Uuid extVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1741                     if (vpnMap.getRouterId() != null) {
1742                         returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
1743                                 .append(vpnMap.getRouterId().getValue());
1744                     } else if (extVpnId != null) {
1745                         returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
1746                             + "another VPN ").append(extVpnId.getValue());
1747                     } else {
1748                         associateRouterToVpn(vpnId, routerId);
1749                     }
1750                 } else {
1751                     returnMsg.append("router not found : ").append(routerId.getValue());
1752                 }
1753             } else {
1754                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1755             }
1756             if (returnMsg.length() != 0) {
1757                 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1758                         returnMsg);
1759                 LOG.error(message);
1760                 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1761                         .build());
1762             } else {
1763                 result.set(RpcResultBuilder.<Void>success().build());
1764             }
1765         } catch (Exception ex) {
1766             String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
1767                     vpnId.getValue(), ex.getMessage());
1768             LOG.error(message, ex);
1769             result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1770         }
1771         LOG.debug("associateRouter returns..");
1772         return result;
1773     }
1774
1775     /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
1776      */
1777     @Override
1778     // TODO Clean up the exception handling
1779     @SuppressWarnings("checkstyle:IllegalCatch")
1780     public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
1781         GetFixedIPsForNeutronPortInput input) {
1782         GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
1783         SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
1784         Uuid portId = input.getPortId();
1785         StringBuilder returnMsg = new StringBuilder();
1786         try {
1787             List<String> fixedIPList = new ArrayList<>();
1788             Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1789             if (port != null) {
1790                 List<FixedIps> fixedIPs = port.getFixedIps();
1791                 for (FixedIps ip : fixedIPs) {
1792                     fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
1793                 }
1794             } else {
1795                 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
1796             }
1797             if (returnMsg.length() != 0) {
1798                 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
1799                 LOG.error(message);
1800                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1801                         .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
1802             } else {
1803                 opBuilder.setFixedIPs(fixedIPList);
1804                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
1805                         .build());
1806                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
1807             }
1808         } catch (Exception ex) {
1809             String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s",
1810                     portId.getValue(), ex.getMessage());
1811             LOG.error(message, ex);
1812             result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1813                     .withError(ErrorType.APPLICATION, message).build());
1814         }
1815         return result;
1816     }
1817
1818     /**
1819      * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
1820      */
1821     @Override
1822     // TODO Clean up the exception handling
1823     @SuppressWarnings("checkstyle:IllegalCatch")
1824     public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
1825
1826         DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
1827         SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
1828
1829         LOG.debug("dissociateNetworks {}", input);
1830         StringBuilder returnMsg = new StringBuilder();
1831         Uuid vpnId = input.getVpnId();
1832
1833         try {
1834             if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1835                 List<Uuid> netIds = input.getNetworkId();
1836                 if (netIds != null && !netIds.isEmpty()) {
1837                     List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
1838                     if (!failed.isEmpty()) {
1839                         returnMsg.append(failed);
1840                     }
1841                 }
1842             } else {
1843                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1844             }
1845             if (returnMsg.length() != 0) {
1846                 String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
1847                         returnMsg);
1848                 LOG.error(message);
1849                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1850                         + message);
1851                 opBuilder.setResponse(errorResponse);
1852                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
1853             } else {
1854                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
1855             }
1856         } catch (Exception ex) {
1857             String message = String.format("dissociate Networks to vpn %s failed due to %s",
1858                     input.getVpnId().getValue(), ex.getMessage());
1859             LOG.error(message, ex);
1860             result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1861                     .build());
1862         }
1863         LOG.debug("dissociateNetworks returns..");
1864         return result;
1865     }
1866
1867     /**
1868      * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
1869      */
1870     @Override
1871     // TODO Clean up the exception handling
1872     @SuppressWarnings("checkstyle:IllegalCatch")
1873     public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
1874
1875         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1876
1877         LOG.debug("dissociateRouter {}", input);
1878         StringBuilder returnMsg = new StringBuilder();
1879         Uuid vpnId = input.getVpnId();
1880         Uuid routerId = input.getRouterId();
1881         try {
1882             if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1883                 if (routerId != null) {
1884                     Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1885                     if (rtr != null) {
1886                         Uuid routerVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1887                         if (vpnId.equals(routerVpnId)) {
1888                             dissociateRouterFromVpn(vpnId, routerId);
1889                         } else {
1890                             if (routerVpnId == null) {
1891                                 returnMsg.append("input router ").append(routerId.getValue())
1892                                     .append(" not associated to any vpn yet");
1893                             } else {
1894                                 returnMsg.append("input router ").append(routerId.getValue())
1895                                     .append(" associated to vpn ")
1896                                     .append(routerVpnId.getValue()).append("instead of the vpn given as input");
1897                             }
1898                         }
1899                     } else {
1900                         returnMsg.append("router not found : ").append(routerId.getValue());
1901                     }
1902                 }
1903             } else {
1904                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1905             }
1906             if (returnMsg.length() != 0) {
1907                 String message = String.format("dissociate router %s to vpn %s failed due to %s", routerId.getValue(),
1908                         vpnId.getValue(), returnMsg);
1909                 LOG.error(message);
1910                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1911                         + message);
1912                 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1913                         .build());
1914             } else {
1915                 result.set(RpcResultBuilder.<Void>success().build());
1916             }
1917         } catch (Exception ex) {
1918             String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
1919                     vpnId.getValue(), ex.getMessage());
1920             LOG.error(message, ex);
1921             result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1922         }
1923         LOG.debug("dissociateRouter returns..");
1924
1925         return result;
1926     }
1927
1928     protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
1929         // check if the router is associated to some VPN
1930         Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1931         if (vpnId != null) {
1932             // remove existing external vpn interfaces
1933             for (Uuid subnetId : routerSubnetIds) {
1934                 removeSubnetFromVpn(vpnId, subnetId);
1935             }
1936             clearFromVpnMaps(vpnId, routerId, null);
1937         } else {
1938             // remove existing internal vpn interfaces
1939             for (Uuid subnetId : routerSubnetIds) {
1940                 removeSubnetFromVpn(routerId, subnetId);
1941             }
1942         }
1943         // delete entire vpnMaps node for internal VPN
1944         deleteVpnMapsNode(routerId);
1945
1946         // delete vpn-instance for internal VPN
1947         deleteVpnInstance(routerId);
1948     }
1949
1950     protected Subnet getNeutronSubnet(Uuid subnetId) {
1951         return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1952     }
1953
1954     protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
1955         Subnet sn = NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1956         if (null != sn) {
1957             return sn.getGatewayIp();
1958         }
1959         return null;
1960     }
1961
1962
1963     protected Network getNeutronNetwork(Uuid networkId) {
1964         return NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
1965     }
1966
1967     protected Port getNeutronPort(String name) {
1968         return NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(name));
1969     }
1970
1971     protected Port getNeutronPort(Uuid portId) {
1972         return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1973     }
1974
1975     protected Uuid getNetworkForSubnet(Uuid subnetId) {
1976         return NeutronvpnUtils.getNetworkForSubnet(dataBroker, subnetId);
1977     }
1978
1979     protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
1980         return NeutronvpnUtils.getNetworksforVpn(dataBroker, vpnId);
1981     }
1982
1983     /**
1984      * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
1985      *
1986      * @return a List of String to be printed on screen
1987      */
1988     // TODO Clean up the exception handling and the console output
1989     @SuppressWarnings({"checkstyle:IllegalCatch", "checkstyle:RegexpSinglelineJava"})
1990     public List<String> showNeutronPortsCLI() {
1991         List<String> result = new ArrayList<>();
1992         result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", "Port ID", "Mac Address", "Prefix Length",
1993             "IP Address"));
1994         result.add("-------------------------------------------------------------------------------------------");
1995         InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
1996         try {
1997             Optional<Ports> ports =
1998                 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
1999             if (ports.isPresent() && ports.get().getPort() != null) {
2000                 for (Port port : ports.get().getPort()) {
2001                     List<FixedIps> fixedIPs = port.getFixedIps();
2002                     try {
2003                         if (fixedIPs != null && !fixedIPs.isEmpty()) {
2004                             List<String> ipList = new ArrayList<>();
2005                             for (FixedIps fixedIp : fixedIPs) {
2006                                 IpAddress ipAddress = fixedIp.getIpAddress();
2007                                 if (ipAddress.getIpv4Address() != null) {
2008                                     ipList.add(ipAddress.getIpv4Address().getValue());
2009                                 } else {
2010                                     ipList.add((ipAddress.getIpv6Address().getValue()));
2011                                 }
2012                             }
2013                             result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
2014                                     .getMacAddress().getValue(), NeutronvpnUtils.getIPPrefixFromPort(dataBroker, port),
2015                                     ipList.toString()));
2016                         } else {
2017                             result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
2018                                     .getMacAddress().getValue(), "Not Assigned", "Not " + "Assigned"));
2019                         }
2020                     } catch (Exception e) {
2021                         LOG.error("Failed to retrieve neutronPorts info for port {}: ", port.getUuid().getValue(),
2022                                 e);
2023                         System.out.println("Failed to retrieve neutronPorts info for port: " + port.getUuid()
2024                                 .getValue() + ": " + e.getMessage());
2025                     }
2026                 }
2027             }
2028         } catch (Exception e) {
2029             LOG.error("Failed to retrieve neutronPorts info : ", e);
2030             System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
2031         }
2032         return result;
2033     }
2034
2035     /**
2036      * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2037      *
2038      * @param vpnuuid Uuid of the VPN whose config must be shown
2039      * @return formatted output list
2040      */
2041     @SuppressWarnings("checkstyle:RegexpSinglelineJava")
2042     public List<String> showVpnConfigCLI(Uuid vpnuuid) {
2043         List<String> result = new ArrayList<>();
2044         if (vpnuuid == null) {
2045             System.out.println("");
2046             System.out.println("Displaying VPN config for all VPNs");
2047             System.out.println("To display VPN config for a particular VPN, use the following syntax");
2048             System.out.println(getshowVpnConfigCLIHelp());
2049         }
2050         try {
2051             RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2052             if (rpcResult.isSuccessful()) {
2053                 result.add("");
2054                 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2055                 result.add("");
2056                 result.add(String.format(" %-80s ", "Import-RTs"));
2057                 result.add("");
2058                 result.add(String.format(" %-80s ", "Export-RTs"));
2059                 result.add("");
2060                 result.add(String.format(" %-76s ", "Subnet IDs"));
2061                 result.add("");
2062                 result.add("------------------------------------------------------------------------------------");
2063                 result.add("");
2064                 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2065                 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2066                             .rev150602.VpnInstance vpn : vpnList) {
2067                     String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2068                             : "\"                 " + "                  \"";
2069                     result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2070                             vpn.getRouteDistinguisher()));
2071                     result.add("");
2072                     result.add(String.format(" %-80s ", vpn.getImportRT()));
2073                     result.add("");
2074                     result.add(String.format(" %-80s ", vpn.getExportRT()));
2075                     result.add("");
2076
2077                     Uuid vpnid = vpn.getId();
2078                     List<Uuid> subnetList = NeutronvpnUtils.getSubnetsforVpn(dataBroker, vpnid);
2079                     if (!subnetList.isEmpty()) {
2080                         for (Uuid subnetuuid : subnetList) {
2081                             result.add(String.format(" %-76s ", subnetuuid.getValue()));
2082                         }
2083                     } else {
2084                         result.add(String.format(" %-76s ", "\"                                    \""));
2085                     }
2086                     result.add("");
2087                     result.add("----------------------------------------");
2088                     result.add("");
2089                 }
2090             } else {
2091                 String errortag = rpcResult.getErrors().iterator().next().getTag();
2092                 if (Objects.equals(errortag, "")) {
2093                     System.out.println("");
2094                     System.out.println("No VPN has been configured yet");
2095                 } else if (Objects.equals(errortag, "invalid-value")) {
2096                     System.out.println("");
2097                     System.out.println("VPN " + vpnuuid.getValue() + " is not present");
2098                 } else {
2099                     System.out.println("error getting VPN info : " + rpcResult.getErrors());
2100                     System.out.println(getshowVpnConfigCLIHelp());
2101                 }
2102             }
2103         } catch (InterruptedException | ExecutionException e) {
2104             LOG.error("error getting VPN info : ", e);
2105             System.out.println("error getting VPN info : " + e.getMessage());
2106         }
2107         return result;
2108     }
2109
2110     protected void createExternalVpnInterfaces(Uuid extNetId) {
2111         if (extNetId == null) {
2112             LOG.trace("external network is null");
2113             return;
2114         }
2115
2116         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2117         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2118             LOG.trace("No external ports attached to external network {}", extNetId.getValue());
2119             return;
2120         }
2121
2122         WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2123         for (String elanInterface : extElanInterfaces) {
2124             createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
2125         }
2126         wrtConfigTxn.submit();
2127     }
2128
2129     // TODO Clean up the exception handling
2130     @SuppressWarnings("checkstyle:IllegalCatch")
2131     protected void removeExternalVpnInterfaces(Uuid extNetId) {
2132         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2133         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2134             LOG.trace("No external ports attached for external network {}", extNetId);
2135             return;
2136         }
2137         try {
2138
2139             WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2140             for (String elanInterface : extElanInterfaces) {
2141                 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2142                         .buildVpnInterfaceIdentifier(elanInterface);
2143                 LOG.info("Removing vpn interface {}", elanInterface);
2144                 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2145             }
2146             wrtConfigTxn.submit();
2147
2148         } catch (Exception ex) {
2149             LOG.error("Removal of vpninterfaces {} failed due to {}", extElanInterfaces, ex);
2150         }
2151     }
2152
2153     private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2154         writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, wrtConfigTxn);
2155     }
2156
2157     // TODO Clean up the exception handling
2158     @SuppressWarnings("checkstyle:IllegalCatch")
2159     private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
2160             Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2161         if (vpnId == null || infName == null) {
2162             LOG.debug("vpn id or interface is null");
2163             return;
2164         }
2165
2166         Boolean wrtConfigTxnPresent = true;
2167         if (wrtConfigTxn == null) {
2168             wrtConfigTxnPresent = false;
2169             wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2170         }
2171
2172         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2173         VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2174                 .setName(infName)
2175                 .setVpnInstanceName(vpnId.getValue())
2176                 .setIsRouterInterface(isRouterInterface);
2177         if (adjacencies != null) {
2178             vpnb.addAugmentation(Adjacencies.class, adjacencies);
2179         }
2180         VpnInterface vpnIf = vpnb.build();
2181         try {
2182             LOG.info("Creating vpn interface {}", vpnIf);
2183             wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2184         } catch (Exception ex) {
2185             LOG.error("Creation of vpninterface {} failed due to {}", infName, ex);
2186         }
2187
2188         if (!wrtConfigTxnPresent) {
2189             wrtConfigTxn.submit();
2190         }
2191     }
2192
2193     private String getshowVpnConfigCLIHelp() {
2194         StringBuilder help = new StringBuilder("Usage:");
2195         help.append("display vpn-config [-vid/--vpnid <id>]");
2196         return help.toString();
2197     }
2198
2199     private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
2200             InterruptedException {
2201         RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
2202                 .setVpnId(vpnId).build();
2203         LOG.info("publishing notification upon association of router to VPN");
2204         notificationPublishService.putNotification(routerAssociatedToVpn);
2205     }
2206
2207     private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
2208             InterruptedException {
2209         RouterDisassociatedFromVpn routerDisassociatedFromVpn =
2210             new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
2211         LOG.info("publishing notification upon disassociation of router from VPN");
2212         notificationPublishService.putNotification(routerDisassociatedFromVpn);
2213     }
2214
2215     protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
2216         floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
2217     }
2218 }