2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
14 import com.google.common.base.Preconditions;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.JdkFutureAdapters;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
33 import java.util.Optional;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ConcurrentMap;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.Future;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.locks.ReentrantLock;
41 import java.util.function.Consumer;
42 import java.util.stream.Collectors;
43 import javax.annotation.PreDestroy;
44 import javax.inject.Inject;
45 import javax.inject.Singleton;
46 import org.eclipse.jdt.annotation.NonNull;
47 import org.eclipse.jdt.annotation.Nullable;
48 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
49 import org.opendaylight.genius.mdsalutil.NwConstants;
50 import org.opendaylight.genius.utils.JvmGlobalLocks;
51 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
52 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
53 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
54 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
55 import org.opendaylight.mdsal.binding.api.DataBroker;
56 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
57 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
58 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
59 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
60 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
61 import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
62 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
63 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
64 import org.opendaylight.netvirt.elanmanager.api.IElanService;
65 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
66 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
67 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
68 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
69 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
70 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
71 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNamesKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
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.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsKey;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
181 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
182 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
183 import org.opendaylight.yangtools.yang.common.RpcError;
184 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
185 import org.opendaylight.yangtools.yang.common.RpcResult;
186 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
187 import org.slf4j.Logger;
188 import org.slf4j.LoggerFactory;
189 import org.slf4j.helpers.FormattingTuple;
190 import org.slf4j.helpers.MessageFormatter;
193 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
195 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
196 private static final long LOCK_WAIT_TIME = 10L;
198 private final DataBroker dataBroker;
199 private final ManagedNewTransactionRunner txRunner;
200 private final VpnRpcService vpnRpcService;
201 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
202 private final IElanService elanService;
203 private final NeutronvpnConfig neutronvpnConfig;
204 private final NeutronEvpnManager neutronEvpnManager;
205 private final NeutronEvpnUtils neutronEvpnUtils;
206 private final JobCoordinator jobCoordinator;
207 private final NeutronvpnUtils neutronvpnUtils;
208 private final IVpnManager vpnManager;
209 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
210 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
211 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
212 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
215 public NeutronvpnManager(
216 final DataBroker dataBroker,
217 final VpnRpcService vpnRpcSrv, final IElanService elanService,
218 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
219 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
220 final JobCoordinator jobCoordinator,
221 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
222 this.dataBroker = dataBroker;
223 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
224 vpnRpcService = vpnRpcSrv;
225 this.elanService = elanService;
226 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
227 this.neutronvpnConfig = neutronvpnConfig;
228 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
229 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
230 this.jobCoordinator = jobCoordinator;
231 this.neutronvpnUtils = neutronvpnUtils;
232 this.vpnManager = vpnManager;
239 public void close() {
240 LOG.info("{} close", getClass().getSimpleName());
243 private void configureFeatures() throws TransactionCommitFailedException {
244 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
245 Neutron.class).child(Features.class).child(
246 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
247 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
249 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
250 } catch (OptimisticLockFailedException e) {
251 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
253 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
254 Neutron.class).child(Features.class).child(
255 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
256 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
258 SingleTransactionDataBroker.syncWrite(
259 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
260 } catch (OptimisticLockFailedException e) {
261 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
265 public String getOpenDaylightVniRangesConfig() {
266 return neutronvpnConfig.getOpendaylightVniRanges();
269 // TODO Clean up the exception handling
270 @SuppressWarnings("checkstyle:IllegalCatch")
271 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
272 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
273 boolean isExternalNw) {
275 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
276 final ReentrantLock lock = lockForUuid(subnetId);
279 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
280 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
281 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
282 if (sn.isPresent()) {
283 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
284 subnetId.getValue());
287 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
288 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
289 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
290 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
291 subnetId.getValue());
292 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
293 subnetMapIdentifier, subnetmapBuilder.build());
297 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
298 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
300 // check if there are ports to update for already created Subnetmap node
301 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
302 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
303 if (entry.getValue().getValue().equals(subnetId.getValue())) {
304 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
305 unprocessedPortsMap.remove(entry.getKey());
311 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
312 @Nullable Uuid internetvpnId) {
313 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
314 .child(Subnetmap.class, new SubnetmapKey(subnetId))
316 final ReentrantLock lock = lockForUuid(subnetId);
319 Optional<Subnetmap> sn =
320 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
321 if (!sn.isPresent()) {
322 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
325 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
326 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
327 if (routerId != null) {
328 builder.setRouterId(routerId);
331 builder.setVpnId(vpnId);
333 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
334 builder.setInternetVpnId(internetvpnId);
336 Subnetmap subnetmap = builder.build();
337 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
338 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
340 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
341 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
348 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
349 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
350 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
351 InstanceIdentifier<Subnetmap> id =
352 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
353 final ReentrantLock lock = lockForUuid(subnetId);
356 Optional<Subnetmap> sn =
357 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
358 if (!sn.isPresent()) {
359 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
360 subnetId.getValue());
363 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
364 subnetId.getValue());
365 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
366 builder.setRouterId(routerId);
367 builder.setRouterInterfacePortId(routerInterfacePortId);
368 builder.setRouterIntfMacAddress(routerIntfMacAddress);
369 builder.setRouterInterfaceFixedIp(fixedIp);
371 builder.setVpnId(vpnId);
373 Subnetmap subnetmap = builder.build();
374 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
375 subnetId.getValue());
376 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
377 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
378 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
379 subnetId.getValue(), e);
385 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
386 @Nullable Uuid directPortId) {
387 Subnetmap subnetmap = null;
388 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
389 new SubnetmapKey(subnetId)).build();
390 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
391 final ReentrantLock lock = lockForUuid(subnetId);
394 Optional<Subnetmap> sn =
395 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
397 if (sn.isPresent()) {
398 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
399 if (null != portId) {
400 List<Uuid> existingPortList = builder.getPortList();
401 List<Uuid> portList = new ArrayList<>();
402 if (null != existingPortList) {
403 portList.addAll(existingPortList);
405 portList.add(portId);
406 builder.setPortList(portList);
407 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
408 subnetId.getValue(), portId.getValue());
410 if (null != directPortId) {
411 List<Uuid> existingDirectPortList = builder.getDirectPortList();
412 List<Uuid> directPortList = new ArrayList<>();
413 if (null != existingDirectPortList) {
414 directPortList.addAll(existingDirectPortList);
416 directPortList.add(directPortId);
417 builder.setDirectPortList(directPortList);
418 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
419 directPortId.getValue());
421 subnetmap = builder.build();
422 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
425 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
426 + "cache ", subnetId.getValue(), portId.getValue());
427 unprocessedPortsMap.put(portId, subnetId);
429 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
430 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
437 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
438 Uuid vpnId, @Nullable Uuid portId) {
439 Subnetmap subnetmap = null;
440 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
441 .child(Subnetmap.class, new SubnetmapKey(subnetId))
443 final ReentrantLock lock = lockForUuid(subnetId);
446 Optional<Subnetmap> sn =
447 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
449 if (sn.isPresent()) {
450 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
451 if (routerId != null) {
452 builder.setRouterId(null);
454 if (networkId != null) {
455 builder.setNetworkId(null);
458 builder.setVpnId(null);
460 builder.setInternetVpnId(null);
461 if (portId != null && builder.getPortList() != null) {
462 List<Uuid> portList = new ArrayList<>(builder.getPortList());
463 portList.remove(portId);
464 builder.setPortList(portList);
467 subnetmap = builder.build();
468 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
469 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
472 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
474 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
475 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
483 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
484 @Nullable Uuid directPortId) {
485 Subnetmap subnetmap = null;
486 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
487 new SubnetmapKey(subnetId)).build();
488 final ReentrantLock lock = lockForUuid(subnetId);
491 Optional<Subnetmap> sn =
492 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
494 if (sn.isPresent()) {
495 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
496 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
497 List<Uuid> portList = new ArrayList<>(builder.getPortList());
498 portList.remove(portId);
499 builder.setPortList(portList);
500 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
501 subnetId.getValue());
503 if (null != directPortId && null != builder.getDirectPortList()
504 && !builder.getDirectPortList().isEmpty()) {
505 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
506 directPortList.remove(directPortId);
507 builder.setDirectPortList(directPortList);
508 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
509 .getValue(), subnetId.getValue());
511 subnetmap = builder.build();
512 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
515 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
517 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
518 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
519 subnetId.getValue(), e);
526 // TODO Clean up the exception handling
527 @SuppressWarnings("checkstyle:IllegalCatch")
528 protected void deleteSubnetMapNode(Uuid subnetId) {
529 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
530 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
531 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
532 final ReentrantLock lock = lockForUuid(subnetId);
535 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
536 } catch (TransactionCommitFailedException e) {
537 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
543 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
544 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
545 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
547 Optional<VpnInstance> vpnInstanceConfig =
548 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
550 if (!vpnInstanceConfig.isPresent()) {
551 LOG.debug("updateVpnInstanceWithRDs: "
552 + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
555 VpnInstance vpnInstance = vpnInstanceConfig.get();
556 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
557 updateVpnInstanceBuilder.setRouteDistinguisher(rds);
558 LOG.debug("updateVpnInstanceWithRDs: "
559 + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
560 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
561 updateVpnInstanceBuilder.build());
562 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
563 LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
564 + "the list of RDs: {}", vpnInstanceId, rds, ex);
568 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
569 boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
570 String vpnName = vpnId.getValue();
571 VpnInstanceBuilder builder = null;
572 List<VpnTarget> vpnTargetList = new ArrayList<>();
573 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
574 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
575 Optional<VpnInstance> optionalVpn;
577 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
579 } catch (ExecutionException | InterruptedException e) {
580 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
584 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
585 if (optionalVpn.isPresent()) {
586 builder = new VpnInstanceBuilder(optionalVpn.get());
587 LOG.debug("updating existing vpninstance node");
589 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
590 .setL2vpn(isL2Vpn).setL3vni(l3vni).setBgpvpnType(VpnInstance.BgpvpnType.InternalVPN);
592 if (irt != null && !irt.isEmpty()) {
593 if (ert != null && !ert.isEmpty()) {
594 List<String> commonRT = new ArrayList<>(irt);
595 commonRT.retainAll(ert);
597 for (String common : commonRT) {
600 VpnTarget vpnTarget =
601 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
602 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
603 vpnTargetList.add(vpnTarget);
606 for (String importRT : irt) {
607 VpnTarget vpnTarget =
608 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
609 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
610 vpnTargetList.add(vpnTarget);
614 if (ert != null && !ert.isEmpty()) {
615 for (String exportRT : ert) {
616 VpnTarget vpnTarget =
617 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
618 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
619 vpnTargetList.add(vpnTarget);
623 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
624 if (rd != null && !rd.isEmpty()) {
625 builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets).setBgpvpnType(VpnInstance.BgpvpnType.BGPVPN);
628 builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
629 VpnInstance newVpn = builder.build();
630 try (AcquireResult lock = tryVpnLock(vpnId)) {
631 if (!lock.wasAcquired()) {
632 // FIXME: why do we even bother with locking if we do not honor it?!
633 logTryLockFailure(vpnId);
636 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
638 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
640 } catch (TransactionCommitFailedException e) {
641 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
646 private void deleteVpnMapsNode(Uuid vpnId) {
647 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
648 .child(VpnMap.class, new VpnMapKey(vpnId))
650 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
651 try (AcquireResult lock = tryVpnLock(vpnId)) {
652 if (!lock.wasAcquired()) {
653 // FIXME: why do we even bother with locking if we do not honor it?!
654 logTryLockFailure(vpnId);
658 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
660 } catch (TransactionCommitFailedException e) {
661 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
666 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
667 @Nullable List<Uuid> networks) {
668 VpnMapBuilder builder;
669 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
670 .child(VpnMap.class, new VpnMapKey(vpnId))
673 Optional<VpnMap> optionalVpnMap =
674 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
676 if (optionalVpnMap.isPresent()) {
677 builder = new VpnMapBuilder(optionalVpnMap.get());
679 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
683 builder.setName(name);
685 if (tenantId != null) {
686 builder.setTenantId(tenantId);
688 if (router != null) {
689 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
690 List<RouterIds> rtrIds = builder.getRouterIds() != null
691 ? new ArrayList<>(builder.getRouterIds().values()) : null;
692 if (rtrIds == null) {
693 rtrIds = Collections.singletonList(vpnRouterId);
695 //Add vpnRouterId to rtrIds list only if update routerId is not existing in the VpnMap already
696 for (RouterIds routerId: rtrIds) {
697 if (!Objects.equals(routerId, vpnRouterId)) {
698 rtrIds.add(vpnRouterId);
702 builder.setRouterIds(rtrIds);
704 if (networks != null) {
705 List<Uuid> nwList = builder.getNetworkIds() != null
706 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
707 nwList.addAll(networks);
708 builder.setNetworkIds(nwList);
711 try (AcquireResult lock = tryVpnLock(vpnId)) {
712 if (!lock.wasAcquired()) {
713 // FIXME: why do we even bother with locking if we do not honor it?!
714 logTryLockFailure(vpnId);
717 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
718 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
720 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
722 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
723 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
727 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
728 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
729 .child(VpnMap.class, new VpnMapKey(vpnId))
731 Optional<VpnMap> optionalVpnMap;
734 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
736 } catch (ExecutionException | InterruptedException e) {
737 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
740 if (optionalVpnMap.isPresent()) {
741 VpnMap vpnMap = optionalVpnMap.get();
742 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
743 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds().values());
744 if (rtrIds == null) {
745 rtrIds = new ArrayList<>();
747 if (routerId != null) {
748 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
749 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
750 vpnMapBuilder.setRouterIds(rtrIds);
752 try (AcquireResult lock = tryVpnLock(vpnId)) {
753 if (!lock.wasAcquired()) {
754 // FIXME: why do we even bother with locking if we do not honor it?!
755 logTryLockFailure(vpnId);
758 LOG.debug("removing vpnMaps node: {} ", vpnId);
760 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
762 } catch (TransactionCommitFailedException e) {
763 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
767 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
768 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
769 vpnMapBuilder.setRouterIds(rtrIds);
770 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
773 if (networkIds != null) {
774 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
775 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
776 vpnNw.removeAll(networkIds);
777 if (vpnNw.isEmpty()) {
778 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
779 vpnMapBuilder.setNetworkIds(null);
781 vpnMapBuilder.setNetworkIds(vpnNw);
785 try (AcquireResult lock = tryVpnLock(vpnId)) {
786 if (!lock.wasAcquired()) {
787 // FIXME: why do we even bother with locking if we do not honor it?!
788 logTryLockFailure(vpnId);
791 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
793 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
794 vpnMapIdentifier, vpnMapBuilder.build());
795 } catch (TransactionCommitFailedException e) {
796 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
800 LOG.error("VPN : {} not found", vpnId.getValue());
802 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
805 private void deleteVpnInstance(Uuid vpnId) {
806 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
807 .child(VpnInstance.class,
808 new VpnInstanceKey(vpnId.getValue()))
811 try (AcquireResult lock = tryVpnLock(vpnId)) {
812 if (!lock.wasAcquired()) {
813 // FIXME: why do we even bother with locking if we do not honor it?!
814 logTryLockFailure(vpnId);
817 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
819 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
820 } catch (TransactionCommitFailedException e) {
821 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
826 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
827 TypedWriteTransaction<Configuration> wrtConfigTxn,
828 @Nullable VpnInterface vpnIface) {
829 List<Adjacency> adjList = new ArrayList<>();
830 if (vpnIface != null) {
831 adjList = new ArrayList<>(vpnIface.augmentation(Adjacencies.class).getAdjacency().values());
833 String infName = port.getUuid().getValue();
834 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
835 for (FixedIps ip : port.nonnullFixedIps().values()) {
836 String ipValue = ip.getIpAddress().stringValue();
837 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
838 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
839 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
840 snTemp.getSubnetIp(), false)) {
843 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
845 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
846 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
847 //Create Neutron port adjacency if VPN presence is existing for subnet
848 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
849 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
850 .setSubnetId(ip.getSubnetId()).build();
851 if (!adjList.contains(vmAdj)) {
855 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
856 if (snTemp != null && snTemp.getInternetVpnId() != null) {
857 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
858 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
860 if (routerId != null) {
861 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
862 if (rtr != null && rtr.getRoutes() != null) {
863 List<Routes> routeList = new ArrayList<>(rtr.getRoutes().values());
864 // create extraroute Adjacence for each ipValue,
865 // because router can have IPv4 and IPv6 subnet ports, or can have
866 // more that one IPv4 subnet port or more than one IPv6 subnet port
867 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
868 if (!erAdjList.isEmpty()) {
869 adjList.addAll(erAdjList);
874 return new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(adjList)).build();
877 private Map<AdjacencyKey, Adjacency> getAdjacencyMap(List<Adjacency> adjList) {
878 //convert to set to remove duplicates.
879 Set<Adjacency> adjset = adjList.stream().collect(Collectors.toSet());
880 Map<AdjacencyKey, Adjacency> adjacencyMap = new HashMap<>();
881 for (Adjacency adj : adjset) {
882 adjacencyMap.put(new AdjacencyKey(adj.getIpAddress()), adj);
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());
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);
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);
909 optionalVpnInterface = SingleTransactionDataBroker
910 .syncReadOptional(dataBroker, LogicalDatastoreType
911 .CONFIGURATION, vpnIfIdentifier);
912 } catch (ExecutionException | InterruptedException e) {
913 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
916 if (!optionalVpnInterface.isPresent()) {
919 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
920 sn != null ? sn.getSubnetIp() : "null");
921 Map<AdjacencyKey, Adjacency> keyAdjacencyMap
922 = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
923 List<Adjacency> updatedAdjsList = new ArrayList<>();
924 boolean isIpFromAnotherSubnet = false;
925 for (Adjacency adj : keyAdjacencyMap.values()) {
926 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
927 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
928 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
929 isIpFromAnotherSubnet = true;
931 updatedAdjsList.add(adj);
934 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
935 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
938 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
939 String.valueOf(adjString), wrtConfigTxn);
941 if (internetVpnId != null) {
942 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
943 String.valueOf(adjString), wrtConfigTxn);
946 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
947 && sn.getRouterId() != null) {
948 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
949 if (rtr != null && rtr.getRoutes() != null) {
950 List<Routes> extraRoutesToRemove = new ArrayList<>();
951 for (Routes rt: rtr.getRoutes().values()) {
952 if (rt.getNexthop().toString().equals(adjString)) {
953 extraRoutesToRemove.add(rt);
957 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
958 extraRoutesToRemove, vpnId);
959 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
961 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
966 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(updatedAdjsList)).build();
968 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
970 if (!isIpFromAnotherSubnet) {
971 // no more subnetworks for neutron port
972 if (sn != null && sn.getRouterId() != null) {
973 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
975 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
981 // TODO Clean up the exception handling
982 @SuppressWarnings("checkstyle:IllegalCatch")
983 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
984 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
985 if (wrtConfigTxn == null) {
986 LoggingFutures.addErrorLogging(
987 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
988 tx -> deleteVpnInterface(infName, vpnId, tx)),
989 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
993 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
994 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
995 Optional<VpnInterface> optionalVpnInterface;
997 optionalVpnInterface =
998 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1000 } catch (ExecutionException | InterruptedException ex) {
1001 LOG.error("Error during deletion of vpninterface {}", infName, ex);
1004 if (!optionalVpnInterface.isPresent()) {
1005 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
1008 if (vpnId != null) {
1009 VpnInterface vpnInterface = optionalVpnInterface.get();
1010 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap = vpnInterface.getVpnInstanceNames();
1011 if (keyVpnInstanceNamesMap != null
1012 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId,
1013 new ArrayList<>(keyVpnInstanceNamesMap.values()))) {
1014 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId,
1015 new ArrayList<>(keyVpnInstanceNamesMap.values()));
1016 if (!keyVpnInstanceNamesMap.isEmpty()) {
1017 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1018 + "List not empty", infName);
1021 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1022 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1023 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1027 LOG.debug("Deleting vpn interface {}", infName);
1028 wrtConfigTxn.delete(vpnIfIdentifier);
1031 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1032 TypedWriteTransaction<Configuration> writeConfigTxn,
1034 if (vpnId == null || port == null) {
1037 String infName = port.getUuid().getValue();
1038 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1040 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1041 .syncReadOptional(dataBroker, LogicalDatastoreType
1042 .CONFIGURATION, vpnIfIdentifier);
1043 if (optionalVpnInterface.isPresent()) {
1044 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap
1045 = optionalVpnInterface.get().getVpnInstanceNames();
1046 if (keyVpnInstanceNamesMap != null
1047 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),
1048 new ArrayList<>(keyVpnInstanceNamesMap.values()))) {
1049 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(),
1050 new ArrayList<>(keyVpnInstanceNamesMap.values()));
1052 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1053 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1054 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1055 LOG.debug("Updating vpn interface {}", infName);
1056 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency() : new HashMap<>();
1057 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1058 while (adjacencyIter.hasNext()) {
1059 Adjacency adjacency = adjacencyIter.next();
1060 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1063 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1064 InstanceIdentifier<LearntVpnVipToPort> id =
1065 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1066 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1067 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1068 LogicalDatastoreType.OPERATIONAL, id);
1069 if (optionalVpnVipToPort.isPresent()) {
1070 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1072 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1073 adjacencyIter.remove();
1075 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1076 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1077 mipToQuery, infName, vpnId.getValue());
1080 for (FixedIps ip : port.nonnullFixedIps().values()) {
1081 String ipValue = ip.getIpAddress().stringValue();
1083 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1086 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1087 ipValue, writeConfigTxn);
1089 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1090 if (sm != null && sm.getRouterId() != null) {
1091 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1093 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1095 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1098 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1100 } catch (ExecutionException | InterruptedException ex) {
1101 LOG.error("Update of vpninterface {} failed", infName, ex);
1105 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1107 TypedWriteTransaction<Configuration> writeConfigTxn,
1108 boolean isInternetVpn) {
1109 if (vpnId == null || port == null) {
1112 String infName = port.getUuid().getValue();
1113 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1115 try (AcquireResult lock = tryInterfaceLock(infName)) {
1116 if (!lock.wasAcquired()) {
1117 // FIXME: why do we even bother with locking if we do not honor it?!
1118 logTryLockFailure(infName);
1122 Optional<VpnInterface> optionalVpnInterface =
1123 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1125 if (optionalVpnInterface.isPresent()) {
1126 VpnInstanceNames vpnInstance = VpnHelper
1127 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1128 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface.get()
1129 .getVpnInstanceNames().values());
1130 if (oldVpnId != null
1131 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1132 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1134 if (vpnId.getValue() != null
1135 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1136 listVpn.add(vpnInstance);
1138 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1139 .setVpnInstanceNames(listVpn);
1140 LOG.debug("Updating vpn interface {}", infName);
1141 if (!isBeingAssociated) {
1142 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1143 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency()
1145 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1146 while (adjacencyIter.hasNext()) {
1147 Adjacency adjacency = adjacencyIter.next();
1148 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1149 InstanceIdentifier<LearntVpnVipToPort> id =
1150 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1151 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1152 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1153 LogicalDatastoreType.OPERATIONAL, id);
1154 if (optionalVpnVipToPort.isPresent()
1155 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1156 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1157 + "from VPN {}", infName, vpnId, oldVpnId);
1158 adjacencyIter.remove();
1159 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1161 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1162 mipToQuery, infName, vpnId.getValue());
1164 InstanceIdentifier<VpnPortipToPort> build =
1165 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1166 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1167 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1168 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1169 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1170 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1171 mipToQuery, infName, vpnId.getValue());
1174 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(keyAdjacencyMap).build();
1175 vpnIfBuilder.addAugmentation(adjacencies);
1177 for (FixedIps ip : port.nonnullFixedIps().values()) {
1178 String ipValue = ip.getIpAddress().stringValue();
1179 if (oldVpnId != null) {
1180 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1181 ipValue, writeConfigTxn);
1183 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1184 && isInternetVpn == true) {
1188 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1189 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1191 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1193 LOG.error("VPN Interface {} not found", infName);
1195 } catch (ExecutionException | InterruptedException ex) {
1196 LOG.error("Updation of vpninterface {} failed", infName, ex);
1201 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1202 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1204 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1206 // Update VPN Instance node
1207 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
1209 // Update local vpn-subnet DS
1210 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1212 if (routerId != null) {
1213 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1214 if (existingVpn != null) {
1215 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1216 // if before reboot, router was already associated to VPN, should not proceed associating router to
1217 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1218 // preserved upon reboot.
1219 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1220 // RouterInterfacesMap via #createVPNInterface call.
1221 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1222 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1225 associateRouterToInternalVpn(vpnId, routerId);
1230 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1231 * specified Neutron Networks and Routers.
1233 * @param vpnId Uuid of the VPN tp be created
1234 * @param name Representative name of the new VPN
1235 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1236 * @param rdList Route-distinguisher for the VPN
1237 * @param irtList A list of Import Route Targets
1238 * @param ertList A list of Export Route Targets
1239 * @param routerIdsList ist of neutron router Id to associate with created VPN
1240 * @param networkList UUID of the neutron network the VPN may be associated to
1241 * @param isL2Vpn True if VPN Instance is of type L2, false if L3
1242 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1243 * @throws Exception if association of L3VPN failed
1245 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1246 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1247 boolean isL2Vpn, long l3vni) throws Exception {
1249 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1251 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1252 for (Uuid routerId : routerIdsList) {
1253 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1254 ipVersChoices = ipVersChoices.addVersion(vers);
1257 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
1259 // Please note that router and networks will be filled into VPNMaps
1260 // by subsequent calls here to associateRouterToVpn and
1261 // associateNetworksToVpn
1262 updateVpnMaps(vpnId, name, null, tenantId, null);
1263 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1264 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1267 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1268 for (Uuid routerId : routerIdsList) {
1269 associateRouterToVpn(vpnId, routerId);
1272 if (networkList != null) {
1273 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1274 if (!failStrings.isEmpty()) {
1275 LOG.error("VPN {} association to networks failed for networks: {}. ",
1276 vpnId.getValue(), failStrings);
1277 throw new Exception(failStrings.toString());
1283 * It handles the invocations to the createVPN RPC method.
1286 // TODO Clean up the exception handling
1287 @SuppressWarnings("checkstyle:IllegalCatch")
1288 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1290 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1291 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1292 List<RpcError> errorList = new ArrayList<>();
1293 int failurecount = 0;
1294 int warningcount = 0;
1296 List<L3vpn> vpns = input.getL3vpn();
1298 vpns = Collections.emptyList();
1300 for (L3vpn vpn : vpns) {
1301 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1302 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1303 formatAndLog(LOG::warn,
1304 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1305 vpn.getId().getValue())));
1309 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1310 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1311 formatAndLog(LOG::warn,
1312 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1313 vpn.getId().getValue())));
1318 if (vpn.getL3vni() != null) {
1319 l3vni = vpn.getL3vni().toJava();
1322 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1323 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1324 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1325 formatAndLog(LOG::warn,
1326 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1327 + "is already configured",
1328 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1332 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1333 if (operationalVpn.isPresent()) {
1334 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1335 formatAndLog(LOG::error,
1336 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1337 + "is still available. Please retry creation of a new vpn with the same RD"
1338 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1339 vpn.getRouteDistinguisher().get(0))));
1343 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1344 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
1345 .neutronvpn.rev150602.vpn.instance.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight
1346 .netvirt.neutronvpn.rev150602.vpn.instance.RouterIds> keyRouterIdsMap = vpn.getRouterIds();
1347 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1348 routerId : keyRouterIdsMap.values()) {
1349 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1350 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1351 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1352 + "{}", vpn.getId(), routerId.getRouterId())));
1356 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1357 if (vpnId != null) {
1358 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1359 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1360 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1361 vpnId.getValue())));
1367 if (vpn.getNetworkIds() != null) {
1368 int initialWarningCount = warningcount;
1369 for (Uuid nw : vpn.getNetworkIds()) {
1370 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1371 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1372 if (network == null) {
1373 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1374 formatAndLog(LOG::warn,
1375 "Creation of L3VPN failed for VPN {} due to network not found {}",
1376 vpn.getId().getValue(), nw.getValue())));
1378 } else if (vpnId != null) {
1379 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1380 formatAndLog(LOG::warn,
1381 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1382 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1383 vpnId.getValue())));
1387 if (warningcount != initialWarningCount) {
1391 List<Uuid> rtrIdsList = new ArrayList<>();
1392 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1393 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1394 rtrId : vpn.getRouterIds().values()) {
1395 rtrIdsList.add(rtrId.getRouterId());
1399 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1400 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1401 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1402 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1404 List<String> rdList = vpn.getRouteDistinguisher() != null
1405 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1406 List<String> importRdList = vpn.getImportRT() != null
1407 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1408 List<String> exportRdList = vpn.getExportRT() != null
1409 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1411 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1412 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
1413 } catch (Exception ex) {
1414 LOG.error("VPN Creation exception :", ex);
1415 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1416 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1421 // if at least one succeeds; result is success
1422 // if none succeeds; result is failure
1423 if (failurecount + warningcount == vpns.size()) {
1424 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1426 List<String> errorResponseList = new ArrayList<>();
1427 if (!errorList.isEmpty()) {
1428 for (RpcError rpcError : errorList) {
1429 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1430 + ", ErrorMessage: " + rpcError.getMessage());
1433 errorResponseList.add("Operation successful with no errors");
1435 opBuilder.setResponse(errorResponseList);
1436 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1442 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1445 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1447 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1448 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1449 Uuid inputVpnId = input.getId();
1450 List<VpnInstance> vpns = new ArrayList<>();
1451 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1454 if (inputVpnId == null) {
1456 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1458 Optional<VpnInstances> optionalVpns =
1459 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1461 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1462 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance().values()) {
1463 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1464 // from getL3VPN output
1465 if (vpn.getRouteDistinguisher() != null) {
1471 opBuilder.setL3vpnInstances(l3vpnList);
1472 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1476 String name = inputVpnId.getValue();
1477 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1478 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1479 // read VpnInstance Info
1480 Optional<VpnInstance> optionalVpn =
1481 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1483 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1485 if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
1486 vpns.add(optionalVpn.get());
1489 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1490 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1494 for (VpnInstance vpnInstance : vpns) {
1495 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1496 // create VpnMaps id
1497 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1498 List<String> rd = Collections.emptyList();
1499 if (vpnInstance.getRouteDistinguisher() != null) {
1500 rd = vpnInstance.getRouteDistinguisher();
1502 List<String> ertList = new ArrayList<>();
1503 List<String> irtList = new ArrayList<>();
1505 if (vpnInstance.getVpnTargets() != null) {
1506 Map<VpnTargetKey, VpnTarget> keyVpnTargetMap = Collections.emptyMap();
1507 if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
1508 keyVpnTargetMap = vpnInstance.getVpnTargets().getVpnTarget();
1510 if (!keyVpnTargetMap.isEmpty()) {
1511 for (VpnTarget vpnTarget : keyVpnTargetMap.values()) {
1512 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1513 ertList.add(vpnTarget.getVrfRTValue());
1515 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1516 irtList.add(vpnTarget.getVrfRTValue());
1518 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1519 ertList.add(vpnTarget.getVrfRTValue());
1520 irtList.add(vpnTarget.getVrfRTValue());
1526 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1528 if (vpnInstance.getL3vni() != null) {
1529 l3vpn.setL3vni(vpnInstance.getL3vni());
1531 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1532 .class, new VpnMapKey(vpnId)).build();
1533 Optional<VpnMap> optionalVpnMap =
1534 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1536 if (optionalVpnMap.isPresent()) {
1537 VpnMap vpnMap = optionalVpnMap.get();
1538 List<Uuid> rtrIds = new ArrayList<>();
1539 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1540 for (RouterIds rtrId : vpnMap.getRouterIds().values()) {
1541 rtrIds.add(rtrId.getRouterId());
1544 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1545 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1546 .setName(vpnMap.getName());
1549 l3vpnList.add(l3vpn.build());
1552 opBuilder.setL3vpnInstances(l3vpnList);
1553 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1555 } catch (ExecutionException | InterruptedException ex) {
1556 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1557 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1563 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1566 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1568 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1569 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1570 List<RpcError> errorList = new ArrayList<>();
1572 int failurecount = 0;
1573 int warningcount = 0;
1574 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1575 for (Uuid vpn : vpns) {
1577 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1578 InstanceIdentifier<VpnInstance> vpnIdentifier =
1579 InstanceIdentifier.builder(VpnInstances.class)
1580 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1581 Optional<VpnInstance> optionalVpn =
1582 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1584 if (optionalVpn.isPresent()) {
1587 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1588 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1591 } catch (ExecutionException | InterruptedException ex) {
1592 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1593 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1598 // if at least one succeeds; result is success
1599 // if none succeeds; result is failure
1600 if (failurecount + warningcount == vpns.size()) {
1601 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1603 List<String> errorResponseList = new ArrayList<>();
1604 if (!errorList.isEmpty()) {
1605 for (RpcError rpcError : errorList) {
1606 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1607 + ", ErrorMessage: " + rpcError.getMessage());
1610 errorResponseList.add("Operation successful with no errors");
1612 opBuilder.setResponse(errorResponseList);
1613 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1618 public void createVpnInstanceForSubnet(Uuid subnetId) {
1619 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1620 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1623 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1624 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1625 removeVpn(subnetId);
1628 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1629 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1630 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1631 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1633 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1634 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1637 if (vpnId != null) {
1638 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1639 if (vpnMap == null) {
1640 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1641 + " cannot add subnet {} to VPN", vpnId.getValue(),
1645 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1646 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1647 if (isVpnOfTypeL2(vpnInstance)) {
1648 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1649 NeutronEvpnUtils.Operation.ADD);
1652 if (internetVpnId != null) {
1653 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1654 if (vpnMap == null) {
1655 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1656 + "subnet {} to VPN", internetVpnId.getValue(),
1661 final Uuid internetId = internetVpnId;
1662 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1663 List<Uuid> portList = sn.getPortList();
1664 if (portList != null) {
1665 for (final Uuid portId : portList) {
1666 String vpnInfName = portId.getValue();
1667 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1668 Port port = neutronvpnUtils.getNeutronPort(portId);
1670 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1671 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1674 final Boolean isRouterInterface = port.getDeviceOwner()
1675 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1676 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1677 ListenableFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1679 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1681 if (vpnIface == null) {
1682 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1683 Set<Uuid> listVpn = new HashSet<>();
1684 if (vpnId != null) {
1687 if (internetId != null) {
1688 listVpn.add(internetId);
1690 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1691 isRouterInterface, wrtConfigTxn);
1692 if (sn.getRouterId() != null) {
1693 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1696 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1697 if (vpnId != null) {
1698 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1700 if (internetId != null) {
1701 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1705 LoggingFutures.addErrorLogging(future, LOG,
1706 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1707 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1708 return Collections.singletonList(future);
1714 protected void removeSubnetFromVpn(final Uuid vpnId, Subnetmap subnetmap, @Nullable Uuid internetVpnId) {
1715 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1716 "removeSubnetFromVpn: at least one VPN must be not null");
1717 Uuid subnetId = subnetmap.getId();
1718 LOG.debug("Removing subnet {} from vpn {}/{}", subnetId.getValue(),
1719 vpnId, internetVpnId);
1720 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnetId.getValue());
1721 VpnMap vpnMap = null;
1722 VpnInstance vpnInstance = null;
1723 if (vpnId != null) {
1724 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1725 if (vpnMap == null) {
1726 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1727 vpnId.getValue(), subnetId.getValue());
1730 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1732 if (internetVpnId == null) {
1733 internetVpnId = subnetmap.getInternetVpnId();
1735 if (internetVpnId != null) {
1736 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1737 if (vpnMap == null) {
1738 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1739 + " from Internet VPN",
1740 internetVpnId.getValue(), subnetId.getValue());
1744 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1745 neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(),
1746 NeutronEvpnUtils.Operation.DELETE);
1748 boolean subnetVpnAssociation = false;
1749 if (vpnId != null && subnetmap.getVpnId() != null
1750 && subnetmap.getVpnId().getValue().equals(vpnId.getValue())) {
1751 subnetVpnAssociation = true;
1752 } else if (internetVpnId != null && subnetmap.getInternetVpnId() != null
1753 && subnetmap.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1754 subnetVpnAssociation = true;
1756 if (subnetVpnAssociation == false) {
1757 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1758 vpnId, internetVpnId, subnetmap.getVpnId(), subnetmap.getInternetVpnId());
1761 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1762 List<Uuid> portList = subnetmap.getPortList();
1763 final Uuid internetId = internetVpnId;
1764 if (portList != null) {
1765 for (final Uuid portId : portList) {
1766 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", subnetmap.getSubnetIp(), portId.getValue());
1767 final Port port = neutronvpnUtils.getNeutronPort(portId);
1768 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1769 List<ListenableFuture<?>> futures = new ArrayList<>();
1770 ListenableFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1771 CONFIGURATION, tx -> {
1773 withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx);
1775 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1776 + " port is absent in Neutron config DS", portId.getValue(),
1777 subnetId.getValue());
1780 LoggingFutures.addErrorLogging(future, LOG,
1781 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1782 + " belonging to subnet {} and vpnId {}",
1783 portId.getValue(), subnetId.getValue(), vpnId.getValue());
1784 futures.add(future);
1789 //update subnet-vpn association
1790 removeFromSubnetNode(subnetId, null, null, vpnId, null);
1793 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1794 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1795 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1797 Uuid internalVpnId = sm.getVpnId();
1798 if (internalVpnId == null) {
1799 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1800 sm.getId().getValue());
1803 if (isBeingAssociated) {
1804 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1806 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1809 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1810 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1811 if (isBeingAssociated) {
1812 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1813 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1815 removeInternetVpnFromVpnInterface(vpn,
1816 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1821 // Check for ports on this subnet and update association of
1822 // corresponding vpn-interfaces to internet vpn
1823 List<Uuid> portList = sm.getPortList();
1824 if (portList != null) {
1825 for (Uuid port : portList) {
1826 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1827 port.getValue(), isBeingAssociated);
1828 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1829 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1831 if (isBeingAssociated) {
1832 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1833 true, false, tx, true);
1835 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1843 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1844 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1845 oldVpnId.getValue(), newVpnId.getValue());
1846 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1847 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1848 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1849 Uuid vpnExtUuid = netIsExternal ? neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet) : null;
1850 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1852 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1855 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1856 * associated with internet BGP-VPN.
1858 if (vpnExtUuid != null) {
1859 /* Update V6 Internet default route match with new VPN metadata.
1860 * isBeingAssociated = true means oldVpnId is same as routerId
1861 * isBeingAssociated = false means newVpnId is same as routerId
1863 if (isBeingAssociated) {
1864 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1866 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1869 //Update Router Interface first synchronously.
1870 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1871 ListenableFuture<?> future =
1872 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1873 tx -> updateVpnInterface(newVpnId, oldVpnId,
1874 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1875 isBeingAssociated, true, tx, false));
1876 Futures.addCallback(future, new FutureCallback<Object>() {
1878 public void onSuccess(Object result) {
1879 // Check for ports on this subnet and update association of
1880 // corresponding vpn-interfaces to external vpn
1881 List<Uuid> portList = sn.getPortList();
1882 if (portList != null) {
1883 for (Uuid port : portList) {
1884 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1885 port.getValue(), isBeingAssociated);
1886 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1887 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1888 tx -> updateVpnInterface(newVpnId, oldVpnId,
1889 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1896 public void onFailure(Throwable throwable) {
1898 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1900 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1902 }, MoreExecutors.directExecutor());
1907 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1908 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1909 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1912 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1913 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1914 final ReentrantLock lock = lockForUuid(routerId);
1917 Optional<RouterInterfaces> optRouterInterfaces =
1918 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1919 routerInterfacesId);
1920 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1921 .setInterfaceId(interfaceName).build();
1922 if (optRouterInterfaces.isPresent()) {
1923 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1924 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1926 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1927 List<Interfaces> interfaces = new ArrayList<>();
1928 interfaces.add(routerInterface);
1929 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1930 routerInterfacesId, builder.setInterfaces(interfaces).build());
1932 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1933 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1939 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1940 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1941 final ReentrantLock lock = lockForUuid(routerId);
1944 Optional<RouterInterfaces> optRouterInterfaces =
1945 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1946 routerInterfacesId);
1947 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1948 .setInterfaceId(interfaceName).build();
1949 if (optRouterInterfaces.isPresent()) {
1950 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1951 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces().values());
1952 if (interfaces != null && interfaces.remove(routerInterface)) {
1953 if (interfaces.isEmpty()) {
1954 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1955 routerInterfacesId);
1957 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1958 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1962 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1963 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1970 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1971 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1972 * route will be ignored.
1974 * @param vpnName the VPN identifier
1975 * @param interVpnLinkRoutes The list of static routes
1976 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1978 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1979 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1980 for (Routes route : interVpnLinkRoutes) {
1981 String nexthop = route.getNexthop().stringValue();
1982 String destination = route.getDestination().stringValue();
1983 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1984 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1985 AddStaticRouteInput rpcInput =
1986 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1987 .setVpnInstanceName(vpnName.getValue())
1989 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1990 RpcResult<AddStaticRouteOutput> rpcResult;
1992 rpcResult = labelOuputFtr.get();
1993 if (rpcResult.isSuccessful()) {
1994 LOG.debug("Label generated for destination {} is: {}",
1995 destination, rpcResult.getResult().getLabel());
1997 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1998 destination, nexthop, rpcResult.getErrors());
2000 } catch (InterruptedException | ExecutionException e) {
2001 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
2002 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
2005 // Any other case is a fault.
2006 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2007 route.getDestination().stringValue(), nexthop);
2014 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2015 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2017 * @param vpnName the VPN identifier
2018 * @param interVpnLinkRoutes The list of static routes
2019 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2021 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2022 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2023 for (Routes route : interVpnLinkRoutes) {
2024 String nexthop = route.getNexthop().stringValue();
2025 String destination = route.getDestination().stringValue();
2026 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2027 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2028 RemoveStaticRouteInput rpcInput =
2029 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2030 .setVpnInstanceName(vpnName.getValue())
2033 LoggingFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2034 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2036 // Any other case is a fault.
2037 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2038 route.getDestination().stringValue(), nexthop);
2045 * Returns true if the specified nexthop is the other endpoint in an
2046 * InterVpnLink, regarding one of the VPN's point of view.
2048 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2049 InterVpnLink interVpnLink) {
2051 interVpnLink != null
2052 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2053 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2054 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2055 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2059 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2060 List<Adjacency> adjList = new ArrayList<>();
2061 Map<String, List<String>> adjMap = new HashMap<>();
2062 for (Routes route : routeList) {
2063 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2064 LOG.error("Incorrect input received for extra route. {}", route);
2066 String nextHop = route.getNexthop().stringValue();
2067 String destination = route.getDestination().stringValue();
2068 if (!nextHop.equals(fixedIp)) {
2069 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2072 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2074 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2075 if (!hops.contains(nextHop)) {
2081 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2082 final String destination = entry.getKey();
2083 final List<String> ipList = entry.getValue();
2084 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2085 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2086 .withKey(new AdjacencyKey(destination)).build();
2092 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2093 checkAlarmExtraRoutes(vpnId, routeList);
2095 for (Routes route : routeList) {
2096 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2097 LOG.error("Incorrect input received for extra route. {}", route);
2099 String nextHop = route.getNexthop().stringValue();
2100 String destination = route.getDestination().stringValue();
2101 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2103 if (infName != null) {
2104 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2105 destination, vpnId.getValue(), nextHop, infName);
2106 boolean isLockAcquired = false;
2108 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2109 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2110 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2111 .child(Adjacency.class, new AdjacencyKey(destination));
2112 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2113 LogicalDatastoreType.CONFIGURATION, path);
2114 if (existingAdjacency.isPresent()
2115 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2116 LOG.error("The route with destination {} nextHop {} is already present as"
2117 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2118 destination, nextHop, infName);
2121 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2122 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2123 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2125 try (AcquireResult lock = tryInterfaceLock(infName)) {
2126 if (!lock.wasAcquired()) {
2127 // FIXME: why do we even bother with locking if we do not honor it?!
2128 logTryLockFailure(infName);
2131 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2134 } catch (TransactionCommitFailedException e) {
2135 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2136 destination, nextHop, e);
2137 } catch (ExecutionException | InterruptedException e) {
2138 LOG.error("Exception on reading data-store ", e);
2141 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2142 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2149 * This method setup or down an alarm about extra route fault.
2150 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2151 * available RDs, then an alarm and an error is generated.<br>
2152 * <b>Be careful</b> the routeList could be changed.
2154 * @param vpnId the vpnId of vpn to control.
2155 * @param routeList the list of router to check, it could be modified.
2157 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2158 if (!neutronvpnAlarm.isAlarmEnabled()) {
2159 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2162 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(vpnId);
2163 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2164 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2168 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2169 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2170 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2174 for (Routes route : routeList) {
2175 // count the number of nexthops for each same route.getDestingation().getValue()
2176 String destination = route.getDestination().stringValue();
2177 String nextHop = route.getNexthop().stringValue();
2178 List<String> nextHopList = new ArrayList<>();
2179 nextHopList.add(nextHop);
2181 for (Routes routeTmp : routeList) {
2182 String routeDest = routeTmp.getDestination().stringValue();
2183 if (!destination.equals(routeDest)) {
2186 String routeNextH = routeTmp.getNexthop().stringValue();
2187 if (nextHop.equals(routeNextH)) {
2191 nextHopList.add(routeTmp.getNexthop().stringValue());
2193 final List<String> rdList = new ArrayList<>();
2194 if (vpnInstance != null
2195 && vpnInstance.getRouteDistinguisher() != null) {
2196 vpnInstance.getRouteDistinguisher().forEach(rd -> {
2202 // 1. VPN Instance Name
2203 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2206 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2207 Uuid routerUuid = routerUuidList.get(0);
2208 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2209 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2211 // 3. List of RDs associated with the VPN
2212 detailsAlarm.append(" List of RDs associated with the VPN: ");
2213 for (String s : rdList) {
2214 detailsAlarm.append(s);
2215 detailsAlarm.append(", ");
2218 // 4. Prefix in question
2219 detailsAlarm.append(" for prefix: ");
2220 detailsAlarm.append(route.getDestination().stringValue());
2222 // 5. List of NHs for the prefix
2223 detailsAlarm.append(" for nextHops: ");
2224 for (String s : nextHopList) {
2225 detailsAlarm.append(s);
2226 detailsAlarm.append(", ");
2229 if (rdList.size() < nbNextHops) {
2230 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2232 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2237 // TODO Clean up the exception handling
2238 @SuppressWarnings("checkstyle:IllegalCatch")
2239 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2240 for (Routes route : routeList) {
2241 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2242 String nextHop = route.getNexthop().stringValue();
2243 String destination = route.getDestination().stringValue();
2244 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2246 if (infName == null) {
2247 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2248 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2249 // Proceed to remove the next extra-route
2252 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2253 destination, vpnId.getValue(), nextHop, infName);
2255 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2256 InstanceIdentifier.builder(VpnInterfaces.class)
2257 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2258 .augmentation(Adjacencies.class)
2259 .child(Adjacency.class, new AdjacencyKey(destination))
2263 // Looking for existing prefix in MDSAL database
2264 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2265 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2266 boolean updateNextHops = false;
2267 List<String> nextHopList = new ArrayList<>();
2268 if (adjacency.isPresent()) {
2269 List<String> nhListRead = adjacency.get().getNextHopIpList();
2270 if (nhListRead.size() > 1) { // ECMP case
2271 for (String nextHopRead : nhListRead) {
2272 if (nextHopRead.equals(nextHop)) {
2273 updateNextHops = true;
2275 nextHopList.add(nextHopRead);
2281 try (AcquireResult lock = tryInterfaceLock(infName)) {
2282 if (!lock.wasAcquired()) {
2283 // FIXME: why do we even bother with locking if we do not honor it?!
2284 logTryLockFailure(infName);
2287 if (updateNextHops) {
2288 // An update must be done, not including the current next hop
2289 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2290 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2291 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2292 .setNextHopIpList(nextHopList)
2293 .withKey(new AdjacencyKey(destination))
2295 List<Adjacency> newAdjList = Collections.singletonList(newAdj);
2296 Adjacencies erAdjs =
2297 new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(newAdjList)).build();
2298 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2299 .addAugmentation(erAdjs).build();
2300 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2301 vpnIfIdentifier, vpnIf);
2303 // Remove the whole route
2304 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2305 adjacencyIdentifier);
2306 LOG.trace("extra route {} deleted successfully", route);
2309 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
2310 LOG.error("exception in deleting extra route with destination {} for interface {}",
2311 destination, infName, e);
2314 LOG.error("Incorrect input received for extra route: {}", route);
2319 public void removeVpn(Uuid vpnId) {
2321 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2322 if (vpnMap != null) {
2323 Map<RouterIdsKey, RouterIds> keyRouterIdsMap = vpnMap.getRouterIds();
2324 List<Uuid> routerUuidList = new ArrayList<>();
2325 // dissociate router
2326 if (keyRouterIdsMap != null && !keyRouterIdsMap.isEmpty()) {
2327 for (RouterIds router : keyRouterIdsMap.values()) {
2328 Uuid routerId = router.getRouterId();
2329 routerUuidList.add(routerId);
2330 dissociateRouterFromVpn(vpnId, routerId);
2333 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2334 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2337 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2339 // remove entire vpnMaps node
2340 deleteVpnMapsNode(vpnId);
2342 // remove vpn-instance
2343 deleteVpnInstance(vpnId);
2344 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2347 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2348 return vpnInstance != null && vpnInstance.isL2vpn();
2351 // TODO Clean up the exception handling
2352 @SuppressWarnings("checkstyle:IllegalCatch")
2353 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2354 updateVpnMaps(vpnId, null, routerId, null, null);
2355 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2356 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2357 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2358 for (Subnetmap sn : subMapList) {
2359 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2360 if (!ipVersion.isIpVersionChosen(ipVers)) {
2361 ipVersion = ipVersion.addVersion(ipVers);
2364 if (ipVersion != IpVersionChoice.UNDEFINED) {
2365 LOG.debug("associateRouterToVpn: Updating vpnInstance ip address family {} for VPN {} ",
2367 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2369 for (Subnetmap sn : subMapList) {
2370 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2374 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2375 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2376 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2377 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2378 for (Uuid subnet : routerSubnets) {
2379 IpVersionChoice version = NeutronvpnUtils
2380 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2381 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2382 addSubnetToVpn(vpnId, subnet, null);
2384 addSubnetToVpn(vpnId, subnet, internetVpnId);
2389 // TODO Clean up the exception handling
2390 @SuppressWarnings("checkstyle:IllegalCatch")
2391 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2393 clearFromVpnMaps(vpnId, routerId, null);
2394 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2395 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2396 for (Subnetmap sn : subMapList) {
2397 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2398 if (ipVersion.isIpVersionChosen(ipVers)) {
2399 ipVersion = ipVersion.addVersion(ipVers);
2401 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2402 routerId.getValue());
2403 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2405 if (ipVersion != IpVersionChoice.UNDEFINED) {
2406 LOG.debug("dissociateRouterFromVpn; Updating vpnInstance with ip address family {} for VPN {} ",
2408 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2414 * Parses and associates networks list with given VPN.
2416 * @param vpnId Uuid of given VPN.
2417 * @param networkList List list of network Ids (Uuid), which will be associated.
2418 * @return list of formatted strings with detailed error messages.
2421 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2422 List<String> failedNwList = new ArrayList<>();
2423 HashSet<Uuid> passedNwList = new HashSet<>();
2424 ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
2425 boolean isExternalNetwork = false;
2426 if (networkList.isEmpty()) {
2427 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2428 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2430 return failedNwList;
2432 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2433 if (vpnInstance == null) {
2434 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2435 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2436 + "in ConfigDS", vpnId.getValue()));
2437 return failedNwList;
2440 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2441 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2443 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2444 + "associated with", vpnId.getValue()));
2445 return failedNwList;
2447 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2448 boolean isIpFamilyUpdated = false;
2449 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2450 for (Uuid nw : networkList) {
2451 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2452 if (network == null) {
2453 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2454 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2458 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2459 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2460 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2461 nw.getValue(), vpnId.getValue());
2462 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2463 nw.getValue(), vpnId.getValue()));
2466 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2467 if (networkVpnId != null) {
2468 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2469 nw.getValue(), networkVpnId.getValue());
2470 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2471 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2474 /* Handle association of external network(s) to Internet BGP-VPN use case outside of the
2475 * networkList iteration
2477 if (neutronvpnUtils.getIsExternal(network)) {
2478 extNwMap.put(nw, network);
2479 isExternalNetwork = true;
2480 //Check whether router-gw is set with external network before external network to BGPVPN association
2481 List<Uuid> routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw);
2482 if (!routerList.isEmpty()) {
2483 for (Uuid routerId : routerList) {
2484 //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance
2485 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
2486 ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6);
2487 LOG.debug("associateNetworksToVpn: External network {} is already associated with "
2488 + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 "
2489 + "address family type in Internet VPN Instance {}", network, routerId, vpnId);
2495 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2496 if (subnetmapList == null || subnetmapList.isEmpty()) {
2497 passedNwList.add(nw);
2500 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2503 for (Subnetmap subnetmap : subnetmapList) {
2504 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2505 if (!ipVersion.isIpVersionChosen(ipVers)) {
2506 ipVersion = ipVersion.addVersion(ipVers);
2509 //Update vpnInstance for IP address family
2510 if (ipVersion != IpVersionChoice.UNDEFINED && !isIpFamilyUpdated) {
2511 LOG.debug("associateNetworksToVpn: Updating vpnInstance with ip address family {}"
2512 + " for VPN {} ", ipVersion, vpnId);
2513 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2514 isIpFamilyUpdated = true;
2516 for (Subnetmap subnetmap : subnetmapList) {
2517 Uuid subnetId = subnetmap.getId();
2518 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2519 if (subnetVpnId != null) {
2520 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2521 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2522 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2523 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2526 if (!NeutronvpnUtils.getIsExternal(network)) {
2527 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2529 addSubnetToVpn(vpnId, subnetId, null);
2530 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2532 passedNwList.add(nw);
2535 passedNwList.add(nw);
2536 //Handle association of external network(s) to Internet BGP-VPN Instance use case
2537 if (!extNwMap.isEmpty() || extNwMap != null) {
2538 for (Network extNw : extNwMap.values()) {
2539 if (!associateExtNetworkToVpn(vpnId, extNw, vpnInstance.getBgpvpnType())) {
2540 LOG.error("associateNetworksToVpn: Failed to associate Provider External Network {} with "
2541 + "VPN {}", extNw, vpnId.getValue());
2542 failedNwList.add(String.format("Failed to associate Provider External Network %s with "
2543 + "VPN %s", extNw, vpnId.getValue()));
2549 } catch (ExecutionException | InterruptedException e) {
2550 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2552 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2555 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2556 if (!isExternalNetwork) {
2557 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2559 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2560 return failedNwList;
2563 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet,
2564 VpnInstance.BgpvpnType bgpVpnType) {
2565 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2568 if (!bgpVpnType.equals(VpnInstance.BgpvpnType.InternetBGPVPN)) {
2569 LOG.info("associateExtNetworkToVpn: External network {} is associated to VPN {}."
2570 + "Hence set vpnInstance type to {} from {} ", extNet.key().getUuid().getValue(),
2571 vpnId.getValue(), VpnInstance.BgpvpnType.InternetBGPVPN.getName(),
2572 VpnInstance.BgpvpnType.BGPVPN.getName());
2573 neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.InternetBGPVPN, vpnId);
2575 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2576 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2577 updateVpnMaps(vpnId, null, null, null, extNwList);
2578 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2579 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2580 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2582 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2585 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2586 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2589 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2590 updateVpnInternetForSubnet(sm, vpnId, true);
2592 if (!ipVersion.isIpVersionChosen(ipVers)) {
2593 ipVersion = ipVersion.addVersion(ipVers);
2596 if (ipVersion != IpVersionChoice.UNDEFINED) {
2597 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2598 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2599 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2605 * Parses and disassociates networks list from given VPN.
2607 * @param vpnId Uuid of given VPN.
2608 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2609 * @return list of formatted strings with detailed error messages.
2612 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2613 List<String> failedNwList = new ArrayList<>();
2614 HashSet<Uuid> passedNwList = new HashSet<>();
2615 ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
2616 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2617 if (networkList.isEmpty()) {
2618 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2619 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2621 return failedNwList;
2623 for (Uuid nw : networkList) {
2624 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2625 if (networkSubnets == null) {
2626 passedNwList.add(nw);
2629 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2630 if (network == null) {
2631 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2632 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2636 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2637 if (networkVpnId == null) {
2638 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2639 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2643 if (!vpnId.equals(networkVpnId)) {
2644 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2645 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2646 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2647 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2651 /* Handle disassociation of external network(s) from Internet BGP-VPN use case outside of the
2652 * networkList iteration
2654 if (neutronvpnUtils.getIsExternal(network)) {
2655 extNwMap.put(nw, network);
2656 //Handle external-Nw to BGPVPN Disassociation and still ext-router is being set with external-Nw
2657 List<Uuid> routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw);
2658 if (!routerList.isEmpty()) {
2659 for (Uuid routerId : routerList) {
2660 //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance
2661 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
2662 ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6);
2663 LOG.debug("dissociateNetworksFromVpn: External network {} is still associated with "
2664 + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 "
2665 + "address family type in Internet VPN Instance {}", network, routerId, vpnId);
2671 for (Uuid subnet : networkSubnets) {
2672 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2673 if (subnetmap == null) {
2674 failedNwList.add(String.format("subnetmap %s not found for network %s",
2675 subnet.getValue(), nw.getValue()));
2676 LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when "
2677 + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(),
2681 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2682 if (!ipVersion.isIpVersionChosen(ipVers)) {
2683 ipVersion = ipVersion.addVersion(ipVers);
2685 if (!NeutronvpnUtils.getIsExternal(network)) {
2686 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2688 removeSubnetFromVpn(vpnId, subnetmap, null);
2689 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2690 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2692 passedNwList.add(nw);
2695 if (ipVersion != IpVersionChoice.UNDEFINED) {
2696 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstance with ip address family {}"
2697 + " for VPN {}", ipVersion, vpnId);
2698 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2701 //Handle disassociation of external network(s) from Internet BGP-VPN Instance use case
2702 if (!extNwMap.isEmpty() || extNwMap != null) {
2703 for (Network extNw : extNwMap.values()) {
2704 if (disassociateExtNetworkFromVpn(vpnId, extNw)) {
2705 passedNwList.add(extNw.getUuid());
2707 LOG.error("dissociateNetworksFromVpn: Failed to withdraw External Provider Network {} from VPN {}",
2708 extNw, vpnId.getValue());
2709 failedNwList.add(String.format("Failed to withdraw External Provider Network %s from VPN %s",
2710 extNw, vpnId.getValue()));
2715 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2716 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2717 passedNwList, vpnId.getValue());
2718 return failedNwList;
2721 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2722 if (!removeExternalNetworkFromVpn(extNet)) {
2725 // check, if there is another Provider Networks associated with given VPN
2726 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2727 if (vpnNets != null) {
2728 //Remove currently disassociated network from the list
2729 vpnNets.remove(extNet.getUuid());
2730 for (Uuid netId : vpnNets) {
2731 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2732 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2733 + "{}", vpnId.getValue(), netId.getValue());
2738 ///Set VPN Type is BGPVPN from InternetBGPVPN
2739 LOG.info("disassociateExtNetworkFromVpn: Set BGP-VPN type with {} for VPN {} and update IPv6 address family. "
2740 + "Since external network is disassociated from VPN {}",
2741 VpnInstance.BgpvpnType.BGPVPN, extNet, vpnId.getValue());
2742 neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.BGPVPN, vpnId);
2743 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2744 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2745 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2747 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2750 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2751 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2754 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2755 updateVpnInternetForSubnet(sm, vpnId, false);
2757 if (!ipVersion.isIpVersionChosen(ipVers)) {
2758 ipVersion = ipVersion.addVersion(ipVers);
2761 if (ipVersion != IpVersionChoice.UNDEFINED) {
2762 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2763 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2765 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2771 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2774 // TODO Clean up the exception handling
2775 @SuppressWarnings("checkstyle:IllegalCatch")
2776 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2778 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2779 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2780 StringBuilder returnMsg = new StringBuilder();
2781 Uuid vpnId = input.getVpnId();
2784 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2785 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2786 input.getNetworkId());
2787 List<Uuid> netIds = input.getNetworkId();
2788 if (netIds != null && !netIds.isEmpty()) {
2789 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2790 if (!failed.isEmpty()) {
2791 returnMsg.append(failed);
2795 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2797 if (returnMsg.length() != 0) {
2798 opBuilder.setResponse(
2799 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2800 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2801 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2803 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2805 } catch (Exception ex) {
2806 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2807 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2808 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2809 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2811 LOG.debug("associateNetworks returns..");
2816 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2819 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2821 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2822 LOG.debug("associateRouter {}", input);
2823 StringBuilder returnMsg = new StringBuilder();
2824 Uuid vpnId = input.getVpnId();
2825 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter
2826 .input.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2827 .associaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2828 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "associateRouter: RouterIds list is empty!");
2829 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2830 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2831 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2832 .RouterIds routerId : keyRouterIdsMap.values()) {
2833 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2834 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2835 if (vpnMap != null) {
2837 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2838 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2839 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2840 .append(routerId.getRouterId());
2841 } else if (extVpnId != null) {
2842 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2843 + "another VPN ").append(extVpnId.getValue());
2845 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2846 routerId.getRouterId());
2847 associateRouterToVpn(vpnId, routerId.getRouterId());
2850 returnMsg.append("router not found : ").append(routerId.getRouterId());
2853 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2855 if (returnMsg.length() != 0) {
2856 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2857 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2858 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2860 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2863 LOG.debug("associateRouter returns..");
2868 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2871 // TODO Clean up the exception handling
2872 @SuppressWarnings("checkstyle:IllegalCatch")
2873 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2874 GetFixedIPsForNeutronPortInput input) {
2875 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2876 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2877 Uuid portId = input.getPortId();
2878 StringBuilder returnMsg = new StringBuilder();
2880 List<String> fixedIPList = new ArrayList<>();
2881 Port port = neutronvpnUtils.getNeutronPort(portId);
2883 for (FixedIps ip : port.nonnullFixedIps().values()) {
2884 fixedIPList.add(ip.getIpAddress().stringValue());
2887 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2889 if (returnMsg.length() != 0) {
2890 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2892 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2893 returnMsg)).build());
2895 opBuilder.setFixedIPs(fixedIPList);
2896 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2898 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2900 } catch (Exception ex) {
2901 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2902 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2903 portId.getValue(), ex.getMessage(), ex)).build());
2909 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2912 // TODO Clean up the exception handling
2913 @SuppressWarnings("checkstyle:IllegalCatch")
2914 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2916 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2917 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2919 LOG.debug("dissociateNetworks {}", input);
2920 StringBuilder returnMsg = new StringBuilder();
2921 Uuid vpnId = input.getVpnId();
2924 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2925 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2926 input.getNetworkId());
2927 List<Uuid> netIds = input.getNetworkId();
2928 if (netIds != null && !netIds.isEmpty()) {
2929 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2930 if (!failed.isEmpty()) {
2931 returnMsg.append(failed);
2935 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2937 if (returnMsg.length() != 0) {
2938 opBuilder.setResponse(
2939 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2940 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2942 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2944 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2946 } catch (Exception ex) {
2947 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2948 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2949 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2951 LOG.debug("dissociateNetworks returns..");
2956 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2959 // TODO Clean up the exception handling
2960 @SuppressWarnings("checkstyle:IllegalCatch")
2961 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2963 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2965 LOG.debug("dissociateRouter {}", input);
2966 StringBuilder returnMsg = new StringBuilder();
2967 Uuid vpnId = input.getVpnId();
2968 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2969 .RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2970 .dissociaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2971 String routerIdsString = "";
2972 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2973 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2974 Preconditions.checkNotNull(keyRouterIdsMap, "dissociateRouter: keyRouterIdsMap not found!");
2975 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2976 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2977 .RouterIds routerId : keyRouterIdsMap.values()) {
2979 if (routerId != null) {
2980 routerIdsString += routerId.getRouterId() + ", ";
2981 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2983 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2984 if (routerVpnId == null) {
2985 returnMsg.append("input router ").append(routerId.getRouterId())
2986 .append(" not associated to any vpn yet");
2987 } else if (vpnId.equals(routerVpnId)) {
2988 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2990 returnMsg.append("input router ").append(routerId.getRouterId())
2991 .append(" associated to vpn ")
2992 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2995 returnMsg.append("router not found : ").append(routerId.getRouterId());
2998 if (returnMsg.length() != 0) {
2999 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
3000 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
3001 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
3002 returnMsg)).build());
3004 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
3006 } catch (Exception ex) {
3007 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
3008 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
3009 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
3013 returnMsg.append("VPN not found : ").append(vpnId.getValue());
3016 LOG.debug("dissociateRouter returns..");
3020 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
3021 // check if the router is associated to some VPN
3022 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
3023 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
3024 if (vpnId != null) {
3025 // remove existing external vpn interfaces
3026 for (Uuid subnetId : routerSubnetIds) {
3027 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
3028 if (subnetmap != null) {
3029 removeSubnetFromVpn(vpnId, subnetmap, internetVpnId);
3031 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
3032 subnetId, routerId.getValue());
3035 clearFromVpnMaps(vpnId, routerId, null);
3037 // remove existing internal vpn interfaces
3038 for (Uuid subnetId : routerSubnetIds) {
3039 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
3040 if (subnetmap != null) {
3041 removeSubnetFromVpn(routerId, subnetmap, internetVpnId);
3043 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
3044 subnetId, routerId.getValue());
3048 // delete entire vpnMaps node for internal VPN
3049 deleteVpnMapsNode(routerId);
3051 // delete vpn-instance for internal VPN
3052 deleteVpnInstance(routerId);
3055 protected Subnet getNeutronSubnet(Uuid subnetId) {
3056 return neutronvpnUtils.getNeutronSubnet(subnetId);
3060 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
3061 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
3063 return sn.getGatewayIp();
3069 protected Network getNeutronNetwork(Uuid networkId) {
3070 return neutronvpnUtils.getNeutronNetwork(networkId);
3073 protected Port getNeutronPort(String name) {
3074 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3077 protected Port getNeutronPort(Uuid portId) {
3078 return neutronvpnUtils.getNeutronPort(portId);
3081 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3082 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3085 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3086 return neutronvpnUtils.getNetworksForVpn(vpnId);
3090 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3092 * @return a List of String to be printed on screen
3093 * @throws ExecutionException or InterruptedException if there was a problem reading from the data store
3095 public List<String> showNeutronPortsCLI() throws ExecutionException, InterruptedException {
3096 List<String> result = new ArrayList<>();
3097 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3099 result.add("-------------------------------------------------------------------------------------------");
3100 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3102 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3103 if (ports.isPresent() && ports.get().getPort() != null) {
3104 for (Port port : ports.get().nonnullPort().values()) {
3105 Map<FixedIpsKey, FixedIps> keyFixedIpsMap = port.getFixedIps();
3106 if (keyFixedIpsMap != null && !keyFixedIpsMap.isEmpty()) {
3107 List<String> ipList = new ArrayList<>();
3108 for (FixedIps fixedIp : keyFixedIpsMap.values()) {
3109 IpAddress ipAddress = fixedIp.getIpAddress();
3110 if (ipAddress.getIpv4Address() != null) {
3111 ipList.add(ipAddress.getIpv4Address().getValue());
3113 ipList.add(ipAddress.getIpv6Address().getValue());
3116 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3117 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3118 ipList.toString()));
3120 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3121 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3130 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3132 * @param vpnuuid Uuid of the VPN whose config must be shown
3133 * @return formatted output list
3134 * @throws InterruptedException if there was a thread related problem getting the data to display
3135 * @throws ExecutionException if there was any other problem getting the data to display
3137 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3138 List<String> result = new ArrayList<>();
3139 if (vpnuuid == null) {
3141 result.add("Displaying VPN config for all VPNs");
3142 result.add("To display VPN config for a particular VPN, use the following syntax");
3143 result.add(getshowVpnConfigCLIHelp());
3145 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3146 if (rpcResult.isSuccessful()) {
3148 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3150 result.add(String.format(" %-80s ", "Import-RTs"));
3152 result.add(String.format(" %-80s ", "Export-RTs"));
3154 result.add(String.format(" %-76s ", "Subnet IDs"));
3156 result.add("------------------------------------------------------------------------------------");
3158 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3159 rpcResult.getResult().nonnullL3vpnInstances()) {
3160 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3162 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3163 vpn.getRouteDistinguisher()));
3165 result.add(String.format(" %-80s ", vpn.getImportRT()));
3167 result.add(String.format(" %-80s ", vpn.getExportRT()));
3170 Uuid vpnid = vpn.getId();
3171 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3172 if (!subnetList.isEmpty()) {
3173 for (Uuid subnetuuid : subnetList) {
3174 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3177 result.add(String.format(" %-76s ", "\" \""));
3180 result.add("----------------------------------------");
3184 String errortag = rpcResult.getErrors().iterator().next().getTag();
3185 if (Objects.equals(errortag, "")) {
3187 result.add("No VPN has been configured yet");
3188 } else if (Objects.equals(errortag, "invalid-value")) {
3190 result.add("VPN " + vpnuuid.getValue() + " is not present");
3192 result.add("error getting VPN info : " + rpcResult.getErrors());
3193 result.add(getshowVpnConfigCLIHelp());
3199 protected void createExternalVpnInterfaces(Uuid extNetId) {
3200 if (extNetId == null) {
3201 LOG.error("createExternalVpnInterfaces: external network is null");
3205 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3206 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3207 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3211 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3212 for (String elanInterface : extElanInterfaces) {
3213 createExternalVpnInterface(extNetId, elanInterface, tx);
3215 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3218 // TODO Clean up the exception handling
3219 @SuppressWarnings("checkstyle:IllegalCatch")
3220 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3221 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3222 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3223 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3226 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3227 for (String elanInterface : extElanInterfaces) {
3228 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3229 .buildVpnInterfaceIdentifier(elanInterface);
3230 LOG.info("Removing vpn interface {}", elanInterface);
3231 tx.delete(vpnIfIdentifier);
3233 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3236 private void createExternalVpnInterface(Uuid vpnId, String infName,
3237 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3238 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3239 false /* not a router iface */, wrtConfigTxn);
3242 // TODO Clean up the exception handling
3243 @SuppressWarnings("checkstyle:IllegalCatch")
3244 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3245 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3246 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3247 if (vpnIdList.isEmpty() || infName == null) {
3248 LOG.error("vpnid is empty or interface({}) is null", infName);
3251 if (wrtConfigTxn == null) {
3252 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3253 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3254 "Error writing VPN interface");
3257 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3258 for (Uuid vpnId: vpnIdList) {
3259 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3260 AssociatedSubnetType.V4AndV6Subnets);
3261 vpnIdListStruct.add(vpnInstance);
3264 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3265 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3267 .setVpnInstanceNames(vpnIdListStruct)
3268 .setRouterInterface(isRouterInterface);
3269 LOG.info("Network Id is {}", networkUuid);
3270 if (networkUuid != null) {
3271 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3272 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3273 NetworkAttributes.NetworkType networkType = providerType != null
3274 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3275 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3276 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3277 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3280 if (adjacencies != null) {
3281 vpnb.addAugmentation(adjacencies);
3283 VpnInterface vpnIf = vpnb.build();
3285 LOG.info("Creating vpn interface {}", vpnIf);
3286 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3287 } catch (Exception ex) {
3288 LOG.error("Creation of vpninterface {} failed", infName, ex);
3292 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3293 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3294 if (vpnId == null || infName == null) {
3295 LOG.error("vpn id or interface is null");
3298 if (wrtConfigTxn == null) {
3299 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3300 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3301 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3302 }), LOG, "Error updating VPN interface with adjacencies");
3306 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3308 try (AcquireResult lock = tryInterfaceLock(infName)) {
3309 if (!lock.wasAcquired()) {
3310 // FIXME: why do we even bother with locking if we do not honor it?!
3311 logTryLockFailure(infName);
3315 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3316 .syncReadOptional(dataBroker, LogicalDatastoreType
3317 .CONFIGURATION, vpnIfIdentifier);
3318 if (optionalVpnInterface.isPresent()) {
3319 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3320 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3322 if (adjacencies == null) {
3325 vpnIfBuilder.addAugmentation(adjacencies);
3326 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3327 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3328 optionalVpnInterface.get().getVpnInstanceNames().values());
3329 if (listVpnInstances.isEmpty()
3330 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3331 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3332 AssociatedSubnetType.V4AndV6Subnets);
3333 listVpnInstances.add(vpnInstance);
3334 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3337 VpnInstanceNames vpnInstance = VpnHelper
3338 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3339 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3340 listVpnInstances.add(vpnInstance);
3341 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3343 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3344 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3346 } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
3347 // FIXME: why are we catching IllegalStateException here?
3348 LOG.error("Update of vpninterface {} failed", infName, ex);
3353 private String getshowVpnConfigCLIHelp() {
3354 StringBuilder help = new StringBuilder("Usage:");
3355 help.append("display vpn-config [-vid/--vpnid <id>]");
3356 return help.toString();
3359 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3360 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3364 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3365 return neutronEvpnManager.createEVPN(input);
3369 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3370 return neutronEvpnManager.getEVPN(input);
3374 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3375 return neutronEvpnManager.deleteEVPN(input);
3378 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3379 Uuid extNetId = extNet.getUuid();
3380 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3381 .child(Networks.class, new NetworksKey(extNetId)).build();
3384 Optional<Networks> optionalExtNets =
3385 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3387 if (!optionalExtNets.isPresent()) {
3388 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3389 extNetId.getValue());
3392 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3393 builder.setVpnid(vpnId);
3394 Networks networks = builder.build();
3395 // Add Networks object to the ExternalNetworks list
3396 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3397 extNetId.getValue());
3398 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3401 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3402 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3403 extNetId.getValue(), ex);
3408 private boolean removeExternalNetworkFromVpn(Network extNet) {
3409 Uuid extNetId = extNet.getUuid();
3410 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3411 .child(Networks.class, new NetworksKey(extNetId)).build();
3413 Optional<Networks> optionalNets =
3414 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3416 NetworksBuilder builder = null;
3417 if (optionalNets.isPresent()) {
3418 builder = new NetworksBuilder(optionalNets.get());
3420 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3421 extNetId.getValue());
3424 builder.setVpnid(null);
3425 Networks networks = builder.build();
3426 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3427 extNetId.getValue());
3428 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3430 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3431 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3432 extNetId.getValue(), ex);
3437 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3438 Optional<String> existingVpnName = Optional.of(primaryRd);
3439 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3441 vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3442 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3443 } catch (ExecutionException | InterruptedException e) {
3444 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3446 /*Read failed. We don't know if a VPN exists or not.
3447 * Return primaryRd to halt caller execution, to be safe.*/
3448 return existingVpnName;
3450 if (vpnInstanceOpDataOptional.isPresent()) {
3451 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3453 existingVpnName = Optional.empty();
3455 return existingVpnName;
3458 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3459 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3462 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3463 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3466 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3467 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3470 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3471 String message = tuple.getMessage();
3472 logger.accept(message);
3476 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3477 @NonNull Subnetmap subnetMap) {
3478 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3479 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3480 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3481 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3482 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3483 subnetMap.getId().getValue(), internetVpnId.getValue());
3487 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3488 @NonNull Subnetmap subnetMap) {
3489 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3490 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3493 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3494 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3495 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3496 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3497 internetVpnId.getValue(), routerId.getValue());
3498 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3504 private AcquireResult tryInterfaceLock(final String infName) {
3505 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3509 private AcquireResult tryVpnLock(final Uuid vpnId) {
3510 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3513 private static ReentrantLock lockForUuid(Uuid uuid) {
3514 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3515 return JvmGlobalLocks.getLockForString(uuid.getValue());
3518 private static void logTryLockFailure(Object objectId) {
3519 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());