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