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