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