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.genius.infra.Datastore.CONFIGURATION;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.JdkFutureAdapters;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture;
22 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.Map.Entry;
33 import java.util.Objects;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.locks.ReentrantLock;
40 import java.util.function.Consumer;
41 import javax.annotation.PreDestroy;
42 import javax.inject.Inject;
43 import javax.inject.Singleton;
44 import org.eclipse.jdt.annotation.NonNull;
45 import org.eclipse.jdt.annotation.Nullable;
46 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
50 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
51 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
52 import org.opendaylight.genius.infra.Datastore.Configuration;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
55 import org.opendaylight.genius.infra.TypedWriteTransaction;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.genius.utils.JvmGlobalLocks;
58 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
59 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
60 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
61 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
62 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
63 import org.opendaylight.netvirt.elanmanager.api.IElanService;
64 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
65 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
66 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
67 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
68 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
69 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
70 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
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.rev150602.AssociateNetworksInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
179 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
180 import org.opendaylight.yangtools.yang.common.RpcError;
181 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
182 import org.opendaylight.yangtools.yang.common.RpcResult;
183 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
184 import org.slf4j.Logger;
185 import org.slf4j.LoggerFactory;
186 import org.slf4j.helpers.FormattingTuple;
187 import org.slf4j.helpers.MessageFormatter;
190 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
192 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
193 private static final long LOCK_WAIT_TIME = 10L;
195 private final DataBroker dataBroker;
196 private final ManagedNewTransactionRunner txRunner;
197 private final VpnRpcService vpnRpcService;
198 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
199 private final IElanService elanService;
200 private final NeutronvpnConfig neutronvpnConfig;
201 private final NeutronEvpnManager neutronEvpnManager;
202 private final NeutronEvpnUtils neutronEvpnUtils;
203 private final JobCoordinator jobCoordinator;
204 private final NeutronvpnUtils neutronvpnUtils;
205 private final IVpnManager vpnManager;
206 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
207 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
208 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
209 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
212 public NeutronvpnManager(
213 final DataBroker dataBroker,
214 final VpnRpcService vpnRpcSrv, final IElanService elanService,
215 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
216 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
217 final JobCoordinator jobCoordinator,
218 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
219 this.dataBroker = dataBroker;
220 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
221 vpnRpcService = vpnRpcSrv;
222 this.elanService = elanService;
223 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
224 this.neutronvpnConfig = neutronvpnConfig;
225 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
226 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
227 this.jobCoordinator = jobCoordinator;
228 this.neutronvpnUtils = neutronvpnUtils;
229 this.vpnManager = vpnManager;
236 public void close() {
237 LOG.info("{} close", getClass().getSimpleName());
240 private void configureFeatures() throws TransactionCommitFailedException {
241 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
242 Neutron.class).child(Features.class).child(
243 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
244 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
246 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
247 } catch (OptimisticLockFailedException e) {
248 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
250 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
251 Neutron.class).child(Features.class).child(
252 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
253 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
255 SingleTransactionDataBroker.syncWrite(
256 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
257 } catch (OptimisticLockFailedException e) {
258 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
262 public String getOpenDaylightVniRangesConfig() {
263 return neutronvpnConfig.getOpendaylightVniRanges();
266 // TODO Clean up the exception handling
267 @SuppressWarnings("checkstyle:IllegalCatch")
268 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
269 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
270 boolean isExternalNw) {
272 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
273 final ReentrantLock lock = lockForUuid(subnetId);
276 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
277 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
278 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
279 if (sn.isPresent()) {
280 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
281 subnetId.getValue());
284 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
285 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
286 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
287 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
288 subnetId.getValue());
289 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
290 subnetMapIdentifier, subnetmapBuilder.build());
294 } catch (TransactionCommitFailedException | ReadFailedException e) {
295 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
297 // check if there are ports to update for already created Subnetmap node
298 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
299 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
300 if (entry.getValue().getValue().equals(subnetId.getValue())) {
301 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
302 unprocessedPortsMap.remove(entry.getKey());
308 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
309 @Nullable Uuid internetvpnId) {
310 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
311 .child(Subnetmap.class, new SubnetmapKey(subnetId))
313 final ReentrantLock lock = lockForUuid(subnetId);
316 Optional<Subnetmap> sn =
317 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
318 if (!sn.isPresent()) {
319 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
322 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
323 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
324 if (routerId != null) {
325 builder.setRouterId(routerId);
328 builder.setVpnId(vpnId);
330 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
331 builder.setInternetVpnId(internetvpnId);
333 Subnetmap subnetmap = builder.build();
334 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
335 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
337 } catch (ReadFailedException | TransactionCommitFailedException e) {
338 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
345 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
346 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
347 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
348 InstanceIdentifier<Subnetmap> id =
349 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
350 final ReentrantLock lock = lockForUuid(subnetId);
353 Optional<Subnetmap> sn =
354 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
355 if (!sn.isPresent()) {
356 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
357 subnetId.getValue());
360 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
361 subnetId.getValue());
362 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
363 builder.setRouterId(routerId);
364 builder.setRouterInterfacePortId(routerInterfacePortId);
365 builder.setRouterIntfMacAddress(routerIntfMacAddress);
366 builder.setRouterInterfaceFixedIp(fixedIp);
368 builder.setVpnId(vpnId);
370 Subnetmap subnetmap = builder.build();
371 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
372 subnetId.getValue());
373 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
374 } catch (ReadFailedException | TransactionCommitFailedException e) {
375 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
376 subnetId.getValue(), e);
382 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
383 @Nullable Uuid directPortId) {
384 Subnetmap subnetmap = null;
385 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
386 new SubnetmapKey(subnetId)).build();
387 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
388 final ReentrantLock lock = lockForUuid(subnetId);
391 Optional<Subnetmap> sn =
392 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
394 if (sn.isPresent()) {
395 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
396 if (null != portId) {
397 List<Uuid> existingPortList = builder.getPortList();
398 List<Uuid> portList = new ArrayList<>();
399 if (null != existingPortList) {
400 portList.addAll(existingPortList);
402 portList.add(portId);
403 builder.setPortList(portList);
404 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
405 subnetId.getValue(), portId.getValue());
407 if (null != directPortId) {
408 List<Uuid> existingDirectPortList = builder.getDirectPortList();
409 List<Uuid> directPortList = new ArrayList<>();
410 if (null != existingDirectPortList) {
411 directPortList.addAll(existingDirectPortList);
413 directPortList.add(directPortId);
414 builder.setDirectPortList(directPortList);
415 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
416 directPortId.getValue());
418 subnetmap = builder.build();
419 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
422 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
423 + "cache ", subnetId.getValue(), portId.getValue());
424 unprocessedPortsMap.put(portId, subnetId);
426 } catch (ReadFailedException | TransactionCommitFailedException e) {
427 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
434 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
435 Uuid vpnId, @Nullable Uuid portId) {
436 Subnetmap subnetmap = null;
437 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
438 .child(Subnetmap.class, new SubnetmapKey(subnetId))
440 final ReentrantLock lock = lockForUuid(subnetId);
443 Optional<Subnetmap> sn =
444 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
446 if (sn.isPresent()) {
447 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
448 if (routerId != null) {
449 builder.setRouterId(null);
451 if (networkId != null) {
452 builder.setNetworkId(null);
455 builder.setVpnId(null);
457 builder.setInternetVpnId(null);
458 if (portId != null && builder.getPortList() != null) {
459 List<Uuid> portList = new ArrayList<>(builder.getPortList());
460 portList.remove(portId);
461 builder.setPortList(portList);
464 subnetmap = builder.build();
465 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
466 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
469 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
471 } catch (ReadFailedException | TransactionCommitFailedException e) {
472 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
480 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
481 @Nullable Uuid directPortId) {
482 Subnetmap subnetmap = null;
483 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
484 new SubnetmapKey(subnetId)).build();
485 final ReentrantLock lock = lockForUuid(subnetId);
488 Optional<Subnetmap> sn =
489 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
491 if (sn.isPresent()) {
492 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
493 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
494 List<Uuid> portList = new ArrayList<>(builder.getPortList());
495 portList.remove(portId);
496 builder.setPortList(portList);
497 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
498 subnetId.getValue());
500 if (null != directPortId && null != builder.getDirectPortList()
501 && !builder.getDirectPortList().isEmpty()) {
502 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
503 directPortList.remove(directPortId);
504 builder.setDirectPortList(directPortList);
505 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
506 .getValue(), subnetId.getValue());
508 subnetmap = builder.build();
509 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
512 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
514 } catch (ReadFailedException | TransactionCommitFailedException e) {
515 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
516 subnetId.getValue(), e);
523 // TODO Clean up the exception handling
524 @SuppressWarnings("checkstyle:IllegalCatch")
525 protected void deleteSubnetMapNode(Uuid subnetId) {
526 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
527 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
528 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
529 final ReentrantLock lock = lockForUuid(subnetId);
532 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
533 } catch (TransactionCommitFailedException e) {
534 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
540 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
541 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
542 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
544 Optional<VpnInstance> vpnInstanceConfig =
545 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
547 if (!vpnInstanceConfig.isPresent()) {
548 LOG.debug("updateVpnInstanceWithRDs: "
549 + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
552 VpnInstance vpnInstance = vpnInstanceConfig.get();
553 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
554 updateVpnInstanceBuilder.setRouteDistinguisher(rds);
555 LOG.debug("updateVpnInstanceWithRDs: "
556 + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
557 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
558 updateVpnInstanceBuilder.build());
559 } catch (ReadFailedException | TransactionCommitFailedException ex) {
560 LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
561 + "the list of RDs: {}", vpnInstanceId, rds, ex);
565 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
566 boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
567 String vpnName = vpnId.getValue();
568 VpnInstanceBuilder builder = null;
569 List<VpnTarget> vpnTargetList = new ArrayList<>();
570 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
571 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
572 Optional<VpnInstance> optionalVpn;
574 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
576 } catch (ReadFailedException e) {
577 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
581 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
582 if (optionalVpn.isPresent()) {
583 builder = new VpnInstanceBuilder(optionalVpn.get());
584 LOG.debug("updating existing vpninstance node");
586 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
587 .setL2vpn(isL2Vpn).setL3vni(l3vni);
589 if (irt != null && !irt.isEmpty()) {
590 if (ert != null && !ert.isEmpty()) {
591 List<String> commonRT = new ArrayList<>(irt);
592 commonRT.retainAll(ert);
594 for (String common : commonRT) {
597 VpnTarget vpnTarget =
598 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
599 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
600 vpnTargetList.add(vpnTarget);
603 for (String importRT : irt) {
604 VpnTarget vpnTarget =
605 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
606 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
607 vpnTargetList.add(vpnTarget);
611 if (ert != null && !ert.isEmpty()) {
612 for (String exportRT : ert) {
613 VpnTarget vpnTarget =
614 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
615 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
616 vpnTargetList.add(vpnTarget);
620 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
621 if (rd != null && !rd.isEmpty()) {
622 builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets);
625 builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
626 VpnInstance newVpn = builder.build();
627 try (AcquireResult lock = tryVpnLock(vpnId)) {
628 if (!lock.wasAcquired()) {
629 // FIXME: why do we even bother with locking if we do not honor it?!
630 logTryLockFailure(vpnId);
633 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
635 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
637 } catch (TransactionCommitFailedException e) {
638 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
643 private void deleteVpnMapsNode(Uuid vpnId) {
644 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
645 .child(VpnMap.class, new VpnMapKey(vpnId))
647 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
648 try (AcquireResult lock = tryVpnLock(vpnId)) {
649 if (!lock.wasAcquired()) {
650 // FIXME: why do we even bother with locking if we do not honor it?!
651 logTryLockFailure(vpnId);
655 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
657 } catch (TransactionCommitFailedException e) {
658 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
663 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
664 @Nullable List<Uuid> networks) {
665 VpnMapBuilder builder;
666 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
667 .child(VpnMap.class, new VpnMapKey(vpnId))
670 Optional<VpnMap> optionalVpnMap =
671 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
673 if (optionalVpnMap.isPresent()) {
674 builder = new VpnMapBuilder(optionalVpnMap.get());
676 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
680 builder.setName(name);
682 if (tenantId != null) {
683 builder.setTenantId(tenantId);
685 if (router != null) {
686 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
687 List<RouterIds> rtrIds = builder.getRouterIds() != null
688 ? new ArrayList<>(builder.getRouterIds()) : null;
689 if (rtrIds == null) {
690 rtrIds = Collections.singletonList(vpnRouterId);
692 rtrIds.add(vpnRouterId);
694 builder.setRouterIds(rtrIds);
696 if (networks != null) {
697 List<Uuid> nwList = builder.getNetworkIds() != null
698 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
699 nwList.addAll(networks);
700 builder.setNetworkIds(nwList);
703 try (AcquireResult lock = tryVpnLock(vpnId)) {
704 if (!lock.wasAcquired()) {
705 // FIXME: why do we even bother with locking if we do not honor it?!
706 logTryLockFailure(vpnId);
709 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
710 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
712 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
714 } catch (ReadFailedException | TransactionCommitFailedException e) {
715 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
719 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
720 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
721 .child(VpnMap.class, new VpnMapKey(vpnId))
723 Optional<VpnMap> optionalVpnMap;
726 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
728 } catch (ReadFailedException e) {
729 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
732 if (optionalVpnMap.isPresent()) {
733 VpnMap vpnMap = optionalVpnMap.get();
734 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
735 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds());
736 if (rtrIds == null) {
737 rtrIds = new ArrayList<>();
739 if (routerId != null) {
740 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
741 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
742 vpnMapBuilder.setRouterIds(rtrIds);
744 try (AcquireResult lock = tryVpnLock(vpnId)) {
745 if (!lock.wasAcquired()) {
746 // FIXME: why do we even bother with locking if we do not honor it?!
747 logTryLockFailure(vpnId);
750 LOG.debug("removing vpnMaps node: {} ", vpnId);
752 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
754 } catch (TransactionCommitFailedException e) {
755 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
759 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
760 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
761 vpnMapBuilder.setRouterIds(rtrIds);
762 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
765 if (networkIds != null) {
766 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
767 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
768 vpnNw.removeAll(networkIds);
769 if (vpnNw.isEmpty()) {
770 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
771 vpnMapBuilder.setNetworkIds(null);
773 vpnMapBuilder.setNetworkIds(vpnNw);
777 try (AcquireResult lock = tryVpnLock(vpnId)) {
778 if (!lock.wasAcquired()) {
779 // FIXME: why do we even bother with locking if we do not honor it?!
780 logTryLockFailure(vpnId);
783 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
785 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
786 vpnMapIdentifier, vpnMapBuilder.build());
787 } catch (TransactionCommitFailedException e) {
788 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
792 LOG.error("VPN : {} not found", vpnId.getValue());
794 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
797 private void deleteVpnInstance(Uuid vpnId) {
798 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
799 .child(VpnInstance.class,
800 new VpnInstanceKey(vpnId.getValue()))
803 try (AcquireResult lock = tryVpnLock(vpnId)) {
804 if (!lock.wasAcquired()) {
805 // FIXME: why do we even bother with locking if we do not honor it?!
806 logTryLockFailure(vpnId);
809 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
811 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
812 } catch (TransactionCommitFailedException e) {
813 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
818 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
819 TypedWriteTransaction<Configuration> wrtConfigTxn,
820 @Nullable VpnInterface vpnIface) {
821 List<Adjacency> adjList = new ArrayList<>();
822 if (vpnIface != null) {
823 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
825 String infName = port.getUuid().getValue();
826 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
827 for (FixedIps ip : port.nonnullFixedIps()) {
828 String ipValue = ip.getIpAddress().stringValue();
829 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
830 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
831 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
832 snTemp.getSubnetIp(), false)) {
835 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
837 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
838 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
839 //Create Neutron port adjacency if VPN presence is existing for subnet
840 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
841 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
842 .setSubnetId(ip.getSubnetId()).build();
843 if (!adjList.contains(vmAdj)) {
847 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
848 if (snTemp != null && snTemp.getInternetVpnId() != null) {
849 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
850 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
852 if (routerId != null) {
853 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
854 if (rtr != null && rtr.getRoutes() != null) {
855 List<Routes> routeList = rtr.getRoutes();
856 // create extraroute Adjacence for each ipValue,
857 // because router can have IPv4 and IPv6 subnet ports, or can have
858 // more that one IPv4 subnet port or more than one IPv6 subnet port
859 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
860 if (!erAdjList.isEmpty()) {
861 adjList.addAll(erAdjList);
866 return new AdjacenciesBuilder().setAdjacency(adjList).build();
869 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
870 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
871 boolean isRouterInterface = false;
872 if (port.getDeviceOwner() != null) {
873 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
875 String infName = port.getUuid().getValue();
876 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
877 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
878 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
879 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
880 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
883 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
884 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
885 String infName = port.getUuid().getValue();
886 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
887 Optional<VpnInterface> optionalVpnInterface = null;
888 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
889 vpnId, internetVpnId, infName);
891 optionalVpnInterface = SingleTransactionDataBroker
892 .syncReadOptional(dataBroker, LogicalDatastoreType
893 .CONFIGURATION, vpnIfIdentifier);
894 } catch (ReadFailedException e) {
895 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
898 if (!optionalVpnInterface.isPresent()) {
901 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
902 sn != null ? sn.getSubnetIp() : "null");
903 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
904 List<Adjacency> updatedAdjsList = new ArrayList<>();
905 boolean isIpFromAnotherSubnet = false;
906 for (Adjacency adj : vpnAdjsList) {
907 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
908 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
909 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
910 isIpFromAnotherSubnet = true;
912 updatedAdjsList.add(adj);
915 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
916 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
919 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
920 String.valueOf(adjString), wrtConfigTxn);
922 if (internetVpnId != null) {
923 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
924 String.valueOf(adjString), wrtConfigTxn);
927 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
928 && sn.getRouterId() != null) {
929 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
930 if (rtr != null && rtr.getRoutes() != null) {
931 List<Routes> extraRoutesToRemove = new ArrayList<>();
932 for (Routes rt: rtr.getRoutes()) {
933 if (rt.getNexthop().toString().equals(adjString)) {
934 extraRoutesToRemove.add(rt);
938 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
939 extraRoutesToRemove, vpnId);
940 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
942 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
947 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
949 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
951 if (!isIpFromAnotherSubnet) {
952 // no more subnetworks for neutron port
953 if (sn != null && sn.getRouterId() != null) {
954 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
956 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
962 // TODO Clean up the exception handling
963 @SuppressWarnings("checkstyle:IllegalCatch")
964 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
965 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
966 if (wrtConfigTxn == null) {
967 ListenableFutures.addErrorLogging(
968 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
969 tx -> deleteVpnInterface(infName, vpnId, tx)),
970 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
974 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
975 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
976 Optional<VpnInterface> optionalVpnInterface;
978 optionalVpnInterface =
979 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
981 } catch (ReadFailedException ex) {
982 LOG.error("Error during deletion of vpninterface {}", infName, ex);
985 if (!optionalVpnInterface.isPresent()) {
986 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
990 VpnInterface vpnInterface = optionalVpnInterface.get();
991 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
993 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
994 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
995 if (!vpnList.isEmpty()) {
996 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
997 + "List not empty", infName);
1000 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1001 .setVpnInstanceNames(vpnList);
1002 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1006 LOG.debug("Deleting vpn interface {}", infName);
1007 wrtConfigTxn.delete(vpnIfIdentifier);
1010 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1011 TypedWriteTransaction<Configuration> writeConfigTxn,
1013 if (vpnId == null || port == null) {
1016 String infName = port.getUuid().getValue();
1017 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1019 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1020 .syncReadOptional(dataBroker, LogicalDatastoreType
1021 .CONFIGURATION, vpnIfIdentifier);
1022 if (optionalVpnInterface.isPresent()) {
1023 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1025 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1026 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1028 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1029 .setVpnInstanceNames(listVpn);
1030 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1031 LOG.debug("Updating vpn interface {}", infName);
1032 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1033 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1034 while (adjacencyIter.hasNext()) {
1035 Adjacency adjacency = adjacencyIter.next();
1036 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1039 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1040 InstanceIdentifier<LearntVpnVipToPort> id =
1041 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1042 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1043 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1044 LogicalDatastoreType.OPERATIONAL, id);
1045 if (optionalVpnVipToPort.isPresent()) {
1046 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1048 if (listVpn == null || listVpn.isEmpty()) {
1049 adjacencyIter.remove();
1051 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1052 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1053 mipToQuery, infName, vpnId.getValue());
1056 for (FixedIps ip : port.nonnullFixedIps()) {
1057 String ipValue = ip.getIpAddress().stringValue();
1059 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1062 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1063 ipValue, writeConfigTxn);
1065 if (listVpn == null || listVpn.isEmpty()) {
1066 if (sm != null && sm.getRouterId() != null) {
1067 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1069 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1071 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1074 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1076 } catch (ReadFailedException ex) {
1077 LOG.error("Update of vpninterface {} failed", infName, ex);
1081 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1083 TypedWriteTransaction<Configuration> writeConfigTxn,
1084 boolean isInternetVpn) {
1085 if (vpnId == null || port == null) {
1088 String infName = port.getUuid().getValue();
1089 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1091 try (AcquireResult lock = tryInterfaceLock(infName)) {
1092 if (!lock.wasAcquired()) {
1093 // FIXME: why do we even bother with locking if we do not honor it?!
1094 logTryLockFailure(infName);
1098 Optional<VpnInterface> optionalVpnInterface =
1099 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1101 if (optionalVpnInterface.isPresent()) {
1102 VpnInstanceNames vpnInstance = VpnHelper
1103 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1104 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1105 .get().getVpnInstanceNames());
1106 if (oldVpnId != null
1107 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1108 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1110 if (vpnId.getValue() != null
1111 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1112 listVpn.add(vpnInstance);
1114 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1115 .setVpnInstanceNames(listVpn);
1116 LOG.debug("Updating vpn interface {}", infName);
1117 if (!isBeingAssociated) {
1118 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1119 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1120 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1121 while (adjacencyIter.hasNext()) {
1122 Adjacency adjacency = adjacencyIter.next();
1123 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1124 InstanceIdentifier<LearntVpnVipToPort> id =
1125 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1126 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1127 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1128 LogicalDatastoreType.OPERATIONAL, id);
1129 if (optionalVpnVipToPort.isPresent()
1130 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1131 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1132 + "from VPN {}", infName, vpnId, oldVpnId);
1133 adjacencyIter.remove();
1134 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1136 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1137 mipToQuery, infName, vpnId.getValue());
1139 InstanceIdentifier<VpnPortipToPort> build =
1140 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1141 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1142 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1143 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1144 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1145 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1146 mipToQuery, infName, vpnId.getValue());
1149 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1150 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1152 for (FixedIps ip : port.nonnullFixedIps()) {
1153 String ipValue = ip.getIpAddress().stringValue();
1154 if (oldVpnId != null) {
1155 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1156 ipValue, writeConfigTxn);
1158 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1159 && isInternetVpn == true) {
1163 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1164 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1166 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1168 LOG.error("VPN Interface {} not found", infName);
1170 } catch (ReadFailedException ex) {
1171 LOG.error("Updation of vpninterface {} failed", infName, ex);
1176 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1177 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1179 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1181 // Update VPN Instance node
1182 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
1184 // Update local vpn-subnet DS
1185 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1187 if (routerId != null) {
1188 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1189 if (existingVpn != null) {
1190 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1191 // if before reboot, router was already associated to VPN, should not proceed associating router to
1192 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1193 // preserved upon reboot.
1194 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1195 // RouterInterfacesMap via #createVPNInterface call.
1196 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1197 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1200 associateRouterToInternalVpn(vpnId, routerId);
1205 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1206 * specified Neutron Networks and Routers.
1208 * @param vpnId Uuid of the VPN tp be created
1209 * @param name Representative name of the new VPN
1210 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1211 * @param rdList Route-distinguisher for the VPN
1212 * @param irtList A list of Import Route Targets
1213 * @param ertList A list of Export Route Targets
1214 * @param routerIdsList ist of neutron router Id to associate with created VPN
1215 * @param networkList UUID of the neutron network the VPN may be associated to
1216 * @param isL2Vpn True if VPN Instance is of type L2, false if L3
1217 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1218 * @throws Exception if association of L3VPN failed
1220 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1221 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1222 boolean isL2Vpn, long l3vni) throws Exception {
1224 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1226 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1227 for (Uuid routerId : routerIdsList) {
1228 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1229 ipVersChoices = ipVersChoices.addVersion(vers);
1232 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
1234 // Please note that router and networks will be filled into VPNMaps
1235 // by subsequent calls here to associateRouterToVpn and
1236 // associateNetworksToVpn
1237 updateVpnMaps(vpnId, name, null, tenantId, null);
1238 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1239 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1242 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1243 for (Uuid routerId : routerIdsList) {
1244 associateRouterToVpn(vpnId, routerId);
1247 if (networkList != null) {
1248 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1249 if (!failStrings.isEmpty()) {
1250 LOG.error("VPN {} association to networks failed for networks: {}. ",
1251 vpnId.getValue(), failStrings);
1252 throw new Exception(failStrings.toString());
1258 * It handles the invocations to the createVPN RPC method.
1261 // TODO Clean up the exception handling
1262 @SuppressWarnings("checkstyle:IllegalCatch")
1263 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1265 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1266 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1267 List<RpcError> errorList = new ArrayList<>();
1268 int failurecount = 0;
1269 int warningcount = 0;
1271 List<L3vpn> vpns = input.getL3vpn();
1273 vpns = Collections.emptyList();
1275 for (L3vpn vpn : vpns) {
1276 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1277 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1278 formatAndLog(LOG::warn,
1279 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1280 vpn.getId().getValue())));
1284 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1285 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1286 formatAndLog(LOG::warn,
1287 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1288 vpn.getId().getValue())));
1293 if (vpn.getL3vni() != null) {
1294 l3vni = vpn.getL3vni().toJava();
1297 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1298 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1299 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1300 formatAndLog(LOG::warn,
1301 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1302 + "is already configured",
1303 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1307 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1308 if (operationalVpn.isPresent()) {
1309 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1310 formatAndLog(LOG::error,
1311 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1312 + "is still available. Please retry creation of a new vpn with the same RD"
1313 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1314 vpn.getRouteDistinguisher().get(0))));
1318 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1319 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1320 routerIdsList = vpn.getRouterIds();
1321 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1322 routerId : routerIdsList) {
1323 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1324 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1325 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1326 + "{}", vpn.getId(), routerId.getRouterId())));
1330 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1331 if (vpnId != null) {
1332 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1333 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1334 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1335 vpnId.getValue())));
1341 if (vpn.getNetworkIds() != null) {
1342 int initialWarningCount = warningcount;
1343 for (Uuid nw : vpn.getNetworkIds()) {
1344 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1345 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1346 if (network == null) {
1347 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1348 formatAndLog(LOG::warn,
1349 "Creation of L3VPN failed for VPN {} due to network not found {}",
1350 vpn.getId().getValue(), nw.getValue())));
1352 } else if (vpnId != null) {
1353 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1354 formatAndLog(LOG::warn,
1355 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1356 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1357 vpnId.getValue())));
1361 if (warningcount != initialWarningCount) {
1365 List<Uuid> rtrIdsList = new ArrayList<>();
1366 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1367 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1368 rtrId : vpn.getRouterIds()) {
1369 rtrIdsList.add(rtrId.getRouterId());
1373 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1374 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1375 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1376 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1378 List<String> rdList = vpn.getRouteDistinguisher() != null
1379 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1380 List<String> importRdList = vpn.getImportRT() != null
1381 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1382 List<String> exportRdList = vpn.getExportRT() != null
1383 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1385 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1386 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
1387 } catch (Exception ex) {
1388 LOG.error("VPN Creation exception :", ex);
1389 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1390 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1395 // if at least one succeeds; result is success
1396 // if none succeeds; result is failure
1397 if (failurecount + warningcount == vpns.size()) {
1398 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1400 List<String> errorResponseList = new ArrayList<>();
1401 if (!errorList.isEmpty()) {
1402 for (RpcError rpcError : errorList) {
1403 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1404 + ", ErrorMessage: " + rpcError.getMessage());
1407 errorResponseList.add("Operation successful with no errors");
1409 opBuilder.setResponse(errorResponseList);
1410 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1416 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1419 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1421 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1422 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1423 Uuid inputVpnId = input.getId();
1424 List<VpnInstance> vpns = new ArrayList<>();
1425 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1428 if (inputVpnId == null) {
1430 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1432 Optional<VpnInstances> optionalVpns =
1433 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1435 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1436 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1437 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1438 // from getL3VPN output
1439 if (vpn.getRouteDistinguisher() != null) {
1445 opBuilder.setL3vpnInstances(l3vpnList);
1446 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1450 String name = inputVpnId.getValue();
1451 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1452 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1453 // read VpnInstance Info
1454 Optional<VpnInstance> optionalVpn =
1455 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1457 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1459 if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
1460 vpns.add(optionalVpn.get());
1463 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1464 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1468 for (VpnInstance vpnInstance : vpns) {
1469 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1470 // create VpnMaps id
1471 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1472 List<String> rd = Collections.EMPTY_LIST;
1473 if (vpnInstance.getRouteDistinguisher() != null) {
1474 rd = vpnInstance.getRouteDistinguisher();
1476 List<String> ertList = new ArrayList<>();
1477 List<String> irtList = new ArrayList<>();
1479 if (vpnInstance.getVpnTargets() != null) {
1480 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1481 if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
1482 vpnTargetList = vpnInstance.getVpnTargets().getVpnTarget();
1484 if (!vpnTargetList.isEmpty()) {
1485 for (VpnTarget vpnTarget : vpnTargetList) {
1486 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1487 ertList.add(vpnTarget.getVrfRTValue());
1489 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1490 irtList.add(vpnTarget.getVrfRTValue());
1492 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1493 ertList.add(vpnTarget.getVrfRTValue());
1494 irtList.add(vpnTarget.getVrfRTValue());
1500 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1502 if (vpnInstance.getL3vni() != null) {
1503 l3vpn.setL3vni(vpnInstance.getL3vni());
1505 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1506 .class, new VpnMapKey(vpnId)).build();
1507 Optional<VpnMap> optionalVpnMap =
1508 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1510 if (optionalVpnMap.isPresent()) {
1511 VpnMap vpnMap = optionalVpnMap.get();
1512 List<Uuid> rtrIds = new ArrayList<>();
1513 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1514 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1515 rtrIds.add(rtrId.getRouterId());
1518 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1519 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1520 .setName(vpnMap.getName());
1523 l3vpnList.add(l3vpn.build());
1526 opBuilder.setL3vpnInstances(l3vpnList);
1527 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1529 } catch (ReadFailedException ex) {
1530 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1531 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1537 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1540 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1542 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1543 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1544 List<RpcError> errorList = new ArrayList<>();
1546 int failurecount = 0;
1547 int warningcount = 0;
1548 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1549 for (Uuid vpn : vpns) {
1551 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1552 InstanceIdentifier<VpnInstance> vpnIdentifier =
1553 InstanceIdentifier.builder(VpnInstances.class)
1554 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1555 Optional<VpnInstance> optionalVpn =
1556 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1558 if (optionalVpn.isPresent()) {
1561 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1562 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1565 } catch (ReadFailedException ex) {
1566 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1567 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1572 // if at least one succeeds; result is success
1573 // if none succeeds; result is failure
1574 if (failurecount + warningcount == vpns.size()) {
1575 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1577 List<String> errorResponseList = new ArrayList<>();
1578 if (!errorList.isEmpty()) {
1579 for (RpcError rpcError : errorList) {
1580 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1581 + ", ErrorMessage: " + rpcError.getMessage());
1584 errorResponseList.add("Operation successful with no errors");
1586 opBuilder.setResponse(errorResponseList);
1587 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1592 public void createVpnInstanceForSubnet(Uuid subnetId) {
1593 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1594 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1597 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1598 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1599 removeVpn(subnetId);
1602 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1603 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1604 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1605 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1607 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1608 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1611 if (vpnId != null) {
1612 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1613 if (vpnMap == null) {
1614 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1615 + " cannot add subnet {} to VPN", vpnId.getValue(),
1619 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1620 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1621 if (isVpnOfTypeL2(vpnInstance)) {
1622 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1623 NeutronEvpnUtils.Operation.ADD);
1626 if (internetVpnId != null) {
1627 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1628 if (vpnMap == null) {
1629 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1630 + "subnet {} to VPN", internetVpnId.getValue(),
1635 final Uuid internetId = internetVpnId;
1636 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1637 List<Uuid> portList = sn.getPortList();
1638 if (portList != null) {
1639 for (final Uuid portId : portList) {
1640 String vpnInfName = portId.getValue();
1641 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1642 Port port = neutronvpnUtils.getNeutronPort(portId);
1644 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1645 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1648 final Boolean isRouterInterface = port.getDeviceOwner()
1649 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1650 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1651 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1653 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1655 if (vpnIface == null) {
1656 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1657 Set<Uuid> listVpn = new HashSet<>();
1658 if (vpnId != null) {
1661 if (internetId != null) {
1662 listVpn.add(internetId);
1664 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1665 isRouterInterface, wrtConfigTxn);
1666 if (sn.getRouterId() != null) {
1667 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1670 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1671 if (vpnId != null) {
1672 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1674 if (internetId != null) {
1675 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1679 ListenableFutures.addErrorLogging(future, LOG,
1680 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1681 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1682 return Collections.singletonList(future);
1688 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1689 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1690 "removeSubnetFromVpn: at least one VPN must be not null");
1691 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1692 vpnId, internetVpnId);
1693 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1695 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1698 VpnMap vpnMap = null;
1699 VpnInstance vpnInstance = null;
1700 if (vpnId != null) {
1701 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1702 if (vpnMap == null) {
1703 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1704 vpnId.getValue(), subnet.getValue());
1707 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1709 if (internetVpnId == null) {
1710 internetVpnId = sn.getInternetVpnId();
1712 if (internetVpnId != null) {
1713 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1714 if (vpnMap == null) {
1715 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1716 + " from Internet VPN",
1717 internetVpnId.getValue(), subnet.getValue());
1721 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1722 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1723 NeutronEvpnUtils.Operation.DELETE);
1725 boolean subnetVpnAssociation = false;
1726 if (vpnId != null && sn.getVpnId() != null
1727 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1728 subnetVpnAssociation = true;
1729 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1730 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1731 subnetVpnAssociation = true;
1733 if (subnetVpnAssociation == false) {
1734 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1735 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1738 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1739 List<Uuid> portList = sn.getPortList();
1740 final Uuid internetId = internetVpnId;
1741 if (portList != null) {
1742 for (final Uuid portId : portList) {
1743 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1744 final Port port = neutronvpnUtils.getNeutronPort(portId);
1745 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1746 List<ListenableFuture<Void>> futures = new ArrayList<>();
1747 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1748 CONFIGURATION, tx -> {
1750 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1752 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1753 + " port is absent in Neutron config DS", portId.getValue(),
1757 ListenableFutures.addErrorLogging(future, LOG,
1758 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1759 + " belonging to subnet {} and vpnId {}",
1760 portId.getValue(), subnet.getValue(), vpnId.getValue());
1761 futures.add(future);
1766 //update subnet-vpn association
1767 removeFromSubnetNode(subnet, null, null, vpnId, null);
1770 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1771 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1772 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1774 Uuid internalVpnId = sm.getVpnId();
1775 if (internalVpnId == null) {
1776 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1777 sm.getId().getValue());
1780 if (isBeingAssociated) {
1781 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1783 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1786 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1787 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1788 if (isBeingAssociated) {
1789 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1790 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1792 removeInternetVpnFromVpnInterface(vpn,
1793 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1798 // Check for ports on this subnet and update association of
1799 // corresponding vpn-interfaces to internet vpn
1800 List<Uuid> portList = sm.getPortList();
1801 if (portList != null) {
1802 for (Uuid port : portList) {
1803 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1804 port.getValue(), isBeingAssociated);
1805 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1806 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1808 if (isBeingAssociated) {
1809 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1810 true, false, tx, true);
1812 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1820 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1821 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1822 oldVpnId.getValue(), newVpnId.getValue());
1823 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1824 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1825 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1826 Uuid vpnExtUuid = netIsExternal ? null
1827 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1828 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1830 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1833 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1834 * associated with internet BGP-VPN.
1836 if (vpnExtUuid != null) {
1837 /* Update V6 Internet default route match with new VPN metadata.
1838 * isBeingAssociated = true means oldVpnId is same as routerId
1839 * isBeingAssociated = false means newVpnId is same as routerId
1841 if (isBeingAssociated) {
1842 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1844 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1847 //Update Router Interface first synchronously.
1848 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1849 ListenableFuture<Void> future =
1850 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1851 tx -> updateVpnInterface(newVpnId, oldVpnId,
1852 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1853 isBeingAssociated, true, tx, false));
1854 Futures.addCallback(future, new FutureCallback<Void>() {
1856 public void onSuccess(Void result) {
1857 // Check for ports on this subnet and update association of
1858 // corresponding vpn-interfaces to external vpn
1859 List<Uuid> portList = sn.getPortList();
1860 if (portList != null) {
1861 for (Uuid port : portList) {
1862 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1863 port.getValue(), isBeingAssociated);
1864 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1865 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1866 tx -> updateVpnInterface(newVpnId, oldVpnId,
1867 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1874 public void onFailure(Throwable throwable) {
1876 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1878 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1880 }, MoreExecutors.directExecutor());
1885 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1886 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1887 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1890 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1891 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1892 final ReentrantLock lock = lockForUuid(routerId);
1895 Optional<RouterInterfaces> optRouterInterfaces =
1896 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1897 routerInterfacesId);
1898 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1899 .setInterfaceId(interfaceName).build();
1900 if (optRouterInterfaces.isPresent()) {
1901 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1902 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1904 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1905 List<Interfaces> interfaces = new ArrayList<>();
1906 interfaces.add(routerInterface);
1907 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1908 routerInterfacesId, builder.setInterfaces(interfaces).build());
1910 } catch (ReadFailedException | TransactionCommitFailedException e) {
1911 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1917 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1918 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1919 final ReentrantLock lock = lockForUuid(routerId);
1922 Optional<RouterInterfaces> optRouterInterfaces =
1923 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1924 routerInterfacesId);
1925 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1926 .setInterfaceId(interfaceName).build();
1927 if (optRouterInterfaces.isPresent()) {
1928 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1929 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
1930 if (interfaces != null && interfaces.remove(routerInterface)) {
1931 if (interfaces.isEmpty()) {
1932 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1933 routerInterfacesId);
1935 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1936 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1940 } catch (ReadFailedException | TransactionCommitFailedException e) {
1941 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1948 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1949 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1950 * route will be ignored.
1952 * @param vpnName the VPN identifier
1953 * @param interVpnLinkRoutes The list of static routes
1954 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1956 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1957 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1958 for (Routes route : interVpnLinkRoutes) {
1959 String nexthop = route.getNexthop().stringValue();
1960 String destination = route.getDestination().stringValue();
1961 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1962 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1963 AddStaticRouteInput rpcInput =
1964 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1965 .setVpnInstanceName(vpnName.getValue())
1967 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1968 RpcResult<AddStaticRouteOutput> rpcResult;
1970 rpcResult = labelOuputFtr.get();
1971 if (rpcResult.isSuccessful()) {
1972 LOG.debug("Label generated for destination {} is: {}",
1973 destination, rpcResult.getResult().getLabel());
1975 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1976 destination, nexthop, rpcResult.getErrors());
1978 } catch (InterruptedException | ExecutionException e) {
1979 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1980 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1983 // Any other case is a fault.
1984 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1985 route.getDestination().stringValue(), nexthop);
1992 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1993 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1995 * @param vpnName the VPN identifier
1996 * @param interVpnLinkRoutes The list of static routes
1997 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1999 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2000 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2001 for (Routes route : interVpnLinkRoutes) {
2002 String nexthop = route.getNexthop().stringValue();
2003 String destination = route.getDestination().stringValue();
2004 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2005 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2006 RemoveStaticRouteInput rpcInput =
2007 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2008 .setVpnInstanceName(vpnName.getValue())
2011 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2012 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2014 // Any other case is a fault.
2015 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2016 route.getDestination().stringValue(), nexthop);
2023 * Returns true if the specified nexthop is the other endpoint in an
2024 * InterVpnLink, regarding one of the VPN's point of view.
2026 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2027 InterVpnLink interVpnLink) {
2029 interVpnLink != null
2030 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2031 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2032 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2033 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2037 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2038 List<Adjacency> adjList = new ArrayList<>();
2039 Map<String, List<String>> adjMap = new HashMap<>();
2040 for (Routes route : routeList) {
2041 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2042 LOG.error("Incorrect input received for extra route. {}", route);
2044 String nextHop = route.getNexthop().stringValue();
2045 String destination = route.getDestination().stringValue();
2046 if (!nextHop.equals(fixedIp)) {
2047 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2050 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2052 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2053 if (!hops.contains(nextHop)) {
2059 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2060 final String destination = entry.getKey();
2061 final List<String> ipList = entry.getValue();
2062 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2063 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2064 .withKey(new AdjacencyKey(destination)).build();
2070 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2071 checkAlarmExtraRoutes(vpnId, routeList);
2073 for (Routes route : routeList) {
2074 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2075 LOG.error("Incorrect input received for extra route. {}", route);
2077 String nextHop = route.getNexthop().stringValue();
2078 String destination = route.getDestination().stringValue();
2079 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2081 if (infName != null) {
2082 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2083 destination, vpnId.getValue(), nextHop, infName);
2084 boolean isLockAcquired = false;
2086 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2087 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2088 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2089 .child(Adjacency.class, new AdjacencyKey(destination));
2090 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2091 LogicalDatastoreType.CONFIGURATION, path);
2092 if (existingAdjacency.isPresent()
2093 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2094 LOG.error("The route with destination {} nextHop {} is already present as"
2095 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2096 destination, nextHop, infName);
2099 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2100 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2101 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2103 try (AcquireResult lock = tryInterfaceLock(infName)) {
2104 if (!lock.wasAcquired()) {
2105 // FIXME: why do we even bother with locking if we do not honor it?!
2106 logTryLockFailure(infName);
2109 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2112 } catch (TransactionCommitFailedException e) {
2113 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2114 destination, nextHop, e);
2115 } catch (ReadFailedException e) {
2116 LOG.error("Exception on reading data-store ", e);
2119 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2120 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2127 * This method setup or down an alarm about extra route fault.
2128 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2129 * available RDs, then an alarm and an error is generated.<br>
2130 * <b>Be careful</b> the routeList could be changed.
2132 * @param vpnId the vpnId of vpn to control.
2133 * @param routeList the list of router to check, it could be modified.
2135 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2136 if (!neutronvpnAlarm.isAlarmEnabled()) {
2137 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2140 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2141 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2142 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2146 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2147 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2148 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2152 for (Routes route : routeList) {
2153 // count the number of nexthops for each same route.getDestingation().getValue()
2154 String destination = route.getDestination().stringValue();
2155 String nextHop = route.getNexthop().stringValue();
2156 List<String> nextHopList = new ArrayList<>();
2157 nextHopList.add(nextHop);
2159 for (Routes routeTmp : routeList) {
2160 String routeDest = routeTmp.getDestination().stringValue();
2161 if (!destination.equals(routeDest)) {
2164 String routeNextH = routeTmp.getNexthop().stringValue();
2165 if (nextHop.equals(routeNextH)) {
2169 nextHopList.add(routeTmp.getNexthop().stringValue());
2171 final List<String> rdList = new ArrayList<>();
2172 if (vpnInstance != null
2173 && vpnInstance.getRouteDistinguisher() != null) {
2174 vpnInstance.getRouteDistinguisher().forEach(rd -> {
2180 // 1. VPN Instance Name
2181 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2184 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2185 Uuid routerUuid = routerUuidList.get(0);
2186 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2187 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2189 // 3. List of RDs associated with the VPN
2190 detailsAlarm.append(" List of RDs associated with the VPN: ");
2191 for (String s : rdList) {
2192 detailsAlarm.append(s);
2193 detailsAlarm.append(", ");
2196 // 4. Prefix in question
2197 detailsAlarm.append(" for prefix: ");
2198 detailsAlarm.append(route.getDestination().stringValue());
2200 // 5. List of NHs for the prefix
2201 detailsAlarm.append(" for nextHops: ");
2202 for (String s : nextHopList) {
2203 detailsAlarm.append(s);
2204 detailsAlarm.append(", ");
2207 if (rdList.size() < nbNextHops) {
2208 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2210 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2215 // TODO Clean up the exception handling
2216 @SuppressWarnings("checkstyle:IllegalCatch")
2217 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2218 for (Routes route : routeList) {
2219 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2220 String nextHop = route.getNexthop().stringValue();
2221 String destination = route.getDestination().stringValue();
2222 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2224 if (infName == null) {
2225 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2226 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2227 // Proceed to remove the next extra-route
2230 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2231 destination, vpnId.getValue(), nextHop, infName);
2233 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2234 InstanceIdentifier.builder(VpnInterfaces.class)
2235 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2236 .augmentation(Adjacencies.class)
2237 .child(Adjacency.class, new AdjacencyKey(destination))
2241 // Looking for existing prefix in MDSAL database
2242 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2243 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2244 boolean updateNextHops = false;
2245 List<String> nextHopList = new ArrayList<>();
2246 if (adjacency.isPresent()) {
2247 List<String> nhListRead = adjacency.get().getNextHopIpList();
2248 if (nhListRead.size() > 1) { // ECMP case
2249 for (String nextHopRead : nhListRead) {
2250 if (nextHopRead.equals(nextHop)) {
2251 updateNextHops = true;
2253 nextHopList.add(nextHopRead);
2259 try (AcquireResult lock = tryInterfaceLock(infName)) {
2260 if (!lock.wasAcquired()) {
2261 // FIXME: why do we even bother with locking if we do not honor it?!
2262 logTryLockFailure(infName);
2265 if (updateNextHops) {
2266 // An update must be done, not including the current next hop
2267 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2268 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2269 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2270 .setNextHopIpList(nextHopList)
2271 .withKey(new AdjacencyKey(destination))
2273 Adjacencies erAdjs =
2274 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2275 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2276 .addAugmentation(Adjacencies.class, erAdjs).build();
2277 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2278 vpnIfIdentifier, vpnIf);
2280 // Remove the whole route
2281 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2282 adjacencyIdentifier);
2283 LOG.trace("extra route {} deleted successfully", route);
2286 } catch (TransactionCommitFailedException | ReadFailedException e) {
2287 LOG.error("exception in deleting extra route with destination {} for interface {}",
2288 destination, infName, e);
2291 LOG.error("Incorrect input received for extra route: {}", route);
2296 public void removeVpn(Uuid vpnId) {
2298 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2299 if (vpnMap != null) {
2300 List<RouterIds> routerIdsList = vpnMap.getRouterIds();
2301 List<Uuid> routerUuidList = new ArrayList<>();
2302 // dissociate router
2303 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2304 for (RouterIds router : routerIdsList) {
2305 Uuid routerId = router.getRouterId();
2306 routerUuidList.add(routerId);
2307 dissociateRouterFromVpn(vpnId, routerId);
2310 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2311 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2314 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2316 // remove entire vpnMaps node
2317 deleteVpnMapsNode(vpnId);
2319 // remove vpn-instance
2320 deleteVpnInstance(vpnId);
2321 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2324 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2325 return vpnInstance != null && vpnInstance.isL2vpn();
2328 // TODO Clean up the exception handling
2329 @SuppressWarnings("checkstyle:IllegalCatch")
2330 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2331 updateVpnMaps(vpnId, null, routerId, null, null);
2332 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2333 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2334 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2335 for (Subnetmap sn : subMapList) {
2336 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2337 if (!ipVersion.isIpVersionChosen(ipVers)) {
2338 ipVersion = ipVersion.addVersion(ipVers);
2341 if (ipVersion != IpVersionChoice.UNDEFINED) {
2342 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2344 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2346 for (Subnetmap sn : subMapList) {
2347 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2351 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2352 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2353 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2354 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2355 for (Uuid subnet : routerSubnets) {
2356 IpVersionChoice version = NeutronvpnUtils
2357 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2358 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2359 addSubnetToVpn(vpnId, subnet, null);
2361 addSubnetToVpn(vpnId, subnet, internetVpnId);
2366 // TODO Clean up the exception handling
2367 @SuppressWarnings("checkstyle:IllegalCatch")
2368 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2370 clearFromVpnMaps(vpnId, routerId, null);
2371 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2372 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2373 for (Subnetmap sn : subMapList) {
2374 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2375 if (ipVersion.isIpVersionChosen(ipVers)) {
2376 ipVersion = ipVersion.addVersion(ipVers);
2378 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2379 routerId.getValue());
2380 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2382 if (ipVersion != IpVersionChoice.UNDEFINED) {
2383 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2385 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2391 * Parses and associates networks list with given VPN.
2393 * @param vpnId Uuid of given VPN.
2394 * @param networkList List list of network Ids (Uuid), which will be associated.
2395 * @return list of formatted strings with detailed error messages.
2398 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2399 List<String> failedNwList = new ArrayList<>();
2400 HashSet<Uuid> passedNwList = new HashSet<>();
2401 boolean isExternalNetwork = false;
2402 if (networkList.isEmpty()) {
2403 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2404 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2406 return failedNwList;
2408 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2409 if (vpnInstance == null) {
2410 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2411 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2412 + "in ConfigDS", vpnId.getValue()));
2413 return failedNwList;
2416 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2417 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2419 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2420 + "associated with", vpnId.getValue()));
2421 return failedNwList;
2423 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2424 for (Uuid nw : networkList) {
2425 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2426 if (network == null) {
2427 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2428 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2432 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2433 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2434 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2435 nw.getValue(), vpnId.getValue());
2436 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2437 nw.getValue(), vpnId.getValue()));
2440 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2441 if (networkVpnId != null) {
2442 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2443 nw.getValue(), networkVpnId.getValue());
2444 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2445 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2448 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2449 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2450 nw.getValue(), vpnId.getValue());
2451 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2452 nw.getValue(), vpnId.getValue()));
2455 if (NeutronvpnUtils.getIsExternal(network)) {
2456 isExternalNetwork = true;
2458 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2459 if (subnetmapList == null || subnetmapList.isEmpty()) {
2460 passedNwList.add(nw);
2463 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2466 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2467 for (Subnetmap subnetmap : subnetmapList) {
2468 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2469 if (!ipVersion.isIpVersionChosen(ipVers)) {
2470 ipVersion = ipVersion.addVersion(ipVers);
2473 if (ipVersion != IpVersionChoice.UNDEFINED) {
2474 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2475 + " for VPN {} ", ipVersion, vpnId);
2476 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2478 for (Subnetmap subnetmap : subnetmapList) {
2479 Uuid subnetId = subnetmap.getId();
2480 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2481 if (subnetVpnId != null) {
2482 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2483 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2484 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2485 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2488 if (!NeutronvpnUtils.getIsExternal(network)) {
2489 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2491 addSubnetToVpn(vpnId, subnetId, null);
2492 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2494 passedNwList.add(nw);
2497 passedNwList.add(nw);
2499 } catch (ReadFailedException e) {
2500 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2502 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2505 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2506 if (!isExternalNetwork) {
2507 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2509 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2510 return failedNwList;
2513 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2514 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2517 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2518 if (vpnOpDataEntry == null) {
2519 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2522 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2523 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2524 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2526 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2527 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2528 updateVpnMaps(vpnId, null, null, null, extNwList);
2529 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2530 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2531 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2533 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2536 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2537 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2540 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2541 updateVpnInternetForSubnet(sm, vpnId, true);
2543 if (!ipVersion.isIpVersionChosen(ipVers)) {
2544 ipVersion = ipVersion.addVersion(ipVers);
2547 if (ipVersion != IpVersionChoice.UNDEFINED) {
2548 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2549 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2550 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2556 * Parses and disassociates networks list from given VPN.
2558 * @param vpnId Uuid of given VPN.
2559 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2560 * @return list of formatted strings with detailed error messages.
2563 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2564 List<String> failedNwList = new ArrayList<>();
2565 HashSet<Uuid> passedNwList = new HashSet<>();
2566 if (networkList.isEmpty()) {
2567 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2568 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2570 return failedNwList;
2572 for (Uuid nw : networkList) {
2573 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2574 if (networkSubnets == null) {
2575 passedNwList.add(nw);
2578 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2579 if (network == null) {
2580 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2581 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2585 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2586 if (networkVpnId == null) {
2587 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2588 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2592 if (!vpnId.equals(networkVpnId)) {
2593 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2594 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2595 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2596 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2600 if (NeutronvpnUtils.getIsExternal(network)) {
2601 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2602 passedNwList.add(nw);
2604 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2605 nw.getValue(), vpnId.getValue());
2606 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2611 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2612 for (Uuid subnet : networkSubnets) {
2613 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2614 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2615 if (!ipVersion.isIpVersionChosen(ipVers)) {
2616 ipVersion = ipVersion.addVersion(ipVers);
2618 if (!NeutronvpnUtils.getIsExternal(network)) {
2619 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2621 removeSubnetFromVpn(vpnId, subnet, null);
2622 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2623 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2625 passedNwList.add(nw);
2628 if (ipVersion != IpVersionChoice.UNDEFINED) {
2629 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2630 + " for VPN {}", ipVersion, vpnId);
2631 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2634 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2635 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2636 passedNwList, vpnId.getValue());
2637 return failedNwList;
2640 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2641 if (!removeExternalNetworkFromVpn(extNet)) {
2644 // check, if there is another Provider Networks associated with given VPN
2645 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2646 if (vpnNets != null) {
2647 //Remove currently disassociated network from the list
2648 vpnNets.remove(extNet.getUuid());
2649 for (Uuid netId : vpnNets) {
2650 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2651 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2652 + "{}", vpnId.getValue(), netId.getValue());
2657 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2658 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2659 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2660 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2661 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2662 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2663 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2665 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2668 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2669 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2672 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2673 updateVpnInternetForSubnet(sm, vpnId, false);
2675 if (!ipVersion.isIpVersionChosen(ipVers)) {
2676 ipVersion = ipVersion.addVersion(ipVers);
2679 if (ipVersion != IpVersionChoice.UNDEFINED) {
2680 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2681 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2683 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2689 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2692 // TODO Clean up the exception handling
2693 @SuppressWarnings("checkstyle:IllegalCatch")
2694 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2696 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2697 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2698 StringBuilder returnMsg = new StringBuilder();
2699 Uuid vpnId = input.getVpnId();
2702 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2703 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2704 input.getNetworkId());
2705 List<Uuid> netIds = input.getNetworkId();
2706 if (netIds != null && !netIds.isEmpty()) {
2707 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2708 if (!failed.isEmpty()) {
2709 returnMsg.append(failed);
2713 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2715 if (returnMsg.length() != 0) {
2716 opBuilder.setResponse(
2717 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2718 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2719 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2721 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2723 } catch (Exception ex) {
2724 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2725 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2726 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2727 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2729 LOG.debug("associateNetworks returns..");
2734 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2737 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2739 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2740 LOG.debug("associateRouter {}", input);
2741 StringBuilder returnMsg = new StringBuilder();
2742 Uuid vpnId = input.getVpnId();
2743 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2744 routerIds = input.getRouterIds();
2745 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2746 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2747 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2748 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2749 .RouterIds routerId : routerIds) {
2750 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2751 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2752 if (vpnMap != null) {
2754 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2755 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2756 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2757 .append(routerId.getRouterId());
2758 } else if (extVpnId != null) {
2759 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2760 + "another VPN ").append(extVpnId.getValue());
2762 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2763 routerId.getRouterId());
2764 associateRouterToVpn(vpnId, routerId.getRouterId());
2767 returnMsg.append("router not found : ").append(routerId.getRouterId());
2770 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2772 if (returnMsg.length() != 0) {
2773 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2774 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2775 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2777 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2780 LOG.debug("associateRouter returns..");
2785 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2788 // TODO Clean up the exception handling
2789 @SuppressWarnings("checkstyle:IllegalCatch")
2790 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2791 GetFixedIPsForNeutronPortInput input) {
2792 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2793 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2794 Uuid portId = input.getPortId();
2795 StringBuilder returnMsg = new StringBuilder();
2797 List<String> fixedIPList = new ArrayList<>();
2798 Port port = neutronvpnUtils.getNeutronPort(portId);
2800 for (FixedIps ip : port.nonnullFixedIps()) {
2801 fixedIPList.add(ip.getIpAddress().stringValue());
2804 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2806 if (returnMsg.length() != 0) {
2807 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2809 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2810 returnMsg)).build());
2812 opBuilder.setFixedIPs(fixedIPList);
2813 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2815 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2817 } catch (Exception ex) {
2818 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2819 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2820 portId.getValue(), ex.getMessage(), ex)).build());
2826 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2829 // TODO Clean up the exception handling
2830 @SuppressWarnings("checkstyle:IllegalCatch")
2831 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2833 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2834 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2836 LOG.debug("dissociateNetworks {}", input);
2837 StringBuilder returnMsg = new StringBuilder();
2838 Uuid vpnId = input.getVpnId();
2841 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2842 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2843 input.getNetworkId());
2844 List<Uuid> netIds = input.getNetworkId();
2845 if (netIds != null && !netIds.isEmpty()) {
2846 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2847 if (!failed.isEmpty()) {
2848 returnMsg.append(failed);
2852 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2854 if (returnMsg.length() != 0) {
2855 opBuilder.setResponse(
2856 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2857 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2859 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2861 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2863 } catch (Exception ex) {
2864 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2865 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2866 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2868 LOG.debug("dissociateNetworks returns..");
2873 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2876 // TODO Clean up the exception handling
2877 @SuppressWarnings("checkstyle:IllegalCatch")
2878 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2880 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2882 LOG.debug("dissociateRouter {}", input);
2883 StringBuilder returnMsg = new StringBuilder();
2884 Uuid vpnId = input.getVpnId();
2885 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2886 .RouterIds> routerIdList = input.getRouterIds();
2887 String routerIdsString = "";
2888 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2889 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2890 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2891 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2892 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2893 .RouterIds routerId : routerIdList) {
2895 if (routerId != null) {
2896 routerIdsString += routerId.getRouterId() + ", ";
2897 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2899 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2900 if (routerVpnId == null) {
2901 returnMsg.append("input router ").append(routerId.getRouterId())
2902 .append(" not associated to any vpn yet");
2903 } else if (vpnId.equals(routerVpnId)) {
2904 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2906 returnMsg.append("input router ").append(routerId.getRouterId())
2907 .append(" associated to vpn ")
2908 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2911 returnMsg.append("router not found : ").append(routerId.getRouterId());
2914 if (returnMsg.length() != 0) {
2915 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2916 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2917 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2918 returnMsg)).build());
2920 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2922 } catch (Exception ex) {
2923 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2924 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2925 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2929 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2932 LOG.debug("dissociateRouter returns..");
2936 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2937 // check if the router is associated to some VPN
2938 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2939 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2940 if (vpnId != null) {
2941 // remove existing external vpn interfaces
2942 for (Uuid subnetId : routerSubnetIds) {
2943 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2945 clearFromVpnMaps(vpnId, routerId, null);
2947 // remove existing internal vpn interfaces
2948 for (Uuid subnetId : routerSubnetIds) {
2949 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2952 // delete entire vpnMaps node for internal VPN
2953 deleteVpnMapsNode(routerId);
2955 // delete vpn-instance for internal VPN
2956 deleteVpnInstance(routerId);
2959 protected Subnet getNeutronSubnet(Uuid subnetId) {
2960 return neutronvpnUtils.getNeutronSubnet(subnetId);
2964 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2965 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2967 return sn.getGatewayIp();
2973 protected Network getNeutronNetwork(Uuid networkId) {
2974 return neutronvpnUtils.getNeutronNetwork(networkId);
2977 protected Port getNeutronPort(String name) {
2978 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2981 protected Port getNeutronPort(Uuid portId) {
2982 return neutronvpnUtils.getNeutronPort(portId);
2985 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2986 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2989 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2990 return neutronvpnUtils.getNetworksForVpn(vpnId);
2994 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2996 * @return a List of String to be printed on screen
2997 * @throws ReadFailedException if there was a problem reading from the data store
2999 public List<String> showNeutronPortsCLI() throws ReadFailedException {
3000 List<String> result = new ArrayList<>();
3001 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3003 result.add("-------------------------------------------------------------------------------------------");
3004 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3006 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3007 if (ports.isPresent() && ports.get().getPort() != null) {
3008 for (Port port : ports.get().nonnullPort()) {
3009 List<FixedIps> fixedIPs = port.getFixedIps();
3010 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3011 List<String> ipList = new ArrayList<>();
3012 for (FixedIps fixedIp : fixedIPs) {
3013 IpAddress ipAddress = fixedIp.getIpAddress();
3014 if (ipAddress.getIpv4Address() != null) {
3015 ipList.add(ipAddress.getIpv4Address().getValue());
3017 ipList.add(ipAddress.getIpv6Address().getValue());
3020 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3021 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3022 ipList.toString()));
3024 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3025 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3034 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3036 * @param vpnuuid Uuid of the VPN whose config must be shown
3037 * @return formatted output list
3038 * @throws InterruptedException if there was a thread related problem getting the data to display
3039 * @throws ExecutionException if there was any other problem getting the data to display
3041 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3042 List<String> result = new ArrayList<>();
3043 if (vpnuuid == null) {
3045 result.add("Displaying VPN config for all VPNs");
3046 result.add("To display VPN config for a particular VPN, use the following syntax");
3047 result.add(getshowVpnConfigCLIHelp());
3049 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3050 if (rpcResult.isSuccessful()) {
3052 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3054 result.add(String.format(" %-80s ", "Import-RTs"));
3056 result.add(String.format(" %-80s ", "Export-RTs"));
3058 result.add(String.format(" %-76s ", "Subnet IDs"));
3060 result.add("------------------------------------------------------------------------------------");
3062 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3063 rpcResult.getResult().nonnullL3vpnInstances()) {
3064 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3066 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3067 vpn.getRouteDistinguisher()));
3069 result.add(String.format(" %-80s ", vpn.getImportRT()));
3071 result.add(String.format(" %-80s ", vpn.getExportRT()));
3074 Uuid vpnid = vpn.getId();
3075 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3076 if (!subnetList.isEmpty()) {
3077 for (Uuid subnetuuid : subnetList) {
3078 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3081 result.add(String.format(" %-76s ", "\" \""));
3084 result.add("----------------------------------------");
3088 String errortag = rpcResult.getErrors().iterator().next().getTag();
3089 if (Objects.equals(errortag, "")) {
3091 result.add("No VPN has been configured yet");
3092 } else if (Objects.equals(errortag, "invalid-value")) {
3094 result.add("VPN " + vpnuuid.getValue() + " is not present");
3096 result.add("error getting VPN info : " + rpcResult.getErrors());
3097 result.add(getshowVpnConfigCLIHelp());
3103 protected void createExternalVpnInterfaces(Uuid extNetId) {
3104 if (extNetId == null) {
3105 LOG.error("createExternalVpnInterfaces: external network is null");
3109 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3110 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3111 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3115 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3116 for (String elanInterface : extElanInterfaces) {
3117 createExternalVpnInterface(extNetId, elanInterface, tx);
3119 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3122 // TODO Clean up the exception handling
3123 @SuppressWarnings("checkstyle:IllegalCatch")
3124 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3125 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3126 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3127 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3130 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3131 for (String elanInterface : extElanInterfaces) {
3132 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3133 .buildVpnInterfaceIdentifier(elanInterface);
3134 LOG.info("Removing vpn interface {}", elanInterface);
3135 tx.delete(vpnIfIdentifier);
3137 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3140 private void createExternalVpnInterface(Uuid vpnId, String infName,
3141 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3142 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3143 false /* not a router iface */, wrtConfigTxn);
3146 // TODO Clean up the exception handling
3147 @SuppressWarnings("checkstyle:IllegalCatch")
3148 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3149 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3150 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3151 if (vpnIdList.isEmpty() || infName == null) {
3152 LOG.error("vpnid is empty or interface({}) is null", infName);
3155 if (wrtConfigTxn == null) {
3156 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3157 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3158 "Error writing VPN interface");
3161 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3162 for (Uuid vpnId: vpnIdList) {
3163 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3164 AssociatedSubnetType.V4AndV6Subnets);
3165 vpnIdListStruct.add(vpnInstance);
3168 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3169 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3171 .setVpnInstanceNames(vpnIdListStruct)
3172 .setRouterInterface(isRouterInterface);
3173 LOG.info("Network Id is {}", networkUuid);
3174 if (networkUuid != null) {
3175 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3176 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3177 NetworkAttributes.NetworkType networkType = providerType != null
3178 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3179 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3180 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3181 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3184 if (adjacencies != null) {
3185 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3187 VpnInterface vpnIf = vpnb.build();
3189 LOG.info("Creating vpn interface {}", vpnIf);
3190 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3191 } catch (Exception ex) {
3192 LOG.error("Creation of vpninterface {} failed", infName, ex);
3196 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3197 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3198 if (vpnId == null || infName == null) {
3199 LOG.error("vpn id or interface is null");
3202 if (wrtConfigTxn == null) {
3203 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3204 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3205 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3206 }), LOG, "Error updating VPN interface with adjacencies");
3210 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3212 try (AcquireResult lock = tryInterfaceLock(infName)) {
3213 if (!lock.wasAcquired()) {
3214 // FIXME: why do we even bother with locking if we do not honor it?!
3215 logTryLockFailure(infName);
3219 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3220 .syncReadOptional(dataBroker, LogicalDatastoreType
3221 .CONFIGURATION, vpnIfIdentifier);
3222 if (optionalVpnInterface.isPresent()) {
3223 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3224 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3226 if (adjacencies == null) {
3229 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3230 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3231 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3232 optionalVpnInterface.get().getVpnInstanceNames());
3233 if (listVpnInstances.isEmpty()
3234 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3235 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3236 AssociatedSubnetType.V4AndV6Subnets);
3237 listVpnInstances.add(vpnInstance);
3238 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3241 VpnInstanceNames vpnInstance = VpnHelper
3242 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3243 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3244 listVpnInstances.add(vpnInstance);
3245 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3247 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3248 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3250 } catch (IllegalStateException | ReadFailedException ex) {
3251 // FIXME: why are we catching IllegalStateException here?
3252 LOG.error("Update of vpninterface {} failed", infName, ex);
3257 private String getshowVpnConfigCLIHelp() {
3258 StringBuilder help = new StringBuilder("Usage:");
3259 help.append("display vpn-config [-vid/--vpnid <id>]");
3260 return help.toString();
3263 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3264 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3268 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3269 return neutronEvpnManager.createEVPN(input);
3273 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3274 return neutronEvpnManager.getEVPN(input);
3278 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3279 return neutronEvpnManager.deleteEVPN(input);
3282 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3283 Uuid extNetId = extNet.getUuid();
3284 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3285 .child(Networks.class, new NetworksKey(extNetId)).build();
3288 Optional<Networks> optionalExtNets =
3289 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3291 if (!optionalExtNets.isPresent()) {
3292 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3293 extNetId.getValue());
3296 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3297 builder.setVpnid(vpnId);
3298 Networks networks = builder.build();
3299 // Add Networks object to the ExternalNetworks list
3300 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3301 extNetId.getValue());
3302 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3305 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3306 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3307 extNetId.getValue(), ex);
3312 private boolean removeExternalNetworkFromVpn(Network extNet) {
3313 Uuid extNetId = extNet.getUuid();
3314 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3315 .child(Networks.class, new NetworksKey(extNetId)).build();
3317 Optional<Networks> optionalNets =
3318 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3320 NetworksBuilder builder = null;
3321 if (optionalNets.isPresent()) {
3322 builder = new NetworksBuilder(optionalNets.get());
3324 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3325 extNetId.getValue());
3328 builder.setVpnid(null);
3329 Networks networks = builder.build();
3330 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3331 extNetId.getValue());
3332 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3334 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3335 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3336 extNetId.getValue(), ex);
3341 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3342 Optional<String> existingVpnName = Optional.of(primaryRd);
3343 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3345 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3346 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3347 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3348 } catch (ReadFailedException e) {
3349 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3351 /*Read failed. We don't know if a VPN exists or not.
3352 * Return primaryRd to halt caller execution, to be safe.*/
3353 return existingVpnName;
3355 if (vpnInstanceOpDataOptional.isPresent()) {
3356 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3358 existingVpnName = Optional.absent();
3360 return existingVpnName;
3363 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3364 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3367 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3368 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3371 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3372 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3375 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3376 String message = tuple.getMessage();
3377 logger.accept(message);
3381 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3382 @NonNull Subnetmap subnetMap) {
3383 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3384 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3385 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3386 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3387 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3388 subnetMap.getId().getValue(), internetVpnId.getValue());
3392 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3393 @NonNull Subnetmap subnetMap) {
3394 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3395 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3398 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3399 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3400 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3401 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3402 internetVpnId.getValue(), routerId.getValue());
3403 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3409 private AcquireResult tryInterfaceLock(final String infName) {
3410 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3414 private AcquireResult tryVpnLock(final Uuid vpnId) {
3415 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3418 private static ReentrantLock lockForUuid(Uuid uuid) {
3419 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3420 return JvmGlobalLocks.getLockForString(uuid.getValue());
3423 private static void logTryLockFailure(Object objectId) {
3424 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());