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