Unsupport operation exception in NeutronvpnManager.java
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnManager.java
1 /*
2  * Copyright © 2015, 2018 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 static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13
14 import com.google.common.base.Optional;
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.JdkFutureAdapters;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture;
22 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.Objects;
34 import java.util.Set;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.locks.ReentrantLock;
40 import java.util.function.Consumer;
41 import javax.annotation.PreDestroy;
42 import javax.inject.Inject;
43 import javax.inject.Singleton;
44 import org.eclipse.jdt.annotation.NonNull;
45 import org.eclipse.jdt.annotation.Nullable;
46 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
50 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
51 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
52 import org.opendaylight.genius.infra.Datastore.Configuration;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
55 import org.opendaylight.genius.infra.TypedWriteTransaction;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.genius.utils.JvmGlobalLocks;
58 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
59 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
60 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
61 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
62 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
63 import org.opendaylight.netvirt.elanmanager.api.IElanService;
64 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
65 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
66 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
67 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
68 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
69 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
70 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
86 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
87 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
180 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
181 import org.opendaylight.yangtools.yang.common.RpcError;
182 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
183 import org.opendaylight.yangtools.yang.common.RpcResult;
184 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
185 import org.slf4j.Logger;
186 import org.slf4j.LoggerFactory;
187 import org.slf4j.helpers.FormattingTuple;
188 import org.slf4j.helpers.MessageFormatter;
189
190 @Singleton
191 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
192
193     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
194     private static final long LOCK_WAIT_TIME = 10L;
195
196     private final DataBroker dataBroker;
197     private final ManagedNewTransactionRunner txRunner;
198     private final VpnRpcService vpnRpcService;
199     private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
200     private final IElanService elanService;
201     private final NeutronvpnConfig neutronvpnConfig;
202     private final NeutronEvpnManager neutronEvpnManager;
203     private final NeutronEvpnUtils neutronEvpnUtils;
204     private final JobCoordinator jobCoordinator;
205     private final NeutronvpnUtils neutronvpnUtils;
206     private final IVpnManager vpnManager;
207     private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
208     private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
209     private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
210     private final NamedLocks<String> interfaceLock = new NamedLocks<>();
211
212     @Inject
213     public NeutronvpnManager(
214             final DataBroker dataBroker,
215             final VpnRpcService vpnRpcSrv, final IElanService elanService,
216             final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
217             final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
218             final JobCoordinator jobCoordinator,
219             final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
220         this.dataBroker = dataBroker;
221         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
222         vpnRpcService = vpnRpcSrv;
223         this.elanService = elanService;
224         floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
225         this.neutronvpnConfig = neutronvpnConfig;
226         neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
227         neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
228         this.jobCoordinator = jobCoordinator;
229         this.neutronvpnUtils = neutronvpnUtils;
230         this.vpnManager = vpnManager;
231
232         configureFeatures();
233     }
234
235     @Override
236     @PreDestroy
237     public void close() {
238         LOG.info("{} close", getClass().getSimpleName());
239     }
240
241     private void configureFeatures() throws TransactionCommitFailedException {
242         InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
243                         Neutron.class).child(Features.class).child(
244                         Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
245         Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
246         try {
247             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
248         } catch (OptimisticLockFailedException e) {
249             LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
250         }
251         InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
252                 Neutron.class).child(Features.class).child(
253                 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
254         Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
255         try {
256             SingleTransactionDataBroker.syncWrite(
257                     dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
258         } catch (OptimisticLockFailedException e) {
259             LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
260         }
261     }
262
263     public String getOpenDaylightVniRangesConfig() {
264         return neutronvpnConfig.getOpendaylightVniRanges();
265     }
266
267     // TODO Clean up the exception handling
268     @SuppressWarnings("checkstyle:IllegalCatch")
269     protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
270                                        NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
271                                         boolean isExternalNw) {
272         try {
273             InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
274             final ReentrantLock lock = lockForUuid(subnetId);
275             lock.lock();
276             try {
277                 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
278                 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
279                         LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
280                 if (sn.isPresent()) {
281                     LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
282                         subnetId.getValue());
283                     return;
284                 }
285                 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
286                         .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
287                         .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
288                 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
289                     subnetId.getValue());
290                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
291                         subnetMapIdentifier, subnetmapBuilder.build());
292             } finally {
293                 lock.unlock();
294             }
295         } catch (TransactionCommitFailedException | ReadFailedException e) {
296             LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
297         }
298         // check if there are ports to update for already created Subnetmap node
299         LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
300         for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
301             if (entry.getValue().getValue().equals(subnetId.getValue())) {
302                 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
303                 unprocessedPortsMap.remove(entry.getKey());
304             }
305         }
306     }
307
308     @Nullable
309     protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
310             @Nullable Uuid internetvpnId) {
311         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
312                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
313                 .build();
314         final ReentrantLock lock = lockForUuid(subnetId);
315         lock.lock();
316         try {
317             Optional<Subnetmap> sn =
318                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
319             if (!sn.isPresent()) {
320                 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
321                 return null;
322             }
323             LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
324             SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
325             if (routerId != null) {
326                 builder.setRouterId(routerId);
327             }
328             if (vpnId != null) {
329                 builder.setVpnId(vpnId);
330             }
331             if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
332                 builder.setInternetVpnId(internetvpnId);
333             }
334             Subnetmap subnetmap = builder.build();
335             LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
336             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
337             return subnetmap;
338         } catch (ReadFailedException | TransactionCommitFailedException e) {
339             LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
340             return null;
341         } finally {
342             lock.unlock();
343         }
344     }
345
346     protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
347                                                @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
348                                                @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
349         InstanceIdentifier<Subnetmap> id =
350                 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
351         final ReentrantLock lock = lockForUuid(subnetId);
352         lock.lock();
353         try {
354             Optional<Subnetmap> sn =
355                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
356             if (!sn.isPresent()) {
357                 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
358                     subnetId.getValue());
359                 return;
360             }
361             LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
362                 subnetId.getValue());
363             SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
364             builder.setRouterId(routerId);
365             builder.setRouterInterfacePortId(routerInterfacePortId);
366             builder.setRouterIntfMacAddress(routerIntfMacAddress);
367             builder.setRouterInterfaceFixedIp(fixedIp);
368             if (vpnId != null) {
369                 builder.setVpnId(vpnId);
370             }
371             Subnetmap subnetmap = builder.build();
372             LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
373                 subnetId.getValue());
374             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
375         } catch (ReadFailedException | TransactionCommitFailedException e) {
376             LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
377                 subnetId.getValue(), e);
378         } finally {
379             lock.unlock();
380         }
381     }
382
383     protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
384             @Nullable Uuid directPortId) {
385         Subnetmap subnetmap = null;
386         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
387                 new SubnetmapKey(subnetId)).build();
388         LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
389         final ReentrantLock lock = lockForUuid(subnetId);
390         lock.lock();
391         try {
392             Optional<Subnetmap> sn =
393                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
394                         id);
395             if (sn.isPresent()) {
396                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
397                 if (null != portId) {
398                     List<Uuid> existingPortList = builder.getPortList();
399                     List<Uuid> portList = new ArrayList<>();
400                     if (null != existingPortList) {
401                         portList.addAll(existingPortList);
402                     }
403                     portList.add(portId);
404                     builder.setPortList(portList);
405                     LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
406                         subnetId.getValue(), portId.getValue());
407                 }
408                 if (null != directPortId) {
409                     List<Uuid> existingDirectPortList = builder.getDirectPortList();
410                     List<Uuid> directPortList = new ArrayList<>();
411                     if (null != existingDirectPortList) {
412                         directPortList.addAll(existingDirectPortList);
413                     }
414                     directPortList.add(directPortId);
415                     builder.setDirectPortList(directPortList);
416                     LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
417                         directPortId.getValue());
418                 }
419                 subnetmap = builder.build();
420                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
421                     subnetmap);
422             } else {
423                 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
424                         + "cache ", subnetId.getValue(), portId.getValue());
425                 unprocessedPortsMap.put(portId, subnetId);
426             }
427         } catch (ReadFailedException | TransactionCommitFailedException e) {
428             LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
429         } finally {
430             lock.unlock();
431         }
432         return subnetmap;
433     }
434
435     protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
436                                             Uuid vpnId, @Nullable Uuid portId) {
437         Subnetmap subnetmap = null;
438         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
439                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
440                 .build();
441         final ReentrantLock lock = lockForUuid(subnetId);
442         lock.lock();
443         try {
444             Optional<Subnetmap> sn =
445                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
446                         id);
447             if (sn.isPresent()) {
448                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
449                 if (routerId != null) {
450                     builder.setRouterId(null);
451                 }
452                 if (networkId != null) {
453                     builder.setNetworkId(null);
454                 }
455                 if (vpnId != null) {
456                     builder.setVpnId(null);
457                 }
458                 builder.setInternetVpnId(null);
459                 if (portId != null && builder.getPortList() != null) {
460                     List<Uuid> portList = new ArrayList<>(builder.getPortList());
461                     portList.remove(portId);
462                     builder.setPortList(portList);
463                 }
464
465                 subnetmap = builder.build();
466                 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
467                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
468                     subnetmap);
469             } else {
470                 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
471             }
472         } catch (ReadFailedException | TransactionCommitFailedException e) {
473             LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
474         } finally {
475             lock.unlock();
476         }
477         return subnetmap;
478     }
479
480     @Nullable
481     protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
482             @Nullable Uuid directPortId) {
483         Subnetmap subnetmap = null;
484         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
485                 new SubnetmapKey(subnetId)).build();
486         final ReentrantLock lock = lockForUuid(subnetId);
487         lock.lock();
488         try {
489             Optional<Subnetmap> sn =
490                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
491                         id);
492             if (sn.isPresent()) {
493                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
494                 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
495                     List<Uuid> portList = new ArrayList<>(builder.getPortList());
496                     portList.remove(portId);
497                     builder.setPortList(portList);
498                     LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
499                         subnetId.getValue());
500                 }
501                 if (null != directPortId && null != builder.getDirectPortList()
502                         && !builder.getDirectPortList().isEmpty()) {
503                     List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
504                     directPortList.remove(directPortId);
505                     builder.setDirectPortList(directPortList);
506                     LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
507                         .getValue(), subnetId.getValue());
508                 }
509                 subnetmap = builder.build();
510                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
511                     subnetmap);
512             } else {
513                 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
514             }
515         } catch (ReadFailedException | TransactionCommitFailedException e) {
516             LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
517                     subnetId.getValue(), e);
518         } finally {
519             lock.unlock();
520         }
521         return subnetmap;
522     }
523
524     // TODO Clean up the exception handling
525     @SuppressWarnings("checkstyle:IllegalCatch")
526     protected void deleteSubnetMapNode(Uuid subnetId) {
527         InstanceIdentifier<Subnetmap> subnetMapIdentifier =
528                 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
529         LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
530         final ReentrantLock lock = lockForUuid(subnetId);
531         lock.lock();
532         try {
533             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
534         } catch (TransactionCommitFailedException e) {
535             LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
536         } finally {
537             lock.unlock();
538         }
539     }
540
541     public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
542         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
543             .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
544         try {
545             Optional<VpnInstance> vpnInstanceConfig =
546                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
547                             vpnIdentifier);
548             if (!vpnInstanceConfig.isPresent()) {
549                 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
550                 return;
551             }
552             VpnInstance vpnInstance = vpnInstanceConfig.get();
553             VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
554             if (vpnInstance.getIpv4Family() != null) {
555                 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
556                 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
557             }
558             if (vpnInstance.getIpv6Family() != null) {
559                 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
560                 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
561             }
562             LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
563             SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
564                     updateVpnInstanceBuilder.build());
565         } catch (ReadFailedException | TransactionCommitFailedException ex) {
566             LOG.warn("Error configuring feature ", ex);
567         }
568     }
569
570     private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
571                                        VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
572         String vpnName = vpnId.getValue();
573         VpnInstanceBuilder builder = null;
574         List<VpnTarget> vpnTargetList = new ArrayList<>();
575         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
576             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
577         Optional<VpnInstance> optionalVpn;
578         try {
579             optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
580                 vpnIdentifier);
581         } catch (ReadFailedException e) {
582             LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
583             return;
584         }
585
586         LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
587         if (optionalVpn.isPresent()) {
588             builder = new VpnInstanceBuilder(optionalVpn.get());
589             LOG.debug("updating existing vpninstance node");
590         } else {
591             builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
592                     .setType(type).setL3vni(l3vni);
593         }
594         if (irt != null && !irt.isEmpty()) {
595             if (ert != null && !ert.isEmpty()) {
596                 List<String> commonRT = new ArrayList<>(irt);
597                 commonRT.retainAll(ert);
598
599                 for (String common : commonRT) {
600                     irt.remove(common);
601                     ert.remove(common);
602                     VpnTarget vpnTarget =
603                             new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
604                             .setVrfRTType(VpnTarget.VrfRTType.Both).build();
605                     vpnTargetList.add(vpnTarget);
606                 }
607             }
608             for (String importRT : irt) {
609                 VpnTarget vpnTarget =
610                         new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
611                         .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
612                 vpnTargetList.add(vpnTarget);
613             }
614         }
615
616         if (ert != null && !ert.isEmpty()) {
617             for (String exportRT : ert) {
618                 VpnTarget vpnTarget =
619                         new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
620                         .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
621                 vpnTargetList.add(vpnTarget);
622             }
623         }
624
625         VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
626         Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
627         Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
628
629         if (rd != null && !rd.isEmpty()) {
630             ipv4vpnBuilder.setRouteDistinguisher(rd);
631             ipv6vpnBuilder.setRouteDistinguisher(rd);
632         }
633
634         if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
635             builder.setIpv4Family(ipv4vpnBuilder.build());
636         }
637         if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
638             builder.setIpv6Family(ipv6vpnBuilder.build());
639         }
640         if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
641             builder.setIpv4Family(ipv4vpnBuilder.build());
642         }
643         VpnInstance newVpn = builder.build();
644
645         try (AcquireResult lock = tryVpnLock(vpnId)) {
646             if (!lock.wasAcquired()) {
647                 // FIXME: why do we even bother with locking if we do not honor it?!
648                 logTryLockFailure(vpnId);
649             }
650
651             LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
652             try {
653                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
654                     newVpn);
655             } catch (TransactionCommitFailedException e) {
656                 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
657             }
658         }
659     }
660
661     private void deleteVpnMapsNode(Uuid vpnId) {
662         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
663                 .child(VpnMap.class, new VpnMapKey(vpnId))
664                 .build();
665         LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
666         try (AcquireResult lock = tryVpnLock(vpnId)) {
667             if (!lock.wasAcquired()) {
668                 // FIXME: why do we even bother with locking if we do not honor it?!
669                 logTryLockFailure(vpnId);
670             }
671
672             try {
673                 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
674                     vpnMapIdentifier);
675             } catch (TransactionCommitFailedException e) {
676                 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
677             }
678         }
679     }
680
681     protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
682             @Nullable List<Uuid> networks) {
683         VpnMapBuilder builder;
684         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
685                 .child(VpnMap.class, new VpnMapKey(vpnId))
686                 .build();
687         try {
688             Optional<VpnMap> optionalVpnMap =
689                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
690                             vpnMapIdentifier);
691             if (optionalVpnMap.isPresent()) {
692                 builder = new VpnMapBuilder(optionalVpnMap.get());
693             } else {
694                 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
695             }
696
697             if (name != null) {
698                 builder.setName(name);
699             }
700             if (tenantId != null) {
701                 builder.setTenantId(tenantId);
702             }
703             if (router != null) {
704                 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
705                 List<RouterIds> rtrIds = builder.getRouterIds() != null
706                         ? new ArrayList<>(builder.getRouterIds()) : null;
707                 if (rtrIds == null) {
708                     rtrIds = Collections.singletonList(vpnRouterId);
709                 } else {
710                     rtrIds.add(vpnRouterId);
711                 }
712                 builder.setRouterIds(rtrIds);
713             }
714             if (networks != null) {
715                 List<Uuid> nwList = builder.getNetworkIds() != null
716                     ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
717                 nwList.addAll(networks);
718                 builder.setNetworkIds(nwList);
719             }
720
721             try (AcquireResult lock = tryVpnLock(vpnId)) {
722                 if (!lock.wasAcquired()) {
723                     // FIXME: why do we even bother with locking if we do not honor it?!
724                     logTryLockFailure(vpnId);
725                 }
726
727                 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
728                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
729                         builder.build());
730                 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
731             }
732         } catch (ReadFailedException | TransactionCommitFailedException e) {
733             LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
734         }
735     }
736
737     private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
738         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
739                 .child(VpnMap.class, new VpnMapKey(vpnId))
740                 .build();
741         Optional<VpnMap> optionalVpnMap;
742         try {
743             optionalVpnMap =
744                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
745                             vpnMapIdentifier);
746         } catch (ReadFailedException e) {
747             LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
748             return;
749         }
750         if (optionalVpnMap.isPresent()) {
751             VpnMap vpnMap = optionalVpnMap.get();
752             VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
753             List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds());
754             if (rtrIds == null) {
755                 rtrIds = new ArrayList<>();
756             }
757             if (routerId != null) {
758                 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
759                     rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
760                     vpnMapBuilder.setRouterIds(rtrIds);
761
762                     try (AcquireResult lock = tryVpnLock(vpnId)) {
763                         if (!lock.wasAcquired()) {
764                             // FIXME: why do we even bother with locking if we do not honor it?!
765                             logTryLockFailure(vpnId);
766                         }
767
768                         LOG.debug("removing vpnMaps node: {} ", vpnId);
769                         try {
770                             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
771                                     vpnMapIdentifier);
772                         } catch (TransactionCommitFailedException e) {
773                             LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
774                         }
775                     }
776                     return;
777                 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
778                     rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
779                     vpnMapBuilder.setRouterIds(rtrIds);
780                     LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
781                 }
782             }
783             if (networkIds != null) {
784                 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
785                         ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
786                 vpnNw.removeAll(networkIds);
787                 if (vpnNw.isEmpty()) {
788                     LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
789                     vpnMapBuilder.setNetworkIds(null);
790                 } else {
791                     vpnMapBuilder.setNetworkIds(vpnNw);
792                 }
793             }
794
795             try (AcquireResult lock = tryVpnLock(vpnId)) {
796                 if (!lock.wasAcquired()) {
797                     // FIXME: why do we even bother with locking if we do not honor it?!
798                     logTryLockFailure(vpnId);
799                 }
800
801                 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
802                 try {
803                     SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
804                         vpnMapIdentifier, vpnMapBuilder.build());
805                 } catch (TransactionCommitFailedException e) {
806                     LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
807                 }
808             }
809         } else {
810             LOG.error("VPN : {} not found", vpnId.getValue());
811         }
812         LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
813     }
814
815     private void deleteVpnInstance(Uuid vpnId) {
816         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
817                 .child(VpnInstance.class,
818                         new VpnInstanceKey(vpnId.getValue()))
819                 .build();
820
821         try (AcquireResult lock = tryVpnLock(vpnId)) {
822             if (!lock.wasAcquired()) {
823                 // FIXME: why do we even bother with locking if we do not honor it?!
824                 logTryLockFailure(vpnId);
825             }
826
827             LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
828             try {
829                 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
830             } catch (TransactionCommitFailedException e) {
831                 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
832             }
833         }
834     }
835
836     protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
837                                                   TypedWriteTransaction<Configuration> wrtConfigTxn,
838                                                   @Nullable VpnInterface vpnIface) {
839         List<Adjacency> adjList = new ArrayList<>();
840         if (vpnIface != null) {
841             adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
842         }
843         String infName = port.getUuid().getValue();
844         LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
845         for (FixedIps ip : port.nonnullFixedIps()) {
846             String ipValue = ip.getIpAddress().stringValue();
847             String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
848             Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
849             if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
850                     snTemp.getSubnetIp(), false)) {
851                 continue;
852             }
853             Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
854             if (vpnId != null) {
855                 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
856                         infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
857                 //Create Neutron port adjacency if VPN presence is existing for subnet
858                 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
859                         .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
860                         .setSubnetId(ip.getSubnetId()).build();
861                 if (!adjList.contains(vmAdj)) {
862                     adjList.add(vmAdj);
863                 }
864             }
865             Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
866             if (snTemp != null && snTemp.getInternetVpnId() != null) {
867                 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
868                     ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
869             }
870             if (routerId != null) {
871                 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
872                 if (rtr != null && rtr.getRoutes() != null) {
873                     List<Routes> routeList = rtr.getRoutes();
874                     // create extraroute Adjacence for each ipValue,
875                     // because router can have IPv4 and IPv6 subnet ports, or can have
876                     // more that one IPv4 subnet port or more than one IPv6 subnet port
877                     List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
878                     if (!erAdjList.isEmpty()) {
879                         adjList.addAll(erAdjList);
880                     }
881                 }
882             }
883         }
884         return new AdjacenciesBuilder().setAdjacency(adjList).build();
885     }
886
887     protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
888                                       @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
889         boolean isRouterInterface = false;
890         if (port.getDeviceOwner() != null) {
891             isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
892         }
893         String infName = port.getUuid().getValue();
894         // Handling cluster reboot scenario where VpnInterface already exists in datastore.
895         VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
896         Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
897         LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
898         writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
899     }
900
901     protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
902                        Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
903         String infName = port.getUuid().getValue();
904         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
905         Optional<VpnInterface> optionalVpnInterface = null;
906         LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
907                   vpnId, internetVpnId, infName);
908         try {
909             optionalVpnInterface = SingleTransactionDataBroker
910                     .syncReadOptional(dataBroker, LogicalDatastoreType
911                     .CONFIGURATION, vpnIfIdentifier);
912         } catch (ReadFailedException e) {
913             LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
914             return;
915         }
916         if (!optionalVpnInterface.isPresent()) {
917             return;
918         }
919         LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
920                 sn != null ? sn.getSubnetIp() : "null");
921         List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
922         List<Adjacency> updatedAdjsList = new ArrayList<>();
923         boolean isIpFromAnotherSubnet = false;
924         for (Adjacency adj : vpnAdjsList) {
925             String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
926             if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
927                 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
928                     isIpFromAnotherSubnet = true;
929                 }
930                 updatedAdjsList.add(adj);
931                 continue;
932             }
933             if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
934                 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
935                       adjString, vpnId);
936                 if (vpnId != null) {
937                     neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
938                             String.valueOf(adjString), wrtConfigTxn);
939                 }
940                 if (internetVpnId != null) {
941                     neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
942                           String.valueOf(adjString), wrtConfigTxn);
943                 }
944             } else {
945                 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
946                         && sn.getRouterId() != null) {
947                     Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
948                     if (rtr != null && rtr.getRoutes() != null) {
949                         List<Routes> extraRoutesToRemove = new ArrayList<>();
950                         for (Routes rt: rtr.getRoutes()) {
951                             if (rt.getNexthop().toString().equals(adjString)) {
952                                 extraRoutesToRemove.add(rt);
953                             }
954                         }
955                         if (vpnId != null) {
956                             LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
957                                   extraRoutesToRemove, vpnId);
958                             removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
959                         }
960                         /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
961                     }
962                 }
963             }
964         }
965         Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
966         if (vpnId != null) {
967             updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
968         }
969         if (!isIpFromAnotherSubnet) {
970             // no more subnetworks for neutron port
971             if (sn != null && sn.getRouterId() != null) {
972                 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
973             }
974             deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
975             return;
976         }
977         return;
978     }
979
980     // TODO Clean up the exception handling
981     @SuppressWarnings("checkstyle:IllegalCatch")
982     protected void deleteVpnInterface(String infName, @Nullable String vpnId,
983                                       @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
984         if (wrtConfigTxn == null) {
985             ListenableFutures.addErrorLogging(
986                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
987                         tx -> deleteVpnInterface(infName, vpnId, tx)),
988                     LOG, "Error deleting VPN interface {} {}", infName, vpnId);
989             return;
990         }
991
992         InstanceIdentifier<VpnInterface> vpnIfIdentifier =
993             NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
994         Optional<VpnInterface> optionalVpnInterface;
995         try {
996             optionalVpnInterface =
997                 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
998                             vpnIfIdentifier);
999         } catch (ReadFailedException ex) {
1000             LOG.error("Error during deletion of vpninterface {}", infName, ex);
1001             return;
1002         }
1003         if (!optionalVpnInterface.isPresent()) {
1004             LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
1005             return;
1006         }
1007         if (vpnId != null) {
1008             VpnInterface vpnInterface = optionalVpnInterface.get();
1009             List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
1010             if (vpnList != null
1011                 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
1012                 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
1013                 if (!vpnList.isEmpty()) {
1014                     LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1015                             + "List not empty", infName);
1016                     return;
1017                 }
1018                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1019                         .setVpnInstanceNames(vpnList);
1020                 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1021                         .build());
1022             }
1023         }
1024         LOG.debug("Deleting vpn interface {}", infName);
1025         wrtConfigTxn.delete(vpnIfIdentifier);
1026     }
1027
1028     protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1029                                              TypedWriteTransaction<Configuration> writeConfigTxn,
1030                                              Subnetmap sm) {
1031         if (vpnId == null || port == null) {
1032             return;
1033         }
1034         String infName = port.getUuid().getValue();
1035         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1036         try {
1037             Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1038                     .syncReadOptional(dataBroker, LogicalDatastoreType
1039                     .CONFIGURATION, vpnIfIdentifier);
1040             if (optionalVpnInterface.isPresent()) {
1041                 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1042                 if (listVpn != null
1043                     && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1044                     VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1045                 }
1046                 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1047                          .setVpnInstanceNames(listVpn);
1048                 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1049                 LOG.debug("Updating vpn interface {}", infName);
1050                 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1051                 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1052                 while (adjacencyIter.hasNext()) {
1053                     Adjacency adjacency = adjacencyIter.next();
1054                     if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1055                         continue;
1056                     }
1057                     String mipToQuery = adjacency.getIpAddress().split("/")[0];
1058                     InstanceIdentifier<LearntVpnVipToPort> id =
1059                         NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1060                     Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1061                             SingleTransactionDataBroker.syncReadOptional(dataBroker,
1062                                     LogicalDatastoreType.OPERATIONAL, id);
1063                     if (optionalVpnVipToPort.isPresent()) {
1064                         LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1065                              infName, vpnId);
1066                         if (listVpn == null || listVpn.isEmpty()) {
1067                             adjacencyIter.remove();
1068                         }
1069                         neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1070                         LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1071                                 mipToQuery, infName, vpnId.getValue());
1072                     }
1073                 }
1074                 for (FixedIps ip : port.nonnullFixedIps()) {
1075                     String ipValue = ip.getIpAddress().stringValue();
1076                     //skip IPv4 address
1077                     if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1078                         continue;
1079                     }
1080                     neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1081                             ipValue, writeConfigTxn);
1082                 }
1083                 if (listVpn == null || listVpn.isEmpty()) {
1084                     if (sm != null && sm.getRouterId() != null) {
1085                         removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1086                     }
1087                     deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1088                 } else {
1089                     writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1090                 }
1091             } else {
1092                 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1093             }
1094         } catch (ReadFailedException ex) {
1095             LOG.error("Update of vpninterface {} failed", infName, ex);
1096         }
1097     }
1098
1099     protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1100                                       boolean isSubnetIp,
1101                                       TypedWriteTransaction<Configuration> writeConfigTxn,
1102                                       boolean isInternetVpn) {
1103         if (vpnId == null || port == null) {
1104             return;
1105         }
1106         String infName = port.getUuid().getValue();
1107         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1108
1109         try (AcquireResult lock = tryInterfaceLock(infName)) {
1110             if (!lock.wasAcquired()) {
1111                 // FIXME: why do we even bother with locking if we do not honor it?!
1112                 logTryLockFailure(infName);
1113             }
1114
1115             try {
1116                 Optional<VpnInterface> optionalVpnInterface =
1117                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1118                             vpnIfIdentifier);
1119                 if (optionalVpnInterface.isPresent()) {
1120                     VpnInstanceNames vpnInstance = VpnHelper
1121                             .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1122                     List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1123                             .get().getVpnInstanceNames());
1124                     if (oldVpnId != null
1125                             && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1126                         VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1127                     }
1128                     if (vpnId.getValue() != null
1129                             && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1130                         listVpn.add(vpnInstance);
1131                     }
1132                     VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1133                             .setVpnInstanceNames(listVpn);
1134                     LOG.debug("Updating vpn interface {}", infName);
1135                     if (!isBeingAssociated) {
1136                         Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1137                         List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1138                         Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1139                         while (adjacencyIter.hasNext()) {
1140                             Adjacency adjacency = adjacencyIter.next();
1141                             String mipToQuery = adjacency.getIpAddress().split("/")[0];
1142                             InstanceIdentifier<LearntVpnVipToPort> id =
1143                                     NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1144                             Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1145                                     SingleTransactionDataBroker.syncReadOptional(dataBroker,
1146                                         LogicalDatastoreType.OPERATIONAL, id);
1147                             if (optionalVpnVipToPort.isPresent()
1148                                     && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1149                                 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1150                                         + "from VPN {}", infName, vpnId, oldVpnId);
1151                                 adjacencyIter.remove();
1152                                 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1153                                 LOG.trace(
1154                                     "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1155                                     mipToQuery, infName, vpnId.getValue());
1156                             }
1157                             InstanceIdentifier<VpnPortipToPort> build =
1158                                     NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1159                             Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1160                                 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1161                             if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1162                                 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1163                                 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1164                                     mipToQuery, infName, vpnId.getValue());
1165                             }
1166                         }
1167                         Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1168                         vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1169                     }
1170                     for (FixedIps ip : port.nonnullFixedIps()) {
1171                         String ipValue = ip.getIpAddress().stringValue();
1172                         if (oldVpnId != null) {
1173                             neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1174                                 ipValue, writeConfigTxn);
1175                         }
1176                         if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1177                                 && isInternetVpn == true) {
1178                             continue;
1179                         }
1180
1181                         neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1182                             .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1183                     }
1184                     writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1185                 } else {
1186                     LOG.error("VPN Interface {} not found", infName);
1187                 }
1188             } catch (ReadFailedException ex) {
1189                 LOG.error("Updation of vpninterface {} failed", infName, ex);
1190             }
1191         }
1192     }
1193
1194     public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1195                                     List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1196
1197         IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1198
1199         // Update VPN Instance node
1200         updateVpnInstanceNode(vpnId, rdList, irtList, ertList, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1201
1202         // Update local vpn-subnet DS
1203         updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1204
1205         if (routerId != null) {
1206             Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1207             if (existingVpn != null) {
1208                 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1209                 // if before reboot, router was already associated to VPN, should not proceed associating router to
1210                 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1211                 // preserved upon reboot.
1212                 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1213                 // RouterInterfacesMap via #createVPNInterface call.
1214                 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1215                         + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1216                 return;
1217             }
1218             associateRouterToInternalVpn(vpnId, routerId);
1219         }
1220     }
1221
1222     /**
1223      * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1224      * specified Neutron Networks and Routers.
1225      *
1226      * @param vpnId Uuid of the VPN tp be created
1227      * @param name Representative name of the new VPN
1228      * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1229      * @param rdList Route-distinguisher for the VPN
1230      * @param irtList A list of Import Route Targets
1231      * @param ertList A list of Export Route Targets
1232      * @param routerIdsList ist of neutron router Id to associate with created VPN
1233      * @param networkList UUID of the neutron network the VPN may be associated to
1234      * @param type Type of the VPN Instance
1235      * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1236      * @throws Exception if association of L3VPN failed
1237      */
1238     public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1239                     List<String> ertList,  @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1240                     VpnInstance.Type type, long l3vni) throws Exception {
1241
1242         IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1243
1244         if (routerIdsList != null && !routerIdsList.isEmpty()) {
1245             for (Uuid routerId : routerIdsList) {
1246                 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1247                 ipVersChoices = ipVersChoices.addVersion(vers);
1248             }
1249         }
1250         updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1251
1252         // Please note that router and networks will be filled into VPNMaps
1253         // by subsequent calls here to associateRouterToVpn and
1254         // associateNetworksToVpn
1255         updateVpnMaps(vpnId, name, null, tenantId, null);
1256         LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1257                         + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1258                 networkList);
1259
1260         if (routerIdsList != null && !routerIdsList.isEmpty()) {
1261             for (Uuid routerId : routerIdsList) {
1262                 associateRouterToVpn(vpnId, routerId);
1263             }
1264         }
1265         if (networkList != null) {
1266             List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1267             if (!failStrings.isEmpty()) {
1268                 LOG.error("VPN {} association to networks failed for networks: {}. ",
1269                         vpnId.getValue(), failStrings);
1270                 throw new Exception(failStrings.toString());
1271             }
1272         }
1273     }
1274
1275     /**
1276      * It handles the invocations to the createVPN RPC method.
1277      */
1278     @Override
1279     // TODO Clean up the exception handling
1280     @SuppressWarnings("checkstyle:IllegalCatch")
1281     public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1282
1283         CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1284         SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1285         List<RpcError> errorList = new ArrayList<>();
1286         int failurecount = 0;
1287         int warningcount = 0;
1288
1289         List<L3vpn> vpns = input.getL3vpn();
1290         if (vpns == null) {
1291             vpns = Collections.emptyList();
1292         }
1293         for (L3vpn vpn : vpns) {
1294             if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1295                 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1296                         formatAndLog(LOG::warn,
1297                                 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1298                                 vpn.getId().getValue())));
1299                 warningcount++;
1300                 continue;
1301             }
1302             if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1303                 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1304                         formatAndLog(LOG::warn,
1305                                 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1306                                 vpn.getId().getValue())));
1307                 warningcount++;
1308                 continue;
1309             }
1310             VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1311             long l3vni = 0;
1312             if (vpn.getL3vni() != null) {
1313                 l3vni = vpn.getL3vni().toJava();
1314             }
1315
1316             List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1317             if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1318                 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1319                         formatAndLog(LOG::warn,
1320                                 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1321                                         + "is already configured",
1322                                 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1323                 warningcount++;
1324                 continue;
1325             }
1326             Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1327             if (operationalVpn.isPresent()) {
1328                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1329                         formatAndLog(LOG::error,
1330                                 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1331                                         + "is still available. Please retry creation of a new vpn with the same RD"
1332                                         + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1333                                 vpn.getRouteDistinguisher().get(0))));
1334                 warningcount++;
1335                 continue;
1336             }
1337             if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1338                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1339                         routerIdsList = vpn.getRouterIds();
1340                 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1341                         routerId : routerIdsList) {
1342                     if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1343                         errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1344                                 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1345                                         + "{}", vpn.getId(), routerId.getRouterId())));
1346                         warningcount++;
1347                         continue;
1348                     }
1349                     Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1350                     if (vpnId != null) {
1351                         errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1352                                 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1353                                                 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1354                                         vpnId.getValue())));
1355                         warningcount++;
1356                         continue;
1357                     }
1358                 }
1359             }
1360             if (vpn.getNetworkIds() != null) {
1361                 int initialWarningCount = warningcount;
1362                 for (Uuid nw : vpn.getNetworkIds()) {
1363                     Network network = neutronvpnUtils.getNeutronNetwork(nw);
1364                     Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1365                     if (network == null) {
1366                         errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1367                                 formatAndLog(LOG::warn,
1368                                         "Creation of L3VPN failed for VPN {} due to network not found {}",
1369                                         vpn.getId().getValue(), nw.getValue())));
1370                         warningcount++;
1371                     } else if (vpnId != null) {
1372                         errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1373                                 formatAndLog(LOG::warn,
1374                                         "Creation of L3VPN failed for VPN {} due to network {} already associated"
1375                                                 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1376                                         vpnId.getValue())));
1377                         warningcount++;
1378                     }
1379                 }
1380                 if (warningcount != initialWarningCount) {
1381                     continue;
1382                 }
1383             }
1384             List<Uuid> rtrIdsList = new ArrayList<>();
1385             if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1386                 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1387                         rtrId : vpn.getRouterIds()) {
1388                     rtrIdsList.add(rtrId.getRouterId());
1389                 }
1390             }
1391             try {
1392                 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1393                                 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1394                         vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1395                         vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1396
1397                 List<String> rdList = vpn.getRouteDistinguisher() != null
1398                         ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1399                 List<String> importRdList = vpn.getImportRT() != null
1400                         ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1401                 List<String> exportRdList = vpn.getExportRT() != null
1402                         ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1403
1404                 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1405                         importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), vpnInstanceType, l3vni);
1406             } catch (Exception ex) {
1407                 LOG.error("VPN Creation exception :", ex);
1408                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1409                         formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1410                         ex.getMessage()));
1411                 failurecount++;
1412             }
1413         }
1414         // if at least one succeeds; result is success
1415         // if none succeeds; result is failure
1416         if (failurecount + warningcount == vpns.size()) {
1417             result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1418         } else {
1419             List<String> errorResponseList = new ArrayList<>();
1420             if (!errorList.isEmpty()) {
1421                 for (RpcError rpcError : errorList) {
1422                     errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1423                             + ", ErrorMessage: " + rpcError.getMessage());
1424                 }
1425             } else {
1426                 errorResponseList.add("Operation successful with no errors");
1427             }
1428             opBuilder.setResponse(errorResponseList);
1429             result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1430         }
1431         return result;
1432     }
1433
1434     /**
1435      * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1436      */
1437     @Override
1438     public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1439
1440         GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1441         SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1442         Uuid inputVpnId = input.getId();
1443         List<VpnInstance> vpns = new ArrayList<>();
1444         List<L3vpnInstances> l3vpnList = new ArrayList<>();
1445
1446         try {
1447             if (inputVpnId == null) {
1448                 // get all vpns
1449                 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1450                         .build();
1451                 Optional<VpnInstances> optionalVpns =
1452                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1453                                 vpnsIdentifier);
1454                 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1455                     for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1456                         // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1457                         // from getL3VPN output
1458                         if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1459                             vpns.add(vpn);
1460                         }
1461                         if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1462                             vpns.add(vpn);
1463                         }
1464                     }
1465                 } else {
1466                     // No VPN present
1467                     opBuilder.setL3vpnInstances(l3vpnList);
1468                     result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1469                     return result;
1470                 }
1471             } else {
1472                 String name = inputVpnId.getValue();
1473                 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1474                         .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1475                 // read VpnInstance Info
1476                 Optional<VpnInstance> optionalVpn =
1477                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1478                                 vpnIdentifier);
1479                 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1480                 // getL3VPN output
1481                 if (optionalVpn.isPresent() && (optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1482                         || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
1483                     vpns.add(optionalVpn.get());
1484                 } else {
1485                     result.set(
1486                             RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1487                                     formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1488                                             name)).build());
1489                 }
1490             }
1491             for (VpnInstance vpnInstance : vpns) {
1492                 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1493                 // create VpnMaps id
1494                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1495                 List<String> rd = Collections.EMPTY_LIST;
1496                 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1497                     rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1498                 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1499                     rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1500                 }
1501                 List<String> ertList = new ArrayList<>();
1502                 List<String> irtList = new ArrayList<>();
1503
1504                 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1505                         || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1506                     List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1507                     if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1508                         vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1509                     } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1510                         vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1511                     }
1512                     if (!vpnTargetList.isEmpty()) {
1513                         for (VpnTarget vpnTarget : vpnTargetList) {
1514                             if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1515                                 ertList.add(vpnTarget.getVrfRTValue());
1516                             }
1517                             if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1518                                 irtList.add(vpnTarget.getVrfRTValue());
1519                             }
1520                             if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1521                                 ertList.add(vpnTarget.getVrfRTValue());
1522                                 irtList.add(vpnTarget.getVrfRTValue());
1523                             }
1524                         }
1525                     }
1526                 }
1527
1528                 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1529
1530                 if (vpnInstance.getL3vni() != null) {
1531                     l3vpn.setL3vni(vpnInstance.getL3vni());
1532                 }
1533                 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1534                         .class, new VpnMapKey(vpnId)).build();
1535                 Optional<VpnMap> optionalVpnMap =
1536                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1537                                 vpnMapIdentifier);
1538                 if (optionalVpnMap.isPresent()) {
1539                     VpnMap vpnMap = optionalVpnMap.get();
1540                     List<Uuid> rtrIds = new ArrayList<>();
1541                     if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1542                         for (RouterIds rtrId : vpnMap.getRouterIds()) {
1543                             rtrIds.add(rtrId.getRouterId());
1544                         }
1545                     }
1546                     l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1547                             .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1548                             .setName(vpnMap.getName());
1549
1550                 }
1551                 l3vpnList.add(l3vpn.build());
1552             }
1553
1554             opBuilder.setL3vpnInstances(l3vpnList);
1555             result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1556
1557         } catch (ReadFailedException ex) {
1558             result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1559                     formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1560         }
1561         return result;
1562     }
1563
1564     /**
1565      * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1566      */
1567     @Override
1568     public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1569
1570         DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1571         SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1572         List<RpcError> errorList = new ArrayList<>();
1573
1574         int failurecount = 0;
1575         int warningcount = 0;
1576         List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1577         for (Uuid vpn : vpns) {
1578             try {
1579                 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1580                 InstanceIdentifier<VpnInstance> vpnIdentifier =
1581                         InstanceIdentifier.builder(VpnInstances.class)
1582                             .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1583                 Optional<VpnInstance> optionalVpn =
1584                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1585                                 vpnIdentifier);
1586                 if (optionalVpn.isPresent()) {
1587                     removeVpn(vpn);
1588                 } else {
1589                     errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1590                             formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1591                     warningcount++;
1592                 }
1593             } catch (ReadFailedException ex) {
1594                 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1595                         formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1596                         ex.getMessage()));
1597                 failurecount++;
1598             }
1599         }
1600         // if at least one succeeds; result is success
1601         // if none succeeds; result is failure
1602         if (failurecount + warningcount == vpns.size()) {
1603             result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1604         } else {
1605             List<String> errorResponseList = new ArrayList<>();
1606             if (!errorList.isEmpty()) {
1607                 for (RpcError rpcError : errorList) {
1608                     errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1609                             + ", ErrorMessage: " + rpcError.getMessage());
1610                 }
1611             } else {
1612                 errorResponseList.add("Operation successful with no errors");
1613             }
1614             opBuilder.setResponse(errorResponseList);
1615             result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1616         }
1617         return result;
1618     }
1619
1620     public void createVpnInstanceForSubnet(Uuid subnetId) {
1621         LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1622         createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1623     }
1624
1625     public void removeVpnInstanceForSubnet(Uuid subnetId) {
1626         LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1627         removeVpn(subnetId);
1628     }
1629
1630     protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1631         LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1632                   vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1633         Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1634         if (sn == null) {
1635             LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1636                 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1637             return;
1638         }
1639         if (vpnId != null) {
1640             VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1641             if (vpnMap == null) {
1642                 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1643                      + " cannot add subnet {} to VPN", vpnId.getValue(),
1644                     subnet.getValue());
1645                 return;
1646             }
1647             final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1648             LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1649             if (isVpnOfTypeL2(vpnInstance)) {
1650                 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1651                         NeutronEvpnUtils.Operation.ADD);
1652             }
1653         }
1654         if (internetVpnId != null) {
1655             VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1656             if (vpnMap == null) {
1657                 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1658                     + "subnet {} to VPN", internetVpnId.getValue(),
1659                     subnet.getValue());
1660                 return;
1661             }
1662         }
1663         final Uuid internetId = internetVpnId;
1664         // Check if there are ports on this subnet and add corresponding vpn-interfaces
1665         List<Uuid> portList = sn.getPortList();
1666         if (portList != null) {
1667             for (final Uuid portId : portList) {
1668                 String vpnInfName = portId.getValue();
1669                 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1670                 Port port = neutronvpnUtils.getNeutronPort(portId);
1671                 if (port == null) {
1672                     LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1673                         + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1674                     continue;
1675                 }
1676                 final Boolean isRouterInterface = port.getDeviceOwner()
1677                         .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1678                 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1679                     ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1680                         wrtConfigTxn -> {
1681                             Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1682                                     vpnIface);
1683                             if (vpnIface == null) {
1684                                 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1685                                 Set<Uuid> listVpn = new HashSet<>();
1686                                 if (vpnId != null) {
1687                                     listVpn.add(vpnId);
1688                                 }
1689                                 if (internetId != null) {
1690                                     listVpn.add(internetId);
1691                                 }
1692                                 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1693                                         isRouterInterface, wrtConfigTxn);
1694                                 if (sn.getRouterId() != null) {
1695                                     addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1696                                 }
1697                             } else {
1698                                 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1699                                 if (vpnId != null) {
1700                                     updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1701                                 }
1702                                 if (internetId != null) {
1703                                     updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1704                                 }
1705                             }
1706                         });
1707                     ListenableFutures.addErrorLogging(future, LOG,
1708                             "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1709                                     + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1710                     return Collections.singletonList(future);
1711                 });
1712             }
1713         }
1714     }
1715
1716     protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1717         Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1718                 "removeSubnetFromVpn: at least one VPN must be not null");
1719         LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1720                   vpnId, internetVpnId);
1721         Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1722         if (sn == null) {
1723             LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1724             return;
1725         }
1726         VpnMap vpnMap = null;
1727         VpnInstance vpnInstance = null;
1728         if (vpnId != null) {
1729             vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1730             if (vpnMap == null) {
1731                 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1732                         vpnId.getValue(), subnet.getValue());
1733                 return;
1734             }
1735             vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1736         }
1737         if (internetVpnId == null) {
1738             internetVpnId = sn.getInternetVpnId();
1739         }
1740         if (internetVpnId != null) {
1741             vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1742             if (vpnMap == null) {
1743                 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1744                         + " from Internet VPN",
1745                         internetVpnId.getValue(), subnet.getValue());
1746                 return;
1747             }
1748         }
1749         if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1750             neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1751                     NeutronEvpnUtils.Operation.DELETE);
1752         }
1753         boolean subnetVpnAssociation = false;
1754         if (vpnId != null && sn.getVpnId() != null
1755             && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1756             subnetVpnAssociation = true;
1757         } else if (internetVpnId != null && sn.getInternetVpnId() != null
1758             && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1759             subnetVpnAssociation = true;
1760         }
1761         if (subnetVpnAssociation == false) {
1762             LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1763                       vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1764             return;
1765         }
1766         // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1767         List<Uuid> portList = sn.getPortList();
1768         final Uuid internetId = internetVpnId;
1769         if (portList != null) {
1770             for (final Uuid portId : portList) {
1771                 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1772                 final Port port = neutronvpnUtils.getNeutronPort(portId);
1773                 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1774                     List<ListenableFuture<Void>> futures = new ArrayList<>();
1775                     ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1776                         CONFIGURATION, tx -> {
1777                             if (port != null) {
1778                                 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1779                             } else {
1780                                 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1781                                                 + " port is absent in Neutron config DS", portId.getValue(),
1782                                         subnet.getValue());
1783                             }
1784                         });
1785                     ListenableFutures.addErrorLogging(future, LOG,
1786                             "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1787                                     + " belonging to subnet {} and vpnId {}",
1788                             portId.getValue(), subnet.getValue(), vpnId.getValue());
1789                     futures.add(future);
1790                     return futures;
1791                 });
1792             }
1793         }
1794         //update subnet-vpn association
1795         removeFromSubnetNode(subnet, null, null, vpnId, null);
1796     }
1797
1798     protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1799         LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1800              isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1801              vpn.getValue());
1802         Uuid internalVpnId = sm.getVpnId();
1803         if (internalVpnId == null) {
1804             LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1805                       sm.getId().getValue());
1806             return;
1807         }
1808         if (isBeingAssociated) {
1809             updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1810         } else {
1811             updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1812         }
1813
1814         jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1815             txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1816                 if (isBeingAssociated) {
1817                     updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1818                             sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1819                 } else {
1820                     removeInternetVpnFromVpnInterface(vpn,
1821                             neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1822                 }
1823                 }
1824             )));
1825
1826         // Check for ports on this subnet and update association of
1827         // corresponding vpn-interfaces to internet vpn
1828         List<Uuid> portList = sm.getPortList();
1829         if (portList != null) {
1830             for (Uuid port : portList) {
1831                 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1832                         port.getValue(), isBeingAssociated);
1833                 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1834                     () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1835                         tx -> {
1836                             if (isBeingAssociated) {
1837                                 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1838                                         true, false, tx, true);
1839                             } else {
1840                                 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1841                             }
1842                         })));
1843             }
1844         }
1845     }
1846
1847     @Nullable
1848     private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1849         LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1850                 oldVpnId.getValue(), newVpnId.getValue());
1851         Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1852         Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1853         boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1854         Uuid vpnExtUuid = netIsExternal ? null
1855                 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1856         Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1857         if (sn == null) {
1858             LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1859             return sn;
1860         }
1861         /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1862          * associated with internet BGP-VPN.
1863          */
1864         if (vpnExtUuid != null) {
1865             /* Update V6 Internet default route match with new VPN metadata.
1866              * isBeingAssociated = true means oldVpnId is same as routerId
1867              * isBeingAssociated = false means newVpnId is same as routerId
1868             */
1869             if (isBeingAssociated) {
1870                 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1871             } else {
1872                 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1873             }
1874         }
1875         //Update Router Interface first synchronously.
1876         //CAUTION:  Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1877         ListenableFuture<Void> future =
1878                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1879                     tx -> updateVpnInterface(newVpnId, oldVpnId,
1880                         neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1881                         isBeingAssociated, true, tx, false));
1882         Futures.addCallback(future, new FutureCallback<Void>() {
1883             @Override
1884             public void onSuccess(Void result) {
1885                 // Check for ports on this subnet and update association of
1886                 // corresponding vpn-interfaces to external vpn
1887                 List<Uuid> portList = sn.getPortList();
1888                 if (portList != null) {
1889                     for (Uuid port : portList) {
1890                         LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1891                                 port.getValue(), isBeingAssociated);
1892                         jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1893                                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1894                                     tx -> updateVpnInterface(newVpnId, oldVpnId,
1895                                             neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1896                                             tx, false))));
1897                     }
1898                 }
1899             }
1900
1901             @Override
1902             public void onFailure(Throwable throwable) {
1903                 LOG.error(
1904                         "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1905                                 + "returning",
1906                         sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1907             }
1908         }, MoreExecutors.directExecutor());
1909
1910         return sn;
1911     }
1912
1913     public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1914         return InstanceIdentifier.builder(RouterInterfacesMap.class)
1915                 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1916     }
1917
1918     protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1919         final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1920         final ReentrantLock lock = lockForUuid(routerId);
1921         lock.lock();
1922         try {
1923             Optional<RouterInterfaces> optRouterInterfaces =
1924                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1925                         routerInterfacesId);
1926             Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1927                     .setInterfaceId(interfaceName).build();
1928             if (optRouterInterfaces.isPresent()) {
1929                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1930                     routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1931             } else {
1932                 // TODO Shouldn't we be doing something with builder and interfaces?
1933                 //          RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1934                 //          List<Interfaces> interfaces = new ArrayList<>();
1935                 //          interfaces.add(routerInterface);
1936
1937                 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1938                     routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1939             }
1940         } catch (ReadFailedException | TransactionCommitFailedException e) {
1941             LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1942         } finally {
1943             lock.unlock();
1944         }
1945     }
1946
1947     protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1948         final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1949         final ReentrantLock lock = lockForUuid(routerId);
1950         lock.lock();
1951         try {
1952             Optional<RouterInterfaces> optRouterInterfaces =
1953                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1954                         routerInterfacesId);
1955             Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1956                     .setInterfaceId(interfaceName).build();
1957             if (optRouterInterfaces.isPresent()) {
1958                 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1959                 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
1960                 if (interfaces != null && interfaces.remove(routerInterface)) {
1961                     if (interfaces.isEmpty()) {
1962                         SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1963                             routerInterfacesId);
1964                     } else {
1965                         SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1966                             routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1967                     }
1968                 }
1969             }
1970         } catch (ReadFailedException | TransactionCommitFailedException e) {
1971             LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1972         } finally {
1973             lock.unlock();
1974         }
1975     }
1976
1977     /**
1978      * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1979      * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1980      * route will be ignored.
1981      *
1982      * @param vpnName the VPN identifier
1983      * @param interVpnLinkRoutes The list of static routes
1984      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1985      */
1986     public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1987                                   HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1988         for (Routes route : interVpnLinkRoutes) {
1989             String nexthop = route.getNexthop().stringValue();
1990             String destination = route.getDestination().stringValue();
1991             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1992             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1993                 AddStaticRouteInput rpcInput =
1994                         new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1995                                 .setVpnInstanceName(vpnName.getValue())
1996                                 .build();
1997                 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1998                 RpcResult<AddStaticRouteOutput> rpcResult;
1999                 try {
2000                     rpcResult = labelOuputFtr.get();
2001                     if (rpcResult.isSuccessful()) {
2002                         LOG.debug("Label generated for destination {} is: {}",
2003                                 destination, rpcResult.getResult().getLabel());
2004                     } else {
2005                         LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
2006                                 destination, nexthop, rpcResult.getErrors());
2007                     }
2008                 } catch (InterruptedException | ExecutionException e) {
2009                     LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
2010                             + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
2011                 }
2012             } else {
2013                 // Any other case is a fault.
2014                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2015                         route.getDestination().stringValue(), nexthop);
2016                 continue;
2017             }
2018         }
2019     }
2020
2021     /**
2022      * Removes the corresponding static routes from the specified VPN. These static routes point to an
2023      * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2024      *
2025      * @param vpnName the VPN identifier
2026      * @param interVpnLinkRoutes The list of static routes
2027      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2028      */
2029     public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2030                                      HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2031         for (Routes route : interVpnLinkRoutes) {
2032             String nexthop = route.getNexthop().stringValue();
2033             String destination = route.getDestination().stringValue();
2034             InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2035             if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2036                 RemoveStaticRouteInput rpcInput =
2037                         new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2038                                 .setVpnInstanceName(vpnName.getValue())
2039                                 .build();
2040
2041                 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2042                         vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2043             } else {
2044                 // Any other case is a fault.
2045                 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2046                         route.getDestination().stringValue(), nexthop);
2047                 continue;
2048             }
2049         }
2050     }
2051
2052     /*
2053      * Returns true if the specified nexthop is the other endpoint in an
2054      * InterVpnLink, regarding one of the VPN's point of view.
2055      */
2056     private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2057             InterVpnLink interVpnLink) {
2058         return
2059                 interVpnLink != null
2060                         && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2061                         && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2062                         || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2063                         && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2064     }
2065
2066     @NonNull
2067     protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2068         List<Adjacency> adjList = new ArrayList<>();
2069         Map<String, List<String>> adjMap = new HashMap<>();
2070         for (Routes route : routeList) {
2071             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2072                 LOG.error("Incorrect input received for extra route. {}", route);
2073             } else {
2074                 String nextHop = route.getNexthop().stringValue();
2075                 String destination = route.getDestination().stringValue();
2076                 if (!nextHop.equals(fixedIp)) {
2077                     LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2078                     continue;
2079                 }
2080                 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2081                         nextHop);
2082                 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2083                 if (!hops.contains(nextHop)) {
2084                     hops.add(nextHop);
2085                 }
2086             }
2087         }
2088
2089         for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2090             final String destination = entry.getKey();
2091             final List<String> ipList = entry.getValue();
2092             Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2093                     .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2094                     .withKey(new AdjacencyKey(destination)).build();
2095             adjList.add(erAdj);
2096         }
2097         return adjList;
2098     }
2099
2100     protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2101         checkAlarmExtraRoutes(vpnId, routeList);
2102
2103         for (Routes route : routeList) {
2104             if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2105                 LOG.error("Incorrect input received for extra route. {}", route);
2106             } else {
2107                 String nextHop = route.getNexthop().stringValue();
2108                 String destination = route.getDestination().stringValue();
2109                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2110                         nextHop);
2111                 if (infName != null) {
2112                     LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2113                         destination, vpnId.getValue(), nextHop, infName);
2114                     boolean isLockAcquired = false;
2115                     try {
2116                         InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2117                                 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2118                         InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2119                             .child(Adjacency.class, new AdjacencyKey(destination));
2120                         Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2121                                 LogicalDatastoreType.CONFIGURATION, path);
2122                         if (existingAdjacency.isPresent()
2123                                 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2124                             LOG.error("The route with destination {} nextHop {} is already present as"
2125                                             + " a primary adjacency for interface {}. Skipping adjacency addition.",
2126                                     destination, nextHop, infName);
2127                             continue;
2128                         }
2129                         Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2130                             .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2131                             .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2132
2133                         try (AcquireResult lock = tryInterfaceLock(infName)) {
2134                             if (!lock.wasAcquired()) {
2135                                 // FIXME: why do we even bother with locking if we do not honor it?!
2136                                 logTryLockFailure(infName);
2137                             }
2138
2139                             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2140                                 path, erAdj);
2141                         }
2142                     } catch (TransactionCommitFailedException e) {
2143                         LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2144                             destination, nextHop, e);
2145                     } catch (ReadFailedException e) {
2146                         LOG.error("Exception on reading data-store ", e);
2147                     }
2148                 } else {
2149                     LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2150                         + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2151                 }
2152             }
2153         }
2154     }
2155
2156     /**
2157      * This method setup or down an alarm about extra route fault.
2158      * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2159      * available RDs, then an alarm and an error is generated.<br>
2160      * <b>Be careful</b> the routeList could be changed.
2161      *
2162      * @param vpnId the vpnId of vpn to control.
2163      * @param routeList the list of router to check, it could be modified.
2164      */
2165     private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2166         if (!neutronvpnAlarm.isAlarmEnabled()) {
2167             LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2168             return;
2169         }
2170         VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2171         if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2172             LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2173                     vpnId, routeList);
2174             return;
2175         }
2176         String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2177         if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2178             LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2179                     vpnId);
2180             return;
2181         }
2182         for (Routes route : routeList) {
2183             // count  the number of nexthops for each same route.getDestingation().getValue()
2184             String destination = route.getDestination().stringValue();
2185             String nextHop = route.getNexthop().stringValue();
2186             List<String> nextHopList = new ArrayList<>();
2187             nextHopList.add(nextHop);
2188             int nbNextHops = 1;
2189             for (Routes routeTmp : routeList) {
2190                 String routeDest = routeTmp.getDestination().stringValue();
2191                 if (!destination.equals(routeDest)) {
2192                     continue;
2193                 }
2194                 String routeNextH = routeTmp.getNexthop().stringValue();
2195                 if (nextHop.equals(routeNextH)) {
2196                     continue;
2197                 }
2198                 nbNextHops++;
2199                 nextHopList.add(routeTmp.getNexthop().stringValue());
2200             }
2201             final List<String> rdList = new ArrayList<>();
2202             if (vpnInstance.getIpv4Family() != null
2203                     && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2204                 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2205                     if (rd != null) {
2206                         rdList.add(rd);
2207                     }
2208                 });
2209             }
2210             if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2211                 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2212                     if (rd != null && !rdList.contains(rd)) {
2213                         rdList.add(rd);
2214                     }
2215                 });
2216             }
2217             // 1. VPN Instance Name
2218             String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2219
2220             // 2. Router ID
2221             List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2222             Uuid routerUuid = routerUuidList.get(0);
2223             StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2224             detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2225
2226             // 3. List of RDs associated with the VPN
2227             detailsAlarm.append(" List of RDs associated with the VPN: ");
2228             for (String s : rdList) {
2229                 detailsAlarm.append(s);
2230                 detailsAlarm.append(", ");
2231             }
2232
2233             // 4. Prefix in question
2234             detailsAlarm.append(" for prefix: ");
2235             detailsAlarm.append(route.getDestination().stringValue());
2236
2237             // 5. List of NHs for the prefix
2238             detailsAlarm.append(" for nextHops: ");
2239             for (String s : nextHopList) {
2240                 detailsAlarm.append(s);
2241                 detailsAlarm.append(", ");
2242             }
2243
2244             if (rdList.size() < nbNextHops) {
2245                 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2246             } else {
2247                 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2248             }
2249         }
2250     }
2251
2252     // TODO Clean up the exception handling
2253     @SuppressWarnings("checkstyle:IllegalCatch")
2254     protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2255         for (Routes route : routeList) {
2256             if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2257                 String nextHop = route.getNexthop().stringValue();
2258                 String destination = route.getDestination().stringValue();
2259                 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2260                         nextHop);
2261                 if (infName == null) {
2262                     LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2263                             + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2264                     // Proceed to remove the next extra-route
2265                     continue;
2266                 }
2267                 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2268                         destination, vpnId.getValue(), nextHop, infName);
2269
2270                 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2271                         InstanceIdentifier.builder(VpnInterfaces.class)
2272                                 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2273                                 .augmentation(Adjacencies.class)
2274                                 .child(Adjacency.class, new AdjacencyKey(destination))
2275                                 .build();
2276
2277                 try {
2278                     // Looking for existing prefix in MDSAL database
2279                     Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2280                             LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2281                     boolean updateNextHops = false;
2282                     List<String> nextHopList = new ArrayList<>();
2283                     if (adjacency.isPresent()) {
2284                         List<String> nhListRead = adjacency.get().getNextHopIpList();
2285                         if (nhListRead.size() > 1) { // ECMP case
2286                             for (String nextHopRead : nhListRead) {
2287                                 if (nextHopRead.equals(nextHop)) {
2288                                     updateNextHops = true;
2289                                 } else {
2290                                     nextHopList.add(nextHopRead);
2291                                 }
2292                             }
2293                         }
2294                     }
2295
2296                     try (AcquireResult lock = tryInterfaceLock(infName)) {
2297                         if (!lock.wasAcquired()) {
2298                             // FIXME: why do we even bother with locking if we do not honor it?!
2299                             logTryLockFailure(infName);
2300                         }
2301
2302                         if (updateNextHops) {
2303                             // An update must be done, not including the current next hop
2304                             InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2305                                 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2306                             Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2307                                     .setNextHopIpList(nextHopList)
2308                                     .withKey(new AdjacencyKey(destination))
2309                                     .build();
2310                             Adjacencies erAdjs =
2311                                     new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2312                             VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2313                                     .addAugmentation(Adjacencies.class, erAdjs).build();
2314                             SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2315                                 vpnIfIdentifier, vpnIf);
2316                         } else {
2317                             // Remove the whole route
2318                             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2319                                 adjacencyIdentifier);
2320                             LOG.trace("extra route {} deleted successfully", route);
2321                         }
2322                     }
2323                 } catch (TransactionCommitFailedException | ReadFailedException e) {
2324                     LOG.error("exception in deleting extra route with destination {} for interface {}",
2325                             destination, infName, e);
2326                 }
2327             } else {
2328                 LOG.error("Incorrect input received for extra route: {}", route);
2329             }
2330         }
2331     }
2332
2333     public void removeVpn(Uuid vpnId) {
2334         // read VPNMaps
2335         VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2336         List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2337         List<Uuid> routerUuidList = new ArrayList<>();
2338         // dissociate router
2339         if (routerIdsList != null && !routerIdsList.isEmpty()) {
2340             for (RouterIds router : routerIdsList) {
2341                 Uuid routerId = router.getRouterId();
2342                 routerUuidList.add(routerId);
2343                 dissociateRouterFromVpn(vpnId, routerId);
2344             }
2345         }
2346         if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2347             dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2348         }
2349         // remove entire vpnMaps node
2350         deleteVpnMapsNode(vpnId);
2351
2352         // remove vpn-instance
2353         deleteVpnInstance(vpnId);
2354         LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2355     }
2356
2357     private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2358         return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2359     }
2360
2361     // TODO Clean up the exception handling
2362     @SuppressWarnings("checkstyle:IllegalCatch")
2363     protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2364         updateVpnMaps(vpnId, null, routerId, null, null);
2365         LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2366         List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2367         IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2368         for (Subnetmap sn : subMapList) {
2369             IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2370             if (!ipVersion.isIpVersionChosen(ipVers)) {
2371                 ipVersion = ipVersion.addVersion(ipVers);
2372             }
2373         }
2374         if (ipVersion != IpVersionChoice.UNDEFINED) {
2375             LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2376                     ipVersion, vpnId);
2377             neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2378         }
2379         for (Subnetmap sn : subMapList) {
2380             updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2381         }
2382     }
2383
2384     protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2385         List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2386         Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2387         LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2388         for (Uuid subnet : routerSubnets) {
2389             IpVersionChoice version = NeutronvpnUtils
2390                    .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2391             if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2392                 addSubnetToVpn(vpnId, subnet, null);
2393             } else {
2394                 addSubnetToVpn(vpnId, subnet, internetVpnId);
2395             }
2396         }
2397     }
2398
2399     // TODO Clean up the exception handling
2400     @SuppressWarnings("checkstyle:IllegalCatch")
2401     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2402
2403         clearFromVpnMaps(vpnId, routerId, null);
2404         List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2405         IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2406         for (Subnetmap sn : subMapList) {
2407             IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2408             if (ipVersion.isIpVersionChosen(ipVers)) {
2409                 ipVersion = ipVersion.addVersion(ipVers);
2410             }
2411             LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2412                     routerId.getValue());
2413             updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2414         }
2415         if (ipVersion != IpVersionChoice.UNDEFINED) {
2416             LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2417                     ipVersion, vpnId);
2418             neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2419                     false);
2420         }
2421     }
2422
2423     /**
2424      * Parses and associates networks list with given VPN.
2425      *
2426      * @param vpnId Uuid of given VPN.
2427      * @param networkList List list of network Ids (Uuid), which will be associated.
2428      * @return list of formatted strings with detailed error messages.
2429      */
2430     @NonNull
2431     protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2432         List<String> failedNwList = new ArrayList<>();
2433         HashSet<Uuid> passedNwList = new HashSet<>();
2434         boolean isExternalNetwork = false;
2435         if (networkList.isEmpty()) {
2436             LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2437             failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2438                     vpnId.getValue()));
2439             return failedNwList;
2440         }
2441         VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2442         if (vpnInstance == null) {
2443             LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2444             failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2445                                            + "in ConfigDS", vpnId.getValue()));
2446             return failedNwList;
2447         }
2448         try {
2449             if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2450                 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2451                           vpnId.getValue());
2452                 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2453                                                + "associated with", vpnId.getValue()));
2454                 return failedNwList;
2455             }
2456             Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2457             for (Uuid nw : networkList) {
2458                 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2459                 if (network == null) {
2460                     LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2461                     failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2462                                                    nw.getValue()));
2463                     continue;
2464                 }
2465                 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2466                 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2467                     LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2468                               nw.getValue(), vpnId.getValue());
2469                     failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2470                                                    nw.getValue(), vpnId.getValue()));
2471                     continue;
2472                 }
2473                 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2474                 if (networkVpnId != null) {
2475                     LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2476                               nw.getValue(), networkVpnId.getValue());
2477                     failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2478                                                    + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2479                     continue;
2480                 }
2481                 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2482                     LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2483                             nw.getValue(), vpnId.getValue());
2484                     failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2485                             nw.getValue(), vpnId.getValue()));
2486                     continue;
2487                 }
2488                 if (NeutronvpnUtils.getIsExternal(network)) {
2489                     isExternalNetwork = true;
2490                 }
2491                 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2492                 if (subnetmapList == null || subnetmapList.isEmpty()) {
2493                     passedNwList.add(nw);
2494                     continue;
2495                 }
2496                 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2497                     continue;
2498                 }
2499                 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2500                 for (Subnetmap subnetmap : subnetmapList) {
2501                     IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2502                     if (!ipVersion.isIpVersionChosen(ipVers)) {
2503                         ipVersion = ipVersion.addVersion(ipVers);
2504                     }
2505                 }
2506                 if (ipVersion != IpVersionChoice.UNDEFINED) {
2507                     LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2508                             + " for VPN {} ", ipVersion, vpnId);
2509                     neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2510                 }
2511                 for (Subnetmap subnetmap : subnetmapList) {
2512                     Uuid subnetId = subnetmap.getId();
2513                     Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2514                     if (subnetVpnId != null) {
2515                         LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2516                                 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2517                         failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2518                                 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2519                         continue;
2520                     }
2521                     if (!NeutronvpnUtils.getIsExternal(network)) {
2522                         LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2523                                 vpnId.getValue());
2524                         addSubnetToVpn(vpnId, subnetId, null);
2525                         vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2526                                 vpnId.getValue());
2527                         passedNwList.add(nw);
2528                     }
2529                 }
2530                 passedNwList.add(nw);
2531             }
2532         } catch (ReadFailedException e) {
2533             LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2534                     networkList, e);
2535             failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2536                     networkList, e));
2537         }
2538         //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2539         if (!isExternalNetwork) {
2540             updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2541         }
2542         LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2543         return failedNwList;
2544     }
2545
2546     private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2547         if (!addExternalNetworkToVpn(extNet, vpnId)) {
2548             return false;
2549         }
2550         VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2551         if (vpnOpDataEntry == null) {
2552             LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2553             return false;
2554         }
2555         if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2556             LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2557             neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2558         }
2559         //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2560         List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2561         updateVpnMaps(vpnId, null, null, null, extNwList);
2562         IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2563         for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2564             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2565             if (sm == null) {
2566                 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2567                 continue;
2568             }
2569             IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2570             if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2571                 continue;
2572             }
2573             if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2574                 updateVpnInternetForSubnet(sm, vpnId, true);
2575             }
2576             if (!ipVersion.isIpVersionChosen(ipVers)) {
2577                 ipVersion = ipVersion.addVersion(ipVers);
2578             }
2579         }
2580         if (ipVersion != IpVersionChoice.UNDEFINED) {
2581             neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2582             LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2583             neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2584         }
2585         return true;
2586     }
2587
2588     /**
2589      * Parses and disassociates networks list from given VPN.
2590      *
2591      * @param vpnId Uuid of given VPN.
2592      * @param networkList List list of network Ids (Uuid), which will be disassociated.
2593      * @return list of formatted strings with detailed error messages.
2594      */
2595     @NonNull
2596     protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2597         List<String> failedNwList = new ArrayList<>();
2598         HashSet<Uuid> passedNwList = new HashSet<>();
2599         if (networkList.isEmpty()) {
2600             LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2601             failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2602                              vpnId.getValue()));
2603             return failedNwList;
2604         }
2605         for (Uuid nw : networkList) {
2606             List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2607             if (networkSubnets == null) {
2608                 passedNwList.add(nw);
2609                 continue;
2610             }
2611             Network network = neutronvpnUtils.getNeutronNetwork(nw);
2612             if (network == null) {
2613                 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2614                 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2615                         nw.getValue()));
2616                 continue;
2617             }
2618             Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2619             if (networkVpnId == null) {
2620                 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2621                 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2622                                                nw.getValue()));
2623                 continue;
2624             }
2625             if (!vpnId.equals(networkVpnId)) {
2626                 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2627                           nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2628                 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2629                                 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2630                                 vpnId.getValue()));
2631                 continue;
2632             }
2633             if (NeutronvpnUtils.getIsExternal(network)) {
2634                 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2635                     passedNwList.add(nw);
2636                 } else {
2637                     LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2638                               nw.getValue(), vpnId.getValue());
2639                     failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2640                                                    vpnId.getValue()));
2641                     continue;
2642                 }
2643             }
2644             IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2645             for (Uuid subnet : networkSubnets) {
2646                 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2647                 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2648                 if (!ipVersion.isIpVersionChosen(ipVers)) {
2649                     ipVersion = ipVersion.addVersion(ipVers);
2650                 }
2651                 if (!NeutronvpnUtils.getIsExternal(network)) {
2652                     LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2653                             vpnId.getValue());
2654                     removeSubnetFromVpn(vpnId, subnet, null);
2655                     Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2656                     vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2657                             vpnId.getValue());
2658                     passedNwList.add(nw);
2659                 }
2660             }
2661             if (ipVersion != IpVersionChoice.UNDEFINED) {
2662                 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2663                         + " for VPN {}", ipVersion, vpnId);
2664                 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2665             }
2666         }
2667         clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2668         LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2669                 passedNwList, vpnId.getValue());
2670         return failedNwList;
2671     }
2672
2673     private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2674         if (!removeExternalNetworkFromVpn(extNet)) {
2675             return false;
2676         }
2677         // check, if there is another Provider Networks associated with given VPN
2678         List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2679         if (vpnNets != null) {
2680             //Remove currently disassociated network from the list
2681             vpnNets.remove(extNet.getUuid());
2682             for (Uuid netId : vpnNets) {
2683                 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2684                     LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2685                             + "{}", vpnId.getValue(), netId.getValue());
2686                     return true;
2687                 }
2688             }
2689         }
2690         //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2691         LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2692                 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2693         neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2694         IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2695         for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2696             Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2697             if (sm == null) {
2698                 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2699                 continue;
2700             }
2701             IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2702             if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2703                 continue;
2704             }
2705             if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2706                 updateVpnInternetForSubnet(sm, vpnId, false);
2707             }
2708             if (!ipVersion.isIpVersionChosen(ipVers)) {
2709                 ipVersion = ipVersion.addVersion(ipVers);
2710             }
2711         }
2712         if (ipVersion != IpVersionChoice.UNDEFINED) {
2713             neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2714             LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2715                     vpnId.getValue());
2716             neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2717         }
2718         return true;
2719     }
2720
2721     /**
2722      * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2723      */
2724     @Override
2725     // TODO Clean up the exception handling
2726     @SuppressWarnings("checkstyle:IllegalCatch")
2727     public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2728
2729         AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2730         SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2731         StringBuilder returnMsg = new StringBuilder();
2732         Uuid vpnId = input.getVpnId();
2733
2734         try {
2735             if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2736                 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2737                         input.getNetworkId());
2738                 List<Uuid> netIds = input.getNetworkId();
2739                 if (netIds != null && !netIds.isEmpty()) {
2740                     List<String> failed = associateNetworksToVpn(vpnId, netIds);
2741                     if (!failed.isEmpty()) {
2742                         returnMsg.append(failed);
2743                     }
2744                 }
2745             } else {
2746                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2747             }
2748             if (returnMsg.length() != 0) {
2749                 opBuilder.setResponse(
2750                         "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2751                                 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2752                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2753             } else {
2754                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2755             }
2756         } catch (Exception ex) {
2757             LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2758             result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2759                     formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2760                             input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2761         }
2762         LOG.debug("associateNetworks returns..");
2763         return result;
2764     }
2765
2766     /**
2767      * It handles the invocations to the neutronvpn:associateRouter RPC method.
2768      */
2769     @Override
2770     public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2771
2772         SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2773         LOG.debug("associateRouter {}", input);
2774         StringBuilder returnMsg = new StringBuilder();
2775         Uuid vpnId = input.getVpnId();
2776         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2777                 routerIds = input.getRouterIds();
2778         Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2779         Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2780         Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2781         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2782                 .RouterIds routerId : routerIds) {
2783             VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2784             Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2785             if (vpnMap != null) {
2786                 if (rtr != null) {
2787                     Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2788                     if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2789                         returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2790                                 .append(routerId.getRouterId());
2791                     } else if (extVpnId != null) {
2792                         returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2793                                 + "another VPN ").append(extVpnId.getValue());
2794                     } else {
2795                         LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2796                                 routerId.getRouterId());
2797                         associateRouterToVpn(vpnId, routerId.getRouterId());
2798                     }
2799                 } else {
2800                     returnMsg.append("router not found : ").append(routerId.getRouterId());
2801                 }
2802             } else {
2803                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2804             }
2805             if (returnMsg.length() != 0) {
2806                 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2807                         "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2808                                 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2809             } else {
2810                 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2811             }
2812         }
2813         LOG.debug("associateRouter returns..");
2814         return result;
2815     }
2816
2817     /**
2818      * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2819      */
2820     @Override
2821     // TODO Clean up the exception handling
2822     @SuppressWarnings("checkstyle:IllegalCatch")
2823     public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2824         GetFixedIPsForNeutronPortInput input) {
2825         GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2826         SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2827         Uuid portId = input.getPortId();
2828         StringBuilder returnMsg = new StringBuilder();
2829         try {
2830             List<String> fixedIPList = new ArrayList<>();
2831             Port port = neutronvpnUtils.getNeutronPort(portId);
2832             if (port != null) {
2833                 for (FixedIps ip : port.nonnullFixedIps()) {
2834                     fixedIPList.add(ip.getIpAddress().stringValue());
2835                 }
2836             } else {
2837                 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2838             }
2839             if (returnMsg.length() != 0) {
2840                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2841                         "invalid-value",
2842                         formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2843                                 returnMsg)).build());
2844             } else {
2845                 opBuilder.setFixedIPs(fixedIPList);
2846                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2847                         .build());
2848                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2849             }
2850         } catch (Exception ex) {
2851             result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2852                     formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2853                             portId.getValue(), ex.getMessage(), ex)).build());
2854         }
2855         return result;
2856     }
2857
2858     /**
2859      * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2860      */
2861     @Override
2862     // TODO Clean up the exception handling
2863     @SuppressWarnings("checkstyle:IllegalCatch")
2864     public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2865
2866         DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2867         SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2868
2869         LOG.debug("dissociateNetworks {}", input);
2870         StringBuilder returnMsg = new StringBuilder();
2871         Uuid vpnId = input.getVpnId();
2872
2873         try {
2874             if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2875                 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2876                         input.getNetworkId());
2877                 List<Uuid> netIds = input.getNetworkId();
2878                 if (netIds != null && !netIds.isEmpty()) {
2879                     List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2880                     if (!failed.isEmpty()) {
2881                         returnMsg.append(failed);
2882                     }
2883                 }
2884             } else {
2885                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2886             }
2887             if (returnMsg.length() != 0) {
2888                 opBuilder.setResponse(
2889                         "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2890                                 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2891                                 returnMsg));
2892                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2893             } else {
2894                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2895             }
2896         } catch (Exception ex) {
2897             result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2898                     formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2899                             input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2900         }
2901         LOG.debug("dissociateNetworks returns..");
2902         return result;
2903     }
2904
2905     /**
2906      * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2907      */
2908     @Override
2909     // TODO Clean up the exception handling
2910     @SuppressWarnings("checkstyle:IllegalCatch")
2911     public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2912
2913         SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2914
2915         LOG.debug("dissociateRouter {}", input);
2916         StringBuilder returnMsg = new StringBuilder();
2917         Uuid vpnId = input.getVpnId();
2918         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2919                 .RouterIds> routerIdList = input.getRouterIds();
2920         String routerIdsString = "";
2921         Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2922         Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2923         Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2924         if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2925             for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2926                     .RouterIds routerId : routerIdList) {
2927                 try {
2928                     if (routerId != null) {
2929                         routerIdsString += routerId.getRouterId() + ", ";
2930                         Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2931                         if (rtr != null) {
2932                             Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2933                             if (routerVpnId == null) {
2934                                 returnMsg.append("input router ").append(routerId.getRouterId())
2935                                         .append(" not associated to any vpn yet");
2936                             } else if (vpnId.equals(routerVpnId)) {
2937                                 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2938                             } else {
2939                                 returnMsg.append("input router ").append(routerId.getRouterId())
2940                                         .append(" associated to vpn ")
2941                                         .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2942                             }
2943                         } else {
2944                             returnMsg.append("router not found : ").append(routerId.getRouterId());
2945                         }
2946                     }
2947                     if (returnMsg.length() != 0) {
2948                         result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2949                                 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2950                                                 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2951                                         returnMsg)).build());
2952                     } else {
2953                         result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2954                     }
2955                 } catch (Exception ex) {
2956                     result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2957                             formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2958                                     routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2959                 }
2960             }
2961         } else {
2962             returnMsg.append("VPN not found : ").append(vpnId.getValue());
2963         }
2964
2965         LOG.debug("dissociateRouter returns..");
2966         return result;
2967     }
2968
2969     protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2970         // check if the router is associated to some VPN
2971         Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2972         Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2973         if (vpnId != null) {
2974             // remove existing external vpn interfaces
2975             for (Uuid subnetId : routerSubnetIds) {
2976                 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2977             }
2978             clearFromVpnMaps(vpnId, routerId, null);
2979         } else {
2980             // remove existing internal vpn interfaces
2981             for (Uuid subnetId : routerSubnetIds) {
2982                 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2983             }
2984         }
2985         // delete entire vpnMaps node for internal VPN
2986         deleteVpnMapsNode(routerId);
2987
2988         // delete vpn-instance for internal VPN
2989         deleteVpnInstance(routerId);
2990     }
2991
2992     protected Subnet getNeutronSubnet(Uuid subnetId) {
2993         return neutronvpnUtils.getNeutronSubnet(subnetId);
2994     }
2995
2996     @Nullable
2997     protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2998         Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2999         if (null != sn) {
3000             return sn.getGatewayIp();
3001         }
3002         return null;
3003     }
3004
3005
3006     protected Network getNeutronNetwork(Uuid networkId) {
3007         return neutronvpnUtils.getNeutronNetwork(networkId);
3008     }
3009
3010     protected Port getNeutronPort(String name) {
3011         return neutronvpnUtils.getNeutronPort(new Uuid(name));
3012     }
3013
3014     protected Port getNeutronPort(Uuid portId) {
3015         return neutronvpnUtils.getNeutronPort(portId);
3016     }
3017
3018     protected Uuid getNetworkForSubnet(Uuid subnetId) {
3019         return neutronvpnUtils.getNetworkForSubnet(subnetId);
3020     }
3021
3022     protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3023         return neutronvpnUtils.getNetworksForVpn(vpnId);
3024     }
3025
3026     /**
3027      * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3028      *
3029      * @return a List of String to be printed on screen
3030      * @throws ReadFailedException if there was a problem reading from the data store
3031      */
3032     public List<String> showNeutronPortsCLI() throws ReadFailedException {
3033         List<String> result = new ArrayList<>();
3034         result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", "Port ID", "Mac Address", "Prefix Length",
3035             "IP Address"));
3036         result.add("-------------------------------------------------------------------------------------------");
3037         InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3038
3039         Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3040         if (ports.isPresent() && ports.get().getPort() != null) {
3041             for (Port port : ports.get().nonnullPort()) {
3042                 List<FixedIps> fixedIPs = port.getFixedIps();
3043                 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3044                     List<String> ipList = new ArrayList<>();
3045                     for (FixedIps fixedIp : fixedIPs) {
3046                         IpAddress ipAddress = fixedIp.getIpAddress();
3047                         if (ipAddress.getIpv4Address() != null) {
3048                             ipList.add(ipAddress.getIpv4Address().getValue());
3049                         } else {
3050                             ipList.add(ipAddress.getIpv6Address().getValue());
3051                         }
3052                     }
3053                     result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
3054                             .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3055                             ipList.toString()));
3056                 } else {
3057                     result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
3058                             .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3059                 }
3060             }
3061         }
3062
3063         return result;
3064     }
3065
3066     /**
3067      * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3068      *
3069      * @param vpnuuid Uuid of the VPN whose config must be shown
3070      * @return formatted output list
3071      * @throws InterruptedException if there was a thread related problem getting the data to display
3072      * @throws ExecutionException if there was any other problem getting the data to display
3073      */
3074     public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3075         List<String> result = new ArrayList<>();
3076         if (vpnuuid == null) {
3077             result.add("");
3078             result.add("Displaying VPN config for all VPNs");
3079             result.add("To display VPN config for a particular VPN, use the following syntax");
3080             result.add(getshowVpnConfigCLIHelp());
3081         }
3082         RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3083         if (rpcResult.isSuccessful()) {
3084             result.add("");
3085             result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3086             result.add("");
3087             result.add(String.format(" %-80s ", "Import-RTs"));
3088             result.add("");
3089             result.add(String.format(" %-80s ", "Export-RTs"));
3090             result.add("");
3091             result.add(String.format(" %-76s ", "Subnet IDs"));
3092             result.add("");
3093             result.add("------------------------------------------------------------------------------------");
3094             result.add("");
3095             for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3096                     rpcResult.getResult().nonnullL3vpnInstances()) {
3097                 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3098                         : "\"                 " + "                  \"";
3099                 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3100                         vpn.getRouteDistinguisher()));
3101                 result.add("");
3102                 result.add(String.format(" %-80s ", vpn.getImportRT()));
3103                 result.add("");
3104                 result.add(String.format(" %-80s ", vpn.getExportRT()));
3105                 result.add("");
3106
3107                 Uuid vpnid = vpn.getId();
3108                 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3109                 if (!subnetList.isEmpty()) {
3110                     for (Uuid subnetuuid : subnetList) {
3111                         result.add(String.format(" %-76s ", subnetuuid.getValue()));
3112                     }
3113                 } else {
3114                     result.add(String.format(" %-76s ", "\"                                    \""));
3115                 }
3116                 result.add("");
3117                 result.add("----------------------------------------");
3118                 result.add("");
3119             }
3120         } else {
3121             String errortag = rpcResult.getErrors().iterator().next().getTag();
3122             if (Objects.equals(errortag, "")) {
3123                 result.add("");
3124                 result.add("No VPN has been configured yet");
3125             } else if (Objects.equals(errortag, "invalid-value")) {
3126                 result.add("");
3127                 result.add("VPN " + vpnuuid.getValue() + " is not present");
3128             } else {
3129                 result.add("error getting VPN info : " + rpcResult.getErrors());
3130                 result.add(getshowVpnConfigCLIHelp());
3131             }
3132         }
3133         return result;
3134     }
3135
3136     protected void createExternalVpnInterfaces(Uuid extNetId) {
3137         if (extNetId == null) {
3138             LOG.error("createExternalVpnInterfaces: external network is null");
3139             return;
3140         }
3141
3142         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3143         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3144             LOG.error("No external ports attached to external network {}", extNetId.getValue());
3145             return;
3146         }
3147
3148         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3149             for (String elanInterface : extElanInterfaces) {
3150                 createExternalVpnInterface(extNetId, elanInterface, tx);
3151             }
3152         }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3153     }
3154
3155     // TODO Clean up the exception handling
3156     @SuppressWarnings("checkstyle:IllegalCatch")
3157     protected void removeExternalVpnInterfaces(Uuid extNetId) {
3158         Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3159         if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3160             LOG.error("No external ports attached for external network {}", extNetId.getValue());
3161             return;
3162         }
3163         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3164             for (String elanInterface : extElanInterfaces) {
3165                 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3166                         .buildVpnInterfaceIdentifier(elanInterface);
3167                 LOG.info("Removing vpn interface {}", elanInterface);
3168                 tx.delete(vpnIfIdentifier);
3169             }
3170         }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3171     }
3172
3173     private void createExternalVpnInterface(Uuid vpnId, String infName,
3174                                             TypedWriteTransaction<Configuration> wrtConfigTxn) {
3175         writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3176                 false /* not a router iface */, wrtConfigTxn);
3177     }
3178
3179     // TODO Clean up the exception handling
3180     @SuppressWarnings("checkstyle:IllegalCatch")
3181     private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3182             @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3183             TypedWriteTransaction<Configuration> wrtConfigTxn) {
3184         if (vpnIdList.isEmpty() || infName == null) {
3185             LOG.error("vpnid is empty or interface({}) is null", infName);
3186             return;
3187         }
3188         if (wrtConfigTxn == null) {
3189             ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3190                 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3191                 "Error writing VPN interface");
3192             return;
3193         }
3194         List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3195         for (Uuid vpnId: vpnIdList) {
3196             VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3197                                    AssociatedSubnetType.V4AndV6Subnets);
3198             vpnIdListStruct.add(vpnInstance);
3199         }
3200
3201         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3202         VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3203                 .setName(infName)
3204                 .setVpnInstanceNames(vpnIdListStruct)
3205                 .setRouterInterface(isRouterInterface);
3206         LOG.info("Network Id is {}", networkUuid);
3207         if (networkUuid != null) {
3208             Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3209             ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3210             NetworkAttributes.NetworkType networkType = providerType != null
3211                     ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3212             String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3213             vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3214                 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3215         }
3216
3217         if (adjacencies != null) {
3218             vpnb.addAugmentation(Adjacencies.class, adjacencies);
3219         }
3220         VpnInterface vpnIf = vpnb.build();
3221         try {
3222             LOG.info("Creating vpn interface {}", vpnIf);
3223             wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3224         } catch (Exception ex) {
3225             LOG.error("Creation of vpninterface {} failed", infName, ex);
3226         }
3227     }
3228
3229     private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3230                                                    TypedWriteTransaction<Configuration> wrtConfigTxn) {
3231         if (vpnId == null || infName == null) {
3232             LOG.error("vpn id or interface is null");
3233             return;
3234         }
3235         if (wrtConfigTxn == null) {
3236             LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3237             ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3238                 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3239             }), LOG, "Error updating VPN interface with adjacencies");
3240             return;
3241         }
3242
3243         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3244
3245         try (AcquireResult lock = tryInterfaceLock(infName)) {
3246             if (!lock.wasAcquired()) {
3247                 // FIXME: why do we even bother with locking if we do not honor it?!
3248                 logTryLockFailure(infName);
3249             }
3250
3251             try {
3252                 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3253                         .syncReadOptional(dataBroker, LogicalDatastoreType
3254                             .CONFIGURATION, vpnIfIdentifier);
3255                 if (optionalVpnInterface.isPresent()) {
3256                     VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3257                     LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3258
3259                     if (adjacencies == null) {
3260                         return;
3261                     }
3262                     vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3263                     if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3264                         List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3265                                 optionalVpnInterface.get().getVpnInstanceNames());
3266                         if (listVpnInstances.isEmpty()
3267                                 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3268                             VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3269                                 AssociatedSubnetType.V4AndV6Subnets);
3270                             listVpnInstances.add(vpnInstance);
3271                             vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3272                         }
3273                     } else {
3274                         VpnInstanceNames vpnInstance = VpnHelper
3275                                 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3276                         List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3277                         listVpnInstances.add(vpnInstance);
3278                         vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3279                     }
3280                     LOG.info("Updating vpn interface {} with new adjacencies", infName);
3281                     wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3282                 }
3283             } catch (IllegalStateException | ReadFailedException ex) {
3284                 // FIXME: why are we catching IllegalStateException here?
3285                 LOG.error("Update of vpninterface {} failed", infName, ex);
3286             }
3287         }
3288     }
3289
3290     private String getshowVpnConfigCLIHelp() {
3291         StringBuilder help = new StringBuilder("Usage:");
3292         help.append("display vpn-config [-vid/--vpnid <id>]");
3293         return help.toString();
3294     }
3295
3296     protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3297         floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3298     }
3299
3300     @Override
3301     public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3302         return neutronEvpnManager.createEVPN(input);
3303     }
3304
3305     @Override
3306     public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3307         return neutronEvpnManager.getEVPN(input);
3308     }
3309
3310     @Override
3311     public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3312         return neutronEvpnManager.deleteEVPN(input);
3313     }
3314
3315     private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3316         Uuid extNetId = extNet.getUuid();
3317         InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3318                 .child(Networks.class, new NetworksKey(extNetId)).build();
3319
3320         try {
3321             Optional<Networks> optionalExtNets =
3322                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3323                                                                  extNetIdentifier);
3324             if (!optionalExtNets.isPresent()) {
3325                 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3326                           extNetId.getValue());
3327                 return false;
3328             }
3329             NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3330             builder.setVpnid(vpnId);
3331             Networks networks = builder.build();
3332             // Add Networks object to the ExternalNetworks list
3333             LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3334                       extNetId.getValue());
3335             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3336                                                   networks);
3337             return true;
3338         } catch (TransactionCommitFailedException | ReadFailedException ex) {
3339             LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3340                       extNetId.getValue(), ex);
3341         }
3342         return false;
3343     }
3344
3345     private boolean removeExternalNetworkFromVpn(Network extNet) {
3346         Uuid extNetId = extNet.getUuid();
3347         InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3348             .child(Networks.class, new NetworksKey(extNetId)).build();
3349         try {
3350             Optional<Networks> optionalNets =
3351                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3352                             extNetsId);
3353             NetworksBuilder builder = null;
3354             if (optionalNets.isPresent()) {
3355                 builder = new NetworksBuilder(optionalNets.get());
3356             } else {
3357                 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3358                         extNetId.getValue());
3359                 return false;
3360             }
3361             builder.setVpnid(null);
3362             Networks networks = builder.build();
3363             LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3364                     extNetId.getValue());
3365             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3366             return true;
3367         } catch (TransactionCommitFailedException | ReadFailedException ex) {
3368             LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3369                     extNetId.getValue(), ex);
3370         }
3371         return false;
3372     }
3373
3374     private Optional<String> getExistingOperationalVpn(String primaryRd) {
3375         Optional<String> existingVpnName = Optional.of(primaryRd);
3376         Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3377         try {
3378             vpnInstanceOpDataOptional = SingleTransactionDataBroker
3379                 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3380                     neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3381         } catch (ReadFailedException e) {
3382             LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3383                     primaryRd, e);
3384             /*Read failed. We don't know if a VPN exists or not.
3385             * Return primaryRd to halt caller execution, to be safe.*/
3386             return existingVpnName;
3387         }
3388         if (vpnInstanceOpDataOptional.isPresent()) {
3389             existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3390         } else {
3391             existingVpnName = Optional.absent();
3392         }
3393         return existingVpnName;
3394     }
3395
3396     private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3397         return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3398     }
3399
3400     private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3401         return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3402     }
3403
3404     private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3405         return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3406     }
3407
3408     private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3409         String message = tuple.getMessage();
3410         logger.accept(message);
3411         return message;
3412     }
3413
3414     protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3415                                                   @NonNull Subnetmap subnetMap) {
3416         updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3417         neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3418         if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3419             neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3420             LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3421                     subnetMap.getId().getValue(), internetVpnId.getValue());
3422         }
3423     }
3424
3425     protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3426                                                      @NonNull Subnetmap subnetMap) {
3427         updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3428         neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3429     }
3430
3431     protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3432         if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3433             LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3434                             + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3435                     internetVpnId.getValue(), routerId.getValue());
3436             neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3437                     ? true : false);
3438         }
3439     }
3440
3441     @CheckReturnValue
3442     private AcquireResult tryInterfaceLock(final String infName) {
3443         return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3444     }
3445
3446     @CheckReturnValue
3447     private AcquireResult tryVpnLock(final Uuid vpnId) {
3448         return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3449     }
3450
3451     private static ReentrantLock lockForUuid(Uuid uuid) {
3452         // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3453         return JvmGlobalLocks.getLockForString(uuid.getValue());
3454     }
3455
3456     private static void logTryLockFailure(Object objectId) {
3457         LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());
3458     }
3459 }