Support for IPv6 East-West Routing
[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             String ipValue = String.valueOf(ip.getIpAddress().getValue());
633             String ipPrefix = (ip.getIpAddress().getIpv4Address() != null) ? ipValue + "/32" : ipValue + "/128";
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             NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
646                             .getMacAddress().getValue(), isRouterInterface, true, false);
647         }
648         // create vpn-interface on this neutron port
649         Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
650         writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
651         if (routerId != null) {
652             addToNeutronRouterInterfacesMap(routerId, infName);
653         }
654     }
655
656     protected void deleteVpnInterface(Uuid vpnId, Uuid routerId, Port port, WriteTransaction wrtConfigTxn) {
657         Boolean wrtConfigTxnPresent = true;
658         if (wrtConfigTxn == null) {
659             wrtConfigTxnPresent = false;
660             wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
661         }
662         String infName = port.getUuid().getValue();
663         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
664         try {
665             LOG.debug("Deleting vpn interface {}", infName);
666             wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
667
668             List<FixedIps> ips = port.getFixedIps();
669             for (FixedIps ip : ips) {
670                 String ipValue = String.valueOf(ip.getIpAddress().getValue());
671                 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue);
672             }
673         } catch (Exception ex) {
674             LOG.error("Deletion of vpninterface {} failed due to {}", infName, ex);
675         }
676         if (routerId != null) {
677             removeFromNeutronRouterInterfacesMap(routerId, infName);
678         }
679         if (!wrtConfigTxnPresent) {
680             wrtConfigTxn.submit();
681         }
682     }
683
684     protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean  isBeingAssociated) {
685         if (vpnId == null || port == null) {
686             return;
687         }
688         boolean isLockAcquired = false;
689         String infName = port.getUuid().getValue();
690         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
691         try {
692             isLockAcquired = NeutronvpnUtils.lock(infName);
693             Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
694                     .CONFIGURATION, vpnIfIdentifier);
695             if (optionalVpnInterface.isPresent()) {
696                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
697                         .setVpnInstanceName(vpnId.getValue());
698                 LOG.debug("Updating vpn interface {}", infName);
699                 if (!isBeingAssociated) {
700                     List<Adjacency> adjacencyList = vpnIfBuilder.getAugmentation(Adjacencies.class).getAdjacency();
701                     Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
702                     while (adjacencyIter.hasNext()) {
703                         Adjacency adjacency = adjacencyIter.next();
704                         String mipToQuery = adjacency.getIpAddress().split("/")[0];
705                         InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier
706                                 (oldVpnId.getValue(), mipToQuery);
707                         Optional<VpnPortipToPort> optionalVpnPort = NeutronvpnUtils.read(dataBroker,
708                                 LogicalDatastoreType
709                                 .OPERATIONAL, id);
710                         if (!optionalVpnPort.isPresent() || optionalVpnPort.get().isLearnt()) {
711                             LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} " +
712                                     "from VPN " + "{}", infName, vpnId, oldVpnId);
713                             adjacencyIter.remove();
714                             NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
715                             LOG.trace("Entry for fixedIP {} for port {} on VPN removed from " +
716                                     "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
717                         }
718                     }
719                     Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
720                     vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
721                 }
722                 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
723                         .build());
724
725                 List<FixedIps> ips = port.getFixedIps();
726                 for (FixedIps ip : ips) {
727                     String ipValue = String.valueOf(ip.getIpAddress().getValue());
728                     if (oldVpnId != null) {
729                         NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(), ipValue);
730                     }
731                     NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
732                             .getMacAddress().getValue(), false, true, false);
733                 }
734             } else {
735                 LOG.error("VPN Interface {} not found", infName);
736             }
737         } catch (Exception ex) {
738             LOG.error("Updation of vpninterface {} failed due to {}", infName, ex);
739         } finally {
740             if (isLockAcquired) {
741                 NeutronvpnUtils.unlock(infName);
742             }
743         }
744     }
745
746     public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
747                                     List<String> ert, Uuid router, List<Uuid> networks) {
748
749         // Update VPN Instance node
750         updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
751
752         // Update local vpn-subnet DS
753         updateVpnMaps(vpn, name, router, tenant, networks);
754
755         if (router != null) {
756             Uuid existingVpn = NeutronvpnUtils.getVpnForRouter(dataBroker, router, true);
757             if (existingVpn != null) {
758                 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
759
760                 // if before reboot, router was already associated to VPN, should not proceed associating router to
761                 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
762                 // preserved upon reboot.
763                 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
764                 // RouterInterfacesMap via #createVPNInterface call.
765                 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated " +
766                         "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
767                 return;
768             }
769             associateRouterToInternalVpn(vpn, router);
770         }
771     }
772
773     /**
774      * Performs the creation of a Neutron L3VPN, associating the new VPN to the
775      * specified Neutron Networks and Routers
776      *
777      * @param vpn Uuid of the VPN tp be created
778      * @param name Representative name of the new VPN
779      * @param tenant Uuid of the Tenant under which the VPN is going to be created
780      * @param rd Route-distinguisher for the VPN
781      * @param irt A list of Import Route Targets
782      * @param ert A list of Export Route Targets
783      * @param router UUID of the neutron router the VPN may be associated to
784      * @param networks UUID of the neutron network the VPN may be associated to
785      * @throws Exception if association of L3VPN failed
786      */
787     public void createL3Vpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
788                             Uuid router, List<Uuid> networks) throws Exception {
789
790         // Update VPN Instance node
791         updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
792
793         // Please note that router and networks will be filled into VPNMaps
794         // by subsequent calls here to associateRouterToVpn and
795         // associateNetworksToVpn
796         updateVpnMaps(vpn, name, null, tenant, null);
797
798         if (router != null) {
799             associateRouterToVpn(vpn, router);
800         }
801         if (networks != null) {
802             List<String> failStrings = associateNetworksToVpn(vpn, networks);
803             if (failStrings != null &&  !failStrings.isEmpty()) {
804                 LOG.error("L3VPN {} association to networks failed with error message {}. ",
805                         vpn.getValue(), failStrings.get(0));
806                 throw new Exception(failStrings.get(0));
807             }
808         }
809     }
810
811     /**
812      * It handles the invocations to the createL3VPN RPC method
813      *
814      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#createL3VPN
815      * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput)
816      */
817     @Override
818     public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
819
820         CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
821         SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
822         List<RpcError> errorList = new ArrayList<>();
823         int failurecount = 0;
824         int warningcount = 0;
825
826         List<L3vpn> vpns = input.getL3vpn();
827         for (L3vpn vpn : vpns) {
828             RpcError error = null;
829             String msg;
830             if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
831                 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
832                         vpn.getId().getValue());
833                 LOG.warn(msg);
834                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
835                 errorList.add(error);
836                 warningcount++;
837                 continue;
838             }
839             if (vpn.getRouteDistinguisher().size() > 1) {
840                 msg = String.format("Creation of L3VPN failed for VPN %s due to multiple RD input %s",
841                         vpn.getId().getValue(), vpn.getRouteDistinguisher());
842                 LOG.warn(msg);
843                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
844                 errorList.add(error);
845                 warningcount++;
846                 continue;
847             }
848             if (vpn.getRouterId() != null) {
849                 if (NeutronvpnUtils.getNeutronRouter(dataBroker, vpn.getRouterId()) == null) {
850                     msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
851                             vpn.getId().getValue(), vpn.getRouterId().getValue());
852                     LOG.warn(msg);
853                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
854                     errorList.add(error);
855                     warningcount++;
856                     continue;
857                 }
858                 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, vpn.getRouterId(), true);
859                 if (vpnId != null) {
860                     msg = String.format("Creation of L3VPN failed for VPN %s due to router %s already associated to "
861                                     + "another VPN %s", vpn.getId().getValue(), vpn.getRouterId().getValue(),
862                             vpnId.getValue());
863                     LOG.warn(msg);
864                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
865                     errorList.add(error);
866                     warningcount++;
867                     continue;
868                 }
869             }
870             if (vpn.getNetworkIds() != null) {
871                 for (Uuid nw : vpn.getNetworkIds()) {
872                     Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
873                     Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
874                     if (network == null) {
875                         msg = String.format("Creation of L3VPN failed for VPN %s due to network not found %s",
876                                 vpn.getId().getValue(), nw.getValue());
877                         LOG.warn(msg);
878                         error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
879                         errorList.add(error);
880                         warningcount++;
881                     } else if (vpnId != null) {
882                         msg = String.format("Creation of L3VPN failed for VPN %s due to network %s already associated"
883                                         + " to another VPN %s", vpn.getId().getValue(), nw.getValue(),
884                                 vpnId.getValue());
885                         LOG.warn(msg);
886                         error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
887                         errorList.add(error);
888                         warningcount++;
889                     }
890                 }
891                 if (error != null) {
892                     continue;
893                 }
894             }
895             try {
896                 createL3Vpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
897                         vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds());
898             } catch (Exception ex) {
899                 msg = String.format("Creation of L3VPN failed for VPN %s", vpn.getId().getValue());
900                 LOG.error(msg, ex);
901                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
902                 errorList.add(error);
903                 failurecount++;
904             }
905         }
906         // if at least one succeeds; result is success
907         // if none succeeds; result is failure
908         if (failurecount + warningcount == vpns.size()) {
909             result.set(RpcResultBuilder.<CreateL3VPNOutput> failed().withRpcErrors(errorList).build());
910         } else {
911             List<String> errorResponseList = new ArrayList<>();
912             if (!errorList.isEmpty()) {
913                 for (RpcError rpcError : errorList) {
914                     String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
915                             .getErrorType(), rpcError.getTag(), rpcError.getMessage());
916                     errorResponseList.add(errorResponse);
917                 }
918             } else {
919                 errorResponseList.add("Operation successful with no errors");
920             }
921             opBuilder.setResponse(errorResponseList);
922             result.set(RpcResultBuilder.<CreateL3VPNOutput> success().withResult(opBuilder.build()).build());
923         }
924         return result;
925     }
926
927     /**
928      * It handles the invocations to the neutronvpn:getL3VPN RPC method
929      *
930      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#getL3VPN
931      * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput)
932      */
933     @Override
934     public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
935
936         GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
937         SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
938         Uuid inputVpnId = input.getId();
939         List<VpnInstance> vpns = new ArrayList<>();
940
941         try {
942             if (inputVpnId == null) {
943                 // get all vpns
944                 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
945                         .build();
946                 Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(dataBroker,
947                         LogicalDatastoreType.CONFIGURATION,
948                         vpnsIdentifier);
949                 if (optionalVpns.isPresent() && optionalVpns.get().getVpnInstance() != null) {
950                     for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
951                         // eliminating internal VPNs from getL3VPN output
952                         if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
953                             vpns.add(vpn);
954                         }
955                     }
956                 } else {
957                     // No VPN present
958                     result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "", "No VPN " +
959                             "is present").build());
960                     return result;
961                 }
962             } else {
963                 String name = inputVpnId.getValue();
964                 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
965                         .child(VpnInstance.class,
966                                 new VpnInstanceKey(name))
967                         .build();
968                 // read VpnInstance Info
969                 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
970                         vpnIdentifier);
971                 if (optionalVpn.isPresent()) {
972                     vpns.add(optionalVpn.get());
973                 } else {
974                     String message = String.format("GetL3VPN failed because VPN %s is not present", name);
975                     LOG.error(message);
976                     result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL,
977                             "invalid-value", message).build());
978                 }
979             }
980             List<L3vpnInstances> l3vpnList = new ArrayList<>();
981             for (VpnInstance vpnInstance : vpns) {
982                 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
983                 // create VpnMaps id
984                 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
985                         .class, new VpnMapKey(vpnId)).build();
986                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
987
988                 List<String> rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(","));
989                 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
990
991                 List<String> ertList = new ArrayList<>();
992                 List<String> irtList = new ArrayList<>();
993
994                 for (VpnTarget vpnTarget : vpnTargetList) {
995                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
996                         ertList.add(vpnTarget.getVrfRTValue());
997                     }
998                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
999                         irtList.add(vpnTarget.getVrfRTValue());
1000                     }
1001                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1002                         ertList.add(vpnTarget.getVrfRTValue());
1003                         irtList.add(vpnTarget.getVrfRTValue());
1004                     }
1005                 }
1006
1007                 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1008                 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1009                         vpnMapIdentifier);
1010                 if (optionalVpnMap.isPresent()) {
1011                     VpnMap vpnMap = optionalVpnMap.get();
1012                     l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1013                             .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1014                 }
1015                 l3vpnList.add(l3vpn.build());
1016             }
1017
1018             opBuilder.setL3vpnInstances(l3vpnList);
1019             result.set(RpcResultBuilder.<GetL3VPNOutput> success().withResult(opBuilder.build()).build());
1020
1021         } catch (Exception ex) {
1022             String message = String.format("GetL3VPN failed due to %s", ex.getMessage());
1023             LOG.error(message, ex);
1024             result.set(RpcResultBuilder.<GetL3VPNOutput> failed().withError(ErrorType.APPLICATION, message).build());
1025         }
1026         return result;
1027     }
1028
1029     /**
1030      * It handles the invocations to the neutronvpn:deleteL3VPN RPC method
1031      *
1032      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#deleteL3VPN
1033      * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput)
1034      */
1035     @Override
1036     public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1037
1038         DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1039         SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1040         List<RpcError> errorList = new ArrayList<>();
1041
1042         int failurecount = 0;
1043         int warningcount = 0;
1044         List<Uuid> vpns = input.getId();
1045         for (Uuid vpn : vpns) {
1046             RpcError error;
1047             String msg;
1048             try {
1049                 InstanceIdentifier<VpnInstance> vpnIdentifier =
1050                         InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey
1051                                 (vpn.getValue())).build();
1052                 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1053                         .CONFIGURATION, vpnIdentifier);
1054                 if (optionalVpn.isPresent()) {
1055                     removeL3Vpn(vpn);
1056                 } else {
1057                     msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
1058                     LOG.warn(msg);
1059                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
1060                     errorList.add(error);
1061                     warningcount++;
1062                 }
1063             } catch (Exception ex) {
1064                 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
1065                 LOG.error(msg, ex);
1066                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1067                 errorList.add(error);
1068                 failurecount++;
1069             }
1070         }
1071         // if at least one succeeds; result is success
1072         // if none succeeds; result is failure
1073         if (failurecount + warningcount == vpns.size()) {
1074             result.set(RpcResultBuilder.<DeleteL3VPNOutput> failed().withRpcErrors(errorList).build());
1075         } else {
1076             List<String> errorResponseList = new ArrayList<>();
1077             if (!errorList.isEmpty()) {
1078                 for (RpcError rpcError : errorList) {
1079                     String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
1080                             .getErrorType(), rpcError.getTag(), rpcError.getMessage());
1081                     errorResponseList.add(errorResponse);
1082                 }
1083             } else {
1084                 errorResponseList.add("Operation successful with no errors");
1085             }
1086             opBuilder.setResponse(errorResponseList);
1087             result.set(RpcResultBuilder.<DeleteL3VPNOutput> success().withResult(opBuilder.build()).build());
1088         }
1089         return result;
1090     }
1091
1092     protected void addSubnetToVpn(final Uuid vpnId, Uuid subnet) {
1093         LOG.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
1094         Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1095         final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1096         // send subnet added to vpn notification
1097         isExternalVpn = vpnId.equals(routerId) ? false : true;
1098         String elanInstanceName = sn.getNetworkId().getValue();
1099         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
1100                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
1101         try {
1102             Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1103                     .CONFIGURATION, elanIdentifierId);
1104             if (elanInstance.isPresent()) {
1105                 long elanTag = elanInstance.get().getElanTag();
1106                 checkAndPublishSubnetAddNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isExternalVpn,
1107                         elanTag);
1108                 LOG.debug("Subnet added to VPN notification sent for subnet {} on VPN {}", subnet.getValue(),
1109                         vpnId.getValue());
1110             } else {
1111                 LOG.error("Subnet added to VPN notification failed for subnet {}  on VPN {} because of failure in " +
1112                         "reading ELANInstance {}", subnet.getValue(), vpnId.getValue(), elanInstanceName);
1113             }
1114         } catch (Exception e) {
1115             LOG.error("Subnet added to VPN notification failed for subnet {} on VPN {}", subnet.getValue(), vpnId
1116                     .getValue(), e);
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
1126                         Callable<List<ListenableFuture<Void>>>() {
1127                     @Override
1128                     public List<ListenableFuture<Void>> call() throws Exception {
1129                         WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1130                         List<ListenableFuture<Void>> futures = new ArrayList<>();
1131                         createVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
1132                                 wrtConfigTxn);
1133                         futures.add(wrtConfigTxn.submit());
1134                         return futures;
1135                     }
1136                 });
1137             }
1138         }
1139     }
1140
1141     protected void updateVpnForSubnet(Uuid vpnId, Uuid subnet, boolean isBeingAssociated) {
1142         LOG.debug("Updating VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
1143         // Read the subnet first to see if its already associated to a VPN
1144         Uuid oldVpnId = null;
1145         InstanceIdentifier<Subnetmap> snId = InstanceIdentifier.builder(Subnetmaps.class).
1146                 child(Subnetmap.class, new SubnetmapKey(subnet)).build();
1147         Subnetmap sn = null;
1148         Optional<Subnetmap> optSn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, snId);
1149         if (optSn.isPresent()) {
1150             sn = optSn.get();
1151             oldVpnId = sn.getVpnId();
1152             List<String> ips = sn.getRouterInterfaceFixedIps();
1153             for (String ipValue : ips) {
1154                 if (oldVpnId != null) {
1155                     NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(), ipValue);
1156                 }
1157                 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, sn
1158                         .getRouterInterfaceName().getValue(), sn.getRouterIntfMacAddress(), true, true, false);
1159             }
1160         }
1161         sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1162         // send vpn updated for subnet notification
1163         String elanInstanceName = sn.getNetworkId().getValue();
1164         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
1165                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
1166         try {
1167             Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1168                     .CONFIGURATION, elanIdentifierId);
1169             if (elanInstance.isPresent()) {
1170                 long elanTag = elanInstance.get().getElanTag();
1171                 checkAndPublishSubnetUpdNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isBeingAssociated,
1172                         elanTag);
1173                 LOG.debug("VPN updated for subnet notification sent for subnet {} on VPN {}", subnet.getValue(),
1174                         vpnId.getValue());
1175             } else {
1176                 LOG.error("VPN updated for subnet notification failed for subnet {} on VPN {} because of failure " +
1177                         "in reading ELANInstance {}", subnet.getValue(), vpnId.getValue(), elanInstanceName);
1178             }
1179         } catch (Exception e) {
1180             LOG.error("VPN updated for subnet notification failed for subnet {} on VPN {}", subnet.getValue(),
1181                     vpnId.getValue(), e);
1182         }
1183         // Check for ports on this subnet and update association of
1184         // corresponding vpn-interfaces to external vpn
1185         List<Uuid> portList = sn.getPortList();
1186         if (portList != null) {
1187             for (Uuid port : sn.getPortList()) {
1188                 LOG.debug("Updating vpn-interface for port {}", port.getValue());
1189                 updateVpnInterface(vpnId, oldVpnId, NeutronvpnUtils.getNeutronPort(dataBroker, port),
1190                         isBeingAssociated);
1191             }
1192         }
1193     }
1194
1195     public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1196         return InstanceIdentifier.builder(RouterInterfacesMap.class)
1197                 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1198     }
1199
1200     protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1201         synchronized (routerId.getValue().intern()) {
1202             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1203             Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1204                     .CONFIGURATION, routerInterfacesId);
1205             Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
1206                     (interfaceName).build();
1207             if (optRouterInterfaces.isPresent()) {
1208                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1209                         .class, new InterfacesKey(interfaceName)), routerInterface);
1210             } else {
1211                 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1212                 List<Interfaces> interfaces = new ArrayList<>();
1213                 interfaces.add(routerInterface);
1214                 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1215                         .class, new InterfacesKey(interfaceName)), routerInterface);
1216             }
1217         }
1218     }
1219
1220     protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1221         synchronized (routerId.getValue().intern()) {
1222             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1223             Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1224                     .CONFIGURATION, routerInterfacesId);
1225             Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId
1226                     (interfaceName).build();
1227             if (optRouterInterfaces.isPresent()) {
1228                 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1229                 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1230                 if (interfaces != null && interfaces.remove(routerInterface)) {
1231                     if (interfaces.isEmpty()) {
1232                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1233                     } else {
1234                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1235                                 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1236                     }
1237                 }
1238             }
1239         }
1240     }
1241
1242     /**
1243      * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1244      * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1245      * route will be ignored.
1246      *
1247      * @param vpnName the VPN identifier
1248      * @param interVpnLinkRoutes The list of static routes
1249      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1250      */
1251     public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1252                                   HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1253         for ( Routes route : interVpnLinkRoutes ) {
1254             String nexthop = String.valueOf(route.getNexthop().getValue());
1255             String destination = String.valueOf(route.getDestination().getValue());
1256             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1257             if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
1258                 AddStaticRouteInput rpcInput =
1259                         new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1260                                 .setVpnInstanceName(vpnName.getValue())
1261                                 .build();
1262                 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1263                 RpcResult<AddStaticRouteOutput> rpcResult;
1264                 try {
1265                     rpcResult = labelOuputFtr.get();
1266                     if ( rpcResult.isSuccessful() ) {
1267                         LOG.debug("Label generated for destination {} is: {}",
1268                                 destination, rpcResult.getResult().getLabel());
1269                     } else {
1270                         LOG.warn("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1271                                 destination, nexthop, rpcResult.getErrors());
1272                     }
1273                 } catch (InterruptedException | ExecutionException e) {
1274                     LOG.warn("Error happened while invoking addStaticRoute RPC: ", e);
1275                 }
1276             } else {
1277                 // Any other case is a fault.
1278                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1279                         String.valueOf(route.getDestination().getValue()), nexthop );
1280                 continue;
1281             }
1282         }
1283     }
1284
1285     /**
1286      * Removes the corresponding static routes from the specified VPN. These static routes point to an
1287      * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1288      *
1289      * @param vpnName the VPN identifier
1290      * @param interVpnLinkRoutes The list of static routes
1291      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1292      */
1293     public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1294                                      HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1295         for ( Routes route : interVpnLinkRoutes ) {
1296             String nexthop = String.valueOf(route.getNexthop().getValue());
1297             String destination = String.valueOf(route.getDestination().getValue());
1298             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1299             if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
1300                 RemoveStaticRouteInput rpcInput =
1301                         new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1302                                 .setVpnInstanceName(vpnName.getValue())
1303                                 .build();
1304                 vpnRpcService.removeStaticRoute(rpcInput);
1305             } else {
1306                 // Any other case is a fault.
1307                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1308                         String.valueOf(route.getDestination().getValue()), nexthop );
1309                 continue;
1310             }
1311         }
1312     }
1313
1314     /*
1315      * Returns true if the specified nexthop is the other endpoint in an
1316      * InterVpnLink, regarding one of the VPN's point of view.
1317      */
1318     private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1319         return
1320                 interVpnLink != null
1321                         && (   (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1322                         && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop))
1323                         || (interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid )
1324                         && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)) );
1325     }
1326
1327     protected List<Adjacency> addAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
1328         List<Adjacency> adjList = new ArrayList<>();
1329         Map<String, List<String>> adjMap = new HashMap<>();
1330         for (Routes route : routeList) {
1331             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1332                 LOG.error("Incorrect input received for extra route. {}", route);
1333             } else {
1334                 String nextHop = String.valueOf(route.getNexthop().getValue());
1335                 String destination = String.valueOf(route.getDestination().getValue());
1336                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1337                         nextHop);
1338                 if (infName == null) {
1339                     LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} " +
1340                             "with nexthop {}", destination, vpnId.getValue(), nextHop);
1341                     // Proceed to process the next extra-route
1342                     continue;
1343                 }
1344                 LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} and infName {}", destination,
1345                         vpnId.getValue(), nextHop, infName);
1346                 List<String> hops = adjMap.get(destination);
1347                 if (hops == null){
1348                     hops = new ArrayList<>();
1349                     adjMap.put(destination, hops);
1350                 }
1351                 if (! hops.contains(nextHop)) {
1352                     hops.add(nextHop);
1353                 }
1354             }
1355         }
1356
1357         for (String destination : adjMap.keySet()) {
1358             Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination).setNextHopIpList(adjMap.get
1359                     (destination)).setKey(new AdjacencyKey(destination)).build();
1360             adjList.add(erAdj);
1361         }
1362
1363         for (Adjacency adj : adjList) {
1364             for(String nextHop : adj.getNextHopIpList()) {
1365                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1366                         nextHop);
1367                 if (infName != null) {
1368                     InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class)
1369                             .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1370                     boolean isLockAcquired = false;
1371                     try {
1372                         Optional<VpnInterface> optionalVpnInterface =
1373                                 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
1374                         if (optionalVpnInterface.isPresent()) {
1375                             Adjacency newAdj = new AdjacencyBuilder(adj).setNextHopIpList(Arrays.asList(nextHop))
1376                                     .build();
1377                             Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(newAdj)).build();
1378                             VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
1379                                     .addAugmentation(Adjacencies.class, erAdjs).build();
1380                             isLockAcquired = NeutronvpnUtils.lock(infName);
1381                             MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
1382                         } else {
1383                             LOG.error("VM adjacency for interface {} not present; cannot add extra route adjacency",
1384                                     infName);
1385                         }
1386                     } catch (Exception e) {
1387                         LOG.error("exception in adding extra route with destination: {}, next hop: {}", adj
1388                                 .getIpAddress(), nextHop, e);
1389                     } finally {
1390                         if (isLockAcquired) {
1391                             NeutronvpnUtils.unlock(infName);
1392                         }
1393                     }
1394                 } else {
1395                     LOG.warn("Could not find suitable Interface for {}", nextHop);
1396                 }
1397             }
1398         }
1399         return adjList;
1400     }
1401
1402     protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
1403         for (Routes route : routeList) {
1404             if (route != null && route.getNexthop() != null && route.getDestination() != null) {
1405                 boolean isLockAcquired = false;
1406                 String nextHop = String.valueOf(route.getNexthop().getValue());
1407                 String destination = String.valueOf(route.getDestination().getValue());
1408                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1409                         nextHop);
1410                 if (infName == null) {
1411                     LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} " +
1412                                     "with nexthop {}",
1413                             destination, vpnId.getValue(), nextHop);
1414                     // Proceed to remove the next extra-route
1415                     continue;
1416                 }
1417                 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
1418                         destination, vpnId.getValue(), nextHop, infName);
1419
1420                 InstanceIdentifier<Adjacency> adjacencyIdentifier =
1421                         InstanceIdentifier.builder(VpnInterfaces.class)
1422                                 .child(VpnInterface.class, new VpnInterfaceKey(infName))
1423                                 .augmentation(Adjacencies.class)
1424                                 .child(Adjacency.class, new AdjacencyKey(destination))
1425                                 .build();
1426
1427                 // Looking for existing prefix in MDSAL database
1428                 Optional<Adjacency> adjacency = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1429                         adjacencyIdentifier);
1430                 boolean updateNextHops = false;
1431                 List<String> nextHopList = new ArrayList<>();
1432                 if (adjacency.isPresent()) {
1433                     List<String> nhListRead = adjacency.get().getNextHopIpList();
1434                     if (nhListRead.size() > 1) { // ECMP case
1435                         for (String nextHopRead : nhListRead) {
1436                             if (nextHopRead.equals(nextHop)) {
1437                                 updateNextHops = true;
1438                             } else {
1439                                 nextHopList.add(nextHopRead);
1440                             }
1441                         }
1442                     }
1443                 }
1444
1445                 try {
1446                     isLockAcquired = NeutronvpnUtils.lock(infName);
1447                     if (updateNextHops) {
1448                         // An update must be done, not including the current next hop
1449                         InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
1450                                 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1451                         Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
1452                                 .setNextHopIpList(nextHopList)
1453                                 .setKey(new AdjacencyKey(destination))
1454                                 .build();
1455                         Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(newAdj)).build();
1456                         VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
1457                                 .addAugmentation(Adjacencies.class, erAdjs).build();
1458                         MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
1459                     } else {
1460                         // Remove the whole route
1461                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1462                         LOG.trace("extra route {} deleted successfully", route);
1463                     }
1464                 } catch (Exception e) {
1465                     LOG.error("exception in deleting extra route: {}" + e);
1466                 } finally {
1467                     if (isLockAcquired) {
1468                         NeutronvpnUtils.unlock(infName);
1469                     }
1470                 }
1471             } else {
1472                 LOG.error("Incorrect input received for extra route. {}", route);
1473             }
1474         }
1475     }
1476
1477     protected void removeL3Vpn(Uuid id) {
1478         // read VPNMaps
1479         VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, id);
1480         Uuid router = vpnMap.getRouterId();
1481         // dissociate router
1482         if (router != null) {
1483             dissociateRouterFromVpn(id, router);
1484         }
1485         // dissociate networks
1486         if (!id.equals(router)) {
1487             dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
1488         }
1489         // remove entire vpnMaps node
1490         deleteVpnMapsNode(id);
1491
1492         // remove vpn-instance
1493         deleteVpnInstance(id);
1494     }
1495
1496     protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet) {
1497         LOG.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
1498         final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1499         Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1500         // send subnet removed from vpn notification
1501         isExternalVpn = vpnId.equals(routerId) ? false : true;
1502         String elanInstanceName = sn.getNetworkId().getValue();
1503         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
1504                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
1505         try {
1506             Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1507                     .CONFIGURATION, elanIdentifierId);
1508             if (elanInstance.isPresent()) {
1509                 long elanTag = elanInstance.get().getElanTag();
1510                 checkAndPublishSubnetDelNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isExternalVpn,
1511                         elanTag);
1512                 LOG.debug("Subnet removed from VPN notification sent for subnet {} on VPN {}", subnet.getValue(),
1513                         vpnId.getValue());
1514             } else {
1515                 LOG.error("Subnet removed from VPN notification failed for subnet {} on VPN {} because of failure " +
1516                         "in reading ELANInstance {}", subnet.getValue(), vpnId.getValue(), elanInstanceName);
1517             }
1518         } catch (Exception e) {
1519             LOG.error("Subnet removed from VPN notification failed for subnet {} on VPN {}", subnet.getValue(),
1520                     vpnId.getValue(), e);
1521         }
1522         if (sn != null) {
1523             // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1524             List<Uuid> portList = sn.getPortList();
1525             if (portList != null) {
1526                 for (final Uuid portId : sn.getPortList()) {
1527                     LOG.debug("removing vpn-interface for port {}", portId.getValue());
1528                     final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1529                     portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1530                         WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1531                         List<ListenableFuture<Void>> futures = new ArrayList<>();
1532                         deleteVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
1533                                 wrtConfigTxn);
1534                         futures.add(wrtConfigTxn.submit());
1535                         return futures;
1536                     });
1537                 }
1538             }
1539             // update subnet-vpn association
1540             removeFromSubnetNode(subnet, null, null, vpnId, null);
1541         } else {
1542             LOG.warn("Subnetmap for subnet {} not found", subnet.getValue());
1543         }
1544     }
1545
1546     protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
1547         updateVpnMaps(vpnId, null, routerId, null, null);
1548         LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
1549         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1550         if (routerSubnets != null) {
1551             for (Uuid subnetId : routerSubnets) {
1552                 updateVpnForSubnet(vpnId, subnetId, true);
1553             }
1554         }
1555         try {
1556             checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
1557             LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
1558                     vpnId.getValue());
1559         } catch (Exception e) {
1560             LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
1561                     .getValue(), vpnId.getValue(), e);
1562         }
1563     }
1564
1565     protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
1566         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1567         LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
1568         for (Uuid subnet : routerSubnets) {
1569             addSubnetToVpn(vpnId, subnet);
1570         }
1571     }
1572
1573     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
1574
1575         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1576         if (routerSubnets != null) {
1577             for (Uuid subnetId : routerSubnets) {
1578                 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
1579                 updateVpnForSubnet(routerId, subnetId, false);
1580             }
1581         }
1582         clearFromVpnMaps(vpnId, routerId, null);
1583         try {
1584             checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
1585             LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
1586                     vpnId.getValue());
1587         } catch (Exception e) {
1588             LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
1589                     .getValue(), vpnId.getValue(), e);
1590         }
1591     }
1592
1593     protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
1594         List<String> failedNwList = new ArrayList<>();
1595         List<Uuid> passedNwList = new ArrayList<>();
1596         if (!networks.isEmpty()) {
1597             // process corresponding subnets for VPN
1598             for (Uuid nw : networks) {
1599                 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1600                 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1601                 if (network == null) {
1602                     failedNwList.add(String.format("network %s not found", nw.getValue()));
1603                 } else if (vpnId != null) {
1604                     failedNwList.add(String.format("network %s already associated to another VPN %s", nw.getValue(),
1605                             vpnId.getValue()));
1606                 } else {
1607                     List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1608                     LOG.debug("Adding network subnets...{}", networkSubnets);
1609                     if (networkSubnets != null) {
1610                         for (Uuid subnet : networkSubnets) {
1611                             // check if subnet added as router interface to some router
1612                             Uuid subnetVpnId = NeutronvpnUtils.getVpnForSubnet(dataBroker, subnet);
1613                             if (subnetVpnId == null) {
1614                                 addSubnetToVpn(vpn, subnet);
1615                                 passedNwList.add(nw);
1616                             } else {
1617                                 failedNwList.add(String.format("subnet %s already added as router interface bound to " +
1618                                         "internal/external VPN %s", subnet.getValue (), subnetVpnId.getValue()));
1619                             }
1620                         }
1621                     }
1622                     if (NeutronvpnUtils.getIsExternal(network)) {
1623                         nvpnNatManager.addExternalNetworkToVpn(network, vpn);
1624                     }
1625                 }
1626             }
1627             updateVpnMaps(vpn, null, null, null, passedNwList);
1628         }
1629         return failedNwList;
1630     }
1631
1632     protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
1633         List<String> failedNwList = new ArrayList<>();
1634         List<Uuid> passedNwList = new ArrayList<>();
1635         if (networks != null && !networks.isEmpty()) {
1636             // process corresponding subnets for VPN
1637             for (Uuid nw : networks) {
1638                 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1639                 if (network == null) {
1640                     failedNwList.add(String.format("network %s not found", nw.getValue()));
1641                 } else {
1642                     Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1643                     if (vpn.equals(vpnId)) {
1644                         List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1645                         LOG.debug("Removing network subnets...");
1646                         if (networkSubnets != null) {
1647                             for (Uuid subnet : networkSubnets) {
1648                                 removeSubnetFromVpn(vpn, subnet);
1649                                 passedNwList.add(nw);
1650                             }
1651                         }
1652                     } else {
1653                         if (vpnId == null) {
1654                             failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
1655                                     .getValue()));
1656                         } else {
1657                             failedNwList.add(String.format("input network %s associated to a another vpn %s instead " +
1658                                     "of the one given as input", nw.getValue(), vpnId.getValue()));
1659                         }
1660                     }
1661                     if (NeutronvpnUtils.getIsExternal(network)) {
1662                         nvpnNatManager.removeExternalNetworkFromVpn(network);
1663                     }
1664                 }
1665             }
1666             clearFromVpnMaps(vpn, null, passedNwList);
1667         }
1668         return failedNwList;
1669     }
1670
1671     /**
1672      * It handles the invocations to the neutronvpn:associateNetworks RPC method
1673      *
1674      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#associateNetworks
1675      * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput)
1676      */
1677     @Override
1678     public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1679
1680         AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
1681         SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
1682         LOG.debug("associateNetworks {}", input);
1683         StringBuilder returnMsg = new StringBuilder();
1684         Uuid vpnId = input.getVpnId();
1685
1686         try {
1687             if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1688                 List<Uuid> netIds = input.getNetworkId();
1689                 if (netIds != null && !netIds.isEmpty()) {
1690                     List<String> failed = associateNetworksToVpn(vpnId, netIds);
1691                     if (!failed.isEmpty()) {
1692                         returnMsg.append(failed);
1693                     }
1694                 }
1695             } else {
1696                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1697             }
1698             if (returnMsg.length() != 0) {
1699                 String message = String.format("associate Networks to vpn %s failed due to %s",
1700                         vpnId.getValue(), returnMsg);
1701                 LOG.error(message);
1702                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
1703                         message);
1704                 opBuilder.setResponse(errorResponse);
1705                 result.set(RpcResultBuilder.<AssociateNetworksOutput> success().withResult(opBuilder.build()).build());
1706             } else {
1707                 result.set(RpcResultBuilder.<AssociateNetworksOutput> success().build());
1708             }
1709         } catch (Exception ex) {
1710             String message = String.format("associate Networks to vpn %s failed due to %s",
1711                     input.getVpnId().getValue(), ex.getMessage());
1712             LOG.error(message, ex);
1713             result.set(RpcResultBuilder.<AssociateNetworksOutput> failed().withError(ErrorType.APPLICATION, message)
1714                     .build());
1715         }
1716         LOG.debug("associateNetworks returns..");
1717         return result;
1718     }
1719
1720     /**
1721      * It handles the invocations to the neutronvpn:associateRouter RPC method
1722      *
1723      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#associateRouter
1724      * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput)
1725      */
1726     @Override
1727     public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1728
1729         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1730         LOG.debug("associateRouter {}", input);
1731         StringBuilder returnMsg = new StringBuilder();
1732         Uuid vpnId = input.getVpnId();
1733         Uuid routerId = input.getRouterId();
1734         try {
1735             VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1736             Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1737             if (vpnMap != null) {
1738                 if (rtr != null) {
1739                     Uuid extVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1740                     if (vpnMap.getRouterId() != null) {
1741                         returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
1742                                 .append(vpnMap.getRouterId().getValue());
1743                     } else if (extVpnId != null) {
1744                         returnMsg.append("router ").append(routerId.getValue()).append(" already associated to " +
1745                                 "another VPN ").append(extVpnId.getValue());
1746                     } else {
1747                         associateRouterToVpn(vpnId, routerId);
1748                     }
1749                 } else {
1750                     returnMsg.append("router not found : ").append(routerId.getValue());
1751                 }
1752             } else {
1753                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1754             }
1755             if (returnMsg.length() != 0) {
1756                 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1757                         returnMsg);
1758                 LOG.error(message);
1759                 result.set(RpcResultBuilder.<Void> failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1760                         .build());
1761             } else {
1762                 result.set(RpcResultBuilder.<Void> success().build());
1763             }
1764         } catch (Exception ex) {
1765             String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
1766                     vpnId.getValue(), ex.getMessage());
1767             LOG.error(message, ex);
1768             result.set(RpcResultBuilder.<Void> failed().withError(ErrorType.APPLICATION, message).build());
1769         }
1770         LOG.debug("associateRouter returns..");
1771         return result;
1772     }
1773
1774     /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method
1775      *
1776      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService#getFixedIPsForNeutronPort
1777      * (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput)
1778      */
1779     @Override
1780     public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(GetFixedIPsForNeutronPortInput input) {
1781         GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
1782         SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
1783         Uuid portId = input.getPortId();
1784         StringBuilder returnMsg = new StringBuilder();
1785         try {
1786             List<String> fixedIPList = new ArrayList<>();
1787             Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1788             if (port != null) {
1789                 List<FixedIps> fixedIPs = port.getFixedIps();
1790                 for (FixedIps ip : fixedIPs) {
1791                     fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
1792                 }
1793             } else {
1794                 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
1795             }
1796             if (returnMsg.length() != 0) {
1797                 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
1798                 LOG.error(message);
1799                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> failed()
1800                         .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
1801             } else {
1802                 opBuilder.setFixedIPs(fixedIPList);
1803                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> success().withResult(opBuilder.build())
1804                         .build());
1805                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> success().build());
1806             }
1807         } catch (Exception ex) {
1808             String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s",
1809                     portId.getValue(), ex.getMessage());
1810             LOG.error(message, ex);
1811             result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput> failed()
1812                     .withError(ErrorType.APPLICATION, message).build());
1813         }
1814         return result;
1815     }
1816
1817     /**
1818      * It handles the invocations to the neutronvpn:dissociateNetworks RPC method
1819      *
1820      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1821      * .rev150602.NeutronvpnService#dissociateNetworks(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
1822      * .neutronvpn.rev150602.DissociateNetworksInput)
1823      */
1824     @Override
1825     public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
1826
1827         DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
1828         SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
1829
1830         LOG.debug("dissociateNetworks {}", input);
1831         StringBuilder returnMsg = new StringBuilder();
1832         Uuid vpnId = input.getVpnId();
1833
1834         try {
1835             if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1836                 List<Uuid> netIds = input.getNetworkId();
1837                 if (netIds != null && !netIds.isEmpty()) {
1838                     List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
1839                     if (!failed.isEmpty()) {
1840                         returnMsg.append(failed);
1841                     }
1842                 }
1843             } else {
1844                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1845             }
1846             if (returnMsg.length() != 0) {
1847                 String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
1848                         returnMsg);
1849                 LOG.error(message);
1850                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1851                         + message);
1852                 opBuilder.setResponse(errorResponse);
1853                 result.set(RpcResultBuilder.<DissociateNetworksOutput> success().withResult(opBuilder.build()).build());
1854             } else {
1855                 result.set(RpcResultBuilder.<DissociateNetworksOutput> success().build());
1856             }
1857         } catch (Exception ex) {
1858             String message = String.format("dissociate Networks to vpn %s failed due to %s",
1859                     input.getVpnId().getValue(), ex.getMessage());
1860             LOG.error(message, ex);
1861             result.set(RpcResultBuilder.<DissociateNetworksOutput> failed().withError(ErrorType.APPLICATION, message)
1862                     .build());
1863         }
1864         LOG.debug("dissociateNetworks returns..");
1865         return result;
1866     }
1867
1868     /**
1869      * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
1870      *
1871      * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1872      * .rev150602.NeutronvpnService#dissociateRouter(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1873      * .rev150602.DissociateRouterInput)
1874      */
1875     @Override
1876     public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
1877
1878         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1879
1880         LOG.debug("dissociateRouter {}", input);
1881         StringBuilder returnMsg = new StringBuilder();
1882         Uuid vpnId = input.getVpnId();
1883         Uuid routerId = input.getRouterId();
1884         try {
1885             if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1886                 if (routerId != null) {
1887                     Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1888                     if (rtr != null) {
1889                         Uuid routerVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1890                         if (vpnId.equals(routerVpnId)) {
1891                             dissociateRouterFromVpn(vpnId, routerId);
1892                         } else {
1893                             if (routerVpnId == null) {
1894                                 returnMsg.append("input router ").append(routerId.getValue()).append(" not associated" +
1895                                         " to any vpn yet");
1896                             } else {
1897                                 returnMsg.append("input router ").append(routerId.getValue()).append(" associated to " +
1898                                         "vpn ").append(routerVpnId.getValue()).append("instead of the vpn given as " +
1899                                         "input");
1900                             }
1901                         }
1902                     } else {
1903                         returnMsg.append("router not found : ").append(routerId.getValue());
1904                     }
1905                 }
1906             } else {
1907                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1908             }
1909             if (returnMsg.length() != 0) {
1910                 String message = String.format("dissociate router %s to vpn %s failed due to %s", routerId.getValue(),
1911                         vpnId.getValue(), returnMsg);
1912                 LOG.error(message);
1913                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1914                         + message);
1915                 result.set(RpcResultBuilder.<Void> failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1916                         .build());
1917             } else {
1918                 result.set(RpcResultBuilder.<Void> success().build());
1919             }
1920         } catch (Exception ex) {
1921             String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
1922                     vpnId.getValue(), ex.getMessage());
1923             LOG.error(message, ex);
1924             result.set(RpcResultBuilder.<Void> failed().withError(ErrorType.APPLICATION, message).build());
1925         }
1926         LOG.debug("dissociateRouter returns..");
1927
1928         return result;
1929     }
1930
1931     protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
1932         // check if the router is associated to some VPN
1933         Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1934         if (vpnId != null) {
1935             // remove existing external vpn interfaces
1936             for (Uuid subnetId : routerSubnetIds) {
1937                 removeSubnetFromVpn(vpnId, subnetId);
1938             }
1939             clearFromVpnMaps(vpnId, routerId, null);
1940         } else {
1941             // remove existing internal vpn interfaces
1942             for (Uuid subnetId : routerSubnetIds) {
1943                 removeSubnetFromVpn(routerId, subnetId);
1944             }
1945         }
1946         // delete entire vpnMaps node for internal VPN
1947         deleteVpnMapsNode(routerId);
1948
1949         // delete vpn-instance for internal VPN
1950         deleteVpnInstance(routerId);
1951     }
1952
1953     protected Subnet getNeutronSubnet(Uuid subnetId){
1954         return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1955     }
1956
1957     protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
1958         Subnet sn = NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1959         if (null != sn) {
1960             return sn.getGatewayIp();
1961         }
1962         return null;
1963     }
1964
1965
1966     protected Network getNeutronNetwork(Uuid networkId) {
1967         return NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
1968     }
1969
1970     protected Port getNeutronPort(String name) {
1971         return NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(name));
1972     }
1973
1974     protected Port getNeutronPort(Uuid portId) {
1975         return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1976     }
1977
1978     protected List<Uuid> getSubnetsforVpn(Uuid vpnid) {
1979         List<Uuid> subnets = new ArrayList<>();
1980         // read subnetmaps
1981         InstanceIdentifier<Subnetmaps> subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build();
1982         Optional<Subnetmaps> subnetmaps = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1983                 subnetmapsid);
1984         if (subnetmaps.isPresent() && subnetmaps.get().getSubnetmap() != null) {
1985             List<Subnetmap> subnetMapList = subnetmaps.get().getSubnetmap();
1986             for (Subnetmap subnetMap : subnetMapList) {
1987                 if (subnetMap.getVpnId() != null && subnetMap.getVpnId().equals(vpnid)) {
1988                     subnets.add(subnetMap.getId());
1989                 }
1990             }
1991         }
1992         return subnets;
1993     }
1994
1995     /**
1996      * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command
1997      *
1998      * @return a List of String to be printed on screen
1999      */
2000     public List<String> showNeutronPortsCLI() {
2001         List<String> result = new ArrayList<>();
2002         result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", "Port ID", "Mac Address", "Prefix Length", "IP " +
2003                 "Address"));
2004         result.add("-------------------------------------------------------------------------------------------");
2005         InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2006         try {
2007             Optional<Ports> ports = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2008             if (ports.isPresent() && ports.get().getPort() != null) {
2009                 for (Port port : ports.get().getPort()) {
2010                     List<FixedIps> fixedIPs = port.getFixedIps();
2011                     try {
2012                         if (fixedIPs != null && !fixedIPs.isEmpty()) {
2013                             List<String> ipList = new ArrayList<>();
2014                             for (FixedIps fixedIp : fixedIPs) {
2015                                 IpAddress ipAddress = fixedIp.getIpAddress();
2016                                 if (ipAddress.getIpv4Address() != null) {
2017                                     ipList.add(ipAddress.getIpv4Address().getValue());
2018                                 } else {
2019                                     ipList.add((ipAddress.getIpv6Address().getValue()));
2020                                 }
2021                             }
2022                             result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
2023                                     .getMacAddress().getValue(), NeutronvpnUtils.getIPPrefixFromPort(dataBroker, port),
2024                                     ipList.toString()));
2025                         } else {
2026                             result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
2027                                     .getMacAddress().getValue(), "Not Assigned", "Not " + "Assigned"));
2028                         }
2029                     } catch (Exception e) {
2030                         LOG.error("Failed to retrieve neutronPorts info for port {}: ", port.getUuid().getValue(),
2031                                 e);
2032                         System.out.println("Failed to retrieve neutronPorts info for port: " + port.getUuid()
2033                                 .getValue() + ": " + e.getMessage());
2034                     }
2035                 }
2036             }
2037         } catch (Exception e) {
2038             LOG.error("Failed to retrieve neutronPorts info : ", e);
2039             System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
2040         }
2041         return result;
2042     }
2043
2044     /**
2045      * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command
2046      *
2047      * @param vpnuuid Uuid of the VPN whose config must be shown
2048      * @return formatted output list
2049      */
2050     public List<String> showVpnConfigCLI(Uuid vpnuuid) {
2051         List<String> result = new ArrayList<>();
2052         if (vpnuuid == null) {
2053             System.out.println("");
2054             System.out.println("Displaying VPN config for all VPNs");
2055             System.out.println("To display VPN config for a particular VPN, use the following syntax");
2056             System.out.println(getshowVpnConfigCLIHelp());
2057         }
2058         try {
2059             RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2060             if (rpcResult.isSuccessful()) {
2061                 result.add("");
2062                 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2063                 result.add("");
2064                 result.add(String.format(" %-80s ", "Import-RTs"));
2065                 result.add("");
2066                 result.add(String.format(" %-80s ", "Export-RTs"));
2067                 result.add("");
2068                 result.add(String.format(" %-76s ", "Subnet IDs"));
2069                 result.add("");
2070                 result.add("------------------------------------------------------------------------------------");
2071                 result.add("");
2072                 List<L3vpnInstances> VpnList = rpcResult.getResult().getL3vpnInstances();
2073                 for (L3vpnInstance Vpn : VpnList) {
2074                     String tenantId = Vpn.getTenantId() != null ? Vpn.getTenantId().getValue()
2075                             : "\"                 " + "                  \"";
2076                     result.add(String.format(" %-37s %-37s %-7s ", Vpn.getId().getValue(), tenantId,
2077                             Vpn.getRouteDistinguisher()));
2078                     result.add("");
2079                     result.add(String.format(" %-80s ", Vpn.getImportRT()));
2080                     result.add("");
2081                     result.add(String.format(" %-80s ", Vpn.getExportRT()));
2082                     result.add("");
2083
2084                     Uuid vpnid = Vpn.getId();
2085                     List<Uuid> subnetList = getSubnetsforVpn(vpnid);
2086                     if (!subnetList.isEmpty()) {
2087                         for (Uuid subnetuuid : subnetList) {
2088                             result.add(String.format(" %-76s ", subnetuuid.getValue()));
2089                         }
2090                     } else {
2091                         result.add(String.format(" %-76s ", "\"                                    \""));
2092                     }
2093                     result.add("");
2094                     result.add("----------------------------------------");
2095                     result.add("");
2096                 }
2097             } else {
2098                 String errortag = rpcResult.getErrors().iterator().next().getTag();
2099                 if (errortag == "") {
2100                     System.out.println("");
2101                     System.out.println("No VPN has been configured yet");
2102                 } else if (errortag == "invalid-value") {
2103                     System.out.println("");
2104                     System.out.println("VPN " + vpnuuid.getValue() + " is not present");
2105                 } else {
2106                     System.out.println("error getting VPN info : " + rpcResult.getErrors());
2107                     System.out.println(getshowVpnConfigCLIHelp());
2108                 }
2109             }
2110         } catch (InterruptedException | ExecutionException e) {
2111             LOG.error("error getting VPN info : ", e);
2112             System.out.println("error getting VPN info : " + e.getMessage());
2113         }
2114         return result;
2115     }
2116
2117     protected void createExternalVpnInterfaces(Uuid extNetId) {
2118         if (extNetId == null) {
2119             LOG.trace("external network is null");
2120             return;
2121         }
2122
2123         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2124         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2125             LOG.trace("No external ports attached to external network {}", extNetId.getValue());
2126             return;
2127         }
2128
2129         for (String elanInterface : extElanInterfaces) {
2130             createExternalVpnInterface(extNetId, elanInterface);
2131         }
2132     }
2133
2134     protected void removeExternalVpnInterfaces(Uuid extNetId) {
2135         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2136         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2137             LOG.trace("No external ports attached for external network {}", extNetId);
2138             return;
2139         }
2140
2141         for (String elanInterface : extElanInterfaces) {
2142             boolean isLockAcquired = false;
2143             InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2144                     .buildVpnInterfaceIdentifier(elanInterface);
2145             try {
2146                 isLockAcquired = NeutronvpnUtils.lock(elanInterface);
2147                 LOG.debug("removing vpn interface {}, vpnIfIdentifier", elanInterface, vpnIfIdentifier);
2148                 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2149             } catch (Exception ex) {
2150                 LOG.error("Removal of vpninterface {} failed due to {}", elanInterface, ex);
2151             } finally {
2152                 if (isLockAcquired) {
2153                     NeutronvpnUtils.unlock(elanInterface);
2154                 }
2155             }
2156         }
2157     }
2158
2159     private void createExternalVpnInterface(Uuid vpnId, String infName) {
2160         writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, null);
2161     }
2162
2163     private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
2164             Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2165         if (vpnId == null || infName == null) {
2166             LOG.debug("vpn id or interface is null");
2167             return;
2168         }
2169
2170         Boolean wrtConfigTxnPresent = true;
2171         if (wrtConfigTxn == null) {
2172             wrtConfigTxnPresent = false;
2173             wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2174         }
2175
2176         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2177         VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2178                 .setName(infName)
2179                 .setVpnInstanceName(vpnId.getValue())
2180                 .setIsRouterInterface(isRouterInterface);
2181         if (adjacencies != null) {
2182             vpnb.addAugmentation(Adjacencies.class, adjacencies);
2183         }
2184         VpnInterface vpnIf = vpnb.build();
2185         try {
2186             LOG.info("Creating vpn interface {}", vpnIf);
2187             wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2188         } catch (Exception ex) {
2189             LOG.error("Creation of vpninterface {} failed due to {}", infName, ex);
2190         }
2191
2192         if (!wrtConfigTxnPresent) {
2193             wrtConfigTxn.submit();
2194         }
2195     }
2196
2197     private String getshowVpnConfigCLIHelp() {
2198         StringBuilder help = new StringBuilder("Usage:");
2199         help.append("display vpn-config [-vid/--vpnid <id>]");
2200         return help.toString();
2201     }
2202
2203     private void checkAndPublishSubnetAddNotification(Uuid subnetId, String subnetIp, String vpnName,
2204                                                       Boolean isExternalvpn, Long elanTag) throws InterruptedException {
2205         SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
2206
2207         LOG.info("publish notification called");
2208
2209         builder.setSubnetId(subnetId);
2210         builder.setSubnetIp(subnetIp);
2211         builder.setVpnName(vpnName);
2212         builder.setExternalVpn(isExternalvpn);
2213         builder.setElanTag(elanTag);
2214
2215         notificationPublishService.putNotification(builder.build());
2216     }
2217
2218     private void checkAndPublishSubnetDelNotification(Uuid subnetId, String subnetIp, String vpnName,
2219                                                       Boolean isExternalvpn, Long elanTag) throws InterruptedException {
2220         SubnetDeletedFromVpnBuilder builder = new SubnetDeletedFromVpnBuilder();
2221
2222         LOG.info("publish notification called");
2223
2224         builder.setSubnetId(subnetId);
2225         builder.setSubnetIp(subnetIp);
2226         builder.setVpnName(vpnName);
2227         builder.setExternalVpn(isExternalvpn);
2228         builder.setElanTag(elanTag);
2229
2230         notificationPublishService.putNotification(builder.build());
2231     }
2232
2233     private void checkAndPublishSubnetUpdNotification(Uuid subnetId, String subnetIp, String vpnName,
2234                                                       Boolean isExternalvpn, Long elanTag) throws InterruptedException {
2235         SubnetUpdatedInVpnBuilder builder = new SubnetUpdatedInVpnBuilder();
2236
2237         LOG.info("publish notification called");
2238
2239         builder.setSubnetId(subnetId);
2240         builder.setSubnetIp(subnetIp);
2241         builder.setVpnName(vpnName);
2242         builder.setExternalVpn(isExternalvpn);
2243         builder.setElanTag(elanTag);
2244
2245         notificationPublishService.putNotification(builder.build());
2246     }
2247
2248     private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
2249             InterruptedException {
2250         RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
2251                 .setVpnId(vpnId).build();
2252         LOG.info("publishing notification upon association of router to VPN");
2253         notificationPublishService.putNotification(routerAssociatedToVpn);
2254     }
2255
2256     private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
2257             InterruptedException {
2258         RouterDisassociatedFromVpn routerDisassociatedFromVpn = new RouterDisassociatedFromVpnBuilder().setRouterId
2259                 (routerId).setVpnId(vpnId).build();
2260         LOG.info("publishing notification upon disassociation of router from VPN");
2261         notificationPublishService.putNotification(routerDisassociatedFromVpn);
2262     }
2263
2264     protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
2265         floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
2266     }
2267 }