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