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