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