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.Preconditions;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.JdkFutureAdapters;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
33 import java.util.Optional;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.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.genius.datastoreutils.SingleTransactionDataBroker;
47 import org.opendaylight.genius.infra.Datastore.Configuration;
48 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
49 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
50 import org.opendaylight.genius.infra.TypedWriteTransaction;
51 import org.opendaylight.genius.mdsalutil.NwConstants;
52 import org.opendaylight.genius.utils.JvmGlobalLocks;
53 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
54 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
55 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
56 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
57 import org.opendaylight.mdsal.binding.api.DataBroker;
58 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
59 import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
60 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
61 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
62 import org.opendaylight.netvirt.elanmanager.api.IElanService;
63 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
64 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
65 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
66 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
67 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
68 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
69 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
178 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
179 import org.opendaylight.yangtools.yang.common.RpcError;
180 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
181 import org.opendaylight.yangtools.yang.common.RpcResult;
182 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
183 import org.slf4j.Logger;
184 import org.slf4j.LoggerFactory;
185 import org.slf4j.helpers.FormattingTuple;
186 import org.slf4j.helpers.MessageFormatter;
189 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
191 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
192 private static final long LOCK_WAIT_TIME = 10L;
194 private final DataBroker dataBroker;
195 private final ManagedNewTransactionRunner txRunner;
196 private final VpnRpcService vpnRpcService;
197 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
198 private final IElanService elanService;
199 private final NeutronvpnConfig neutronvpnConfig;
200 private final NeutronEvpnManager neutronEvpnManager;
201 private final NeutronEvpnUtils neutronEvpnUtils;
202 private final JobCoordinator jobCoordinator;
203 private final NeutronvpnUtils neutronvpnUtils;
204 private final IVpnManager vpnManager;
205 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
206 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
207 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
208 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
211 public NeutronvpnManager(
212 final DataBroker dataBroker,
213 final VpnRpcService vpnRpcSrv, final IElanService elanService,
214 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
215 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
216 final JobCoordinator jobCoordinator,
217 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
218 this.dataBroker = dataBroker;
219 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
220 vpnRpcService = vpnRpcSrv;
221 this.elanService = elanService;
222 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
223 this.neutronvpnConfig = neutronvpnConfig;
224 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
225 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
226 this.jobCoordinator = jobCoordinator;
227 this.neutronvpnUtils = neutronvpnUtils;
228 this.vpnManager = vpnManager;
235 public void close() {
236 LOG.info("{} close", getClass().getSimpleName());
239 private void configureFeatures() throws TransactionCommitFailedException {
240 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
241 Neutron.class).child(Features.class).child(
242 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
243 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
245 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
246 } catch (OptimisticLockFailedException e) {
247 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
249 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
250 Neutron.class).child(Features.class).child(
251 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
252 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
254 SingleTransactionDataBroker.syncWrite(
255 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
256 } catch (OptimisticLockFailedException e) {
257 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
261 public String getOpenDaylightVniRangesConfig() {
262 return neutronvpnConfig.getOpendaylightVniRanges();
265 // TODO Clean up the exception handling
266 @SuppressWarnings("checkstyle:IllegalCatch")
267 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
268 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
269 boolean isExternalNw) {
271 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
272 final ReentrantLock lock = lockForUuid(subnetId);
275 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
276 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
277 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
278 if (sn.isPresent()) {
279 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
280 subnetId.getValue());
283 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
284 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
285 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
286 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
287 subnetId.getValue());
288 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
289 subnetMapIdentifier, subnetmapBuilder.build());
293 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
294 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
296 // check if there are ports to update for already created Subnetmap node
297 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
298 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
299 if (entry.getValue().getValue().equals(subnetId.getValue())) {
300 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
301 unprocessedPortsMap.remove(entry.getKey());
307 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
308 @Nullable Uuid internetvpnId) {
309 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
310 .child(Subnetmap.class, new SubnetmapKey(subnetId))
312 final ReentrantLock lock = lockForUuid(subnetId);
315 Optional<Subnetmap> sn =
316 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
317 if (!sn.isPresent()) {
318 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
321 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
322 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
323 if (routerId != null) {
324 builder.setRouterId(routerId);
327 builder.setVpnId(vpnId);
329 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
330 builder.setInternetVpnId(internetvpnId);
332 Subnetmap subnetmap = builder.build();
333 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
334 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
336 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
337 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
344 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
345 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
346 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
347 InstanceIdentifier<Subnetmap> id =
348 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
349 final ReentrantLock lock = lockForUuid(subnetId);
352 Optional<Subnetmap> sn =
353 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
354 if (!sn.isPresent()) {
355 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
356 subnetId.getValue());
359 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
360 subnetId.getValue());
361 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
362 builder.setRouterId(routerId);
363 builder.setRouterInterfacePortId(routerInterfacePortId);
364 builder.setRouterIntfMacAddress(routerIntfMacAddress);
365 builder.setRouterInterfaceFixedIp(fixedIp);
367 builder.setVpnId(vpnId);
369 Subnetmap subnetmap = builder.build();
370 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
371 subnetId.getValue());
372 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
373 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
374 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
375 subnetId.getValue(), e);
381 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
382 @Nullable Uuid directPortId) {
383 Subnetmap subnetmap = null;
384 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
385 new SubnetmapKey(subnetId)).build();
386 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
387 final ReentrantLock lock = lockForUuid(subnetId);
390 Optional<Subnetmap> sn =
391 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
393 if (sn.isPresent()) {
394 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
395 if (null != portId) {
396 List<Uuid> existingPortList = builder.getPortList();
397 List<Uuid> portList = new ArrayList<>();
398 if (null != existingPortList) {
399 portList.addAll(existingPortList);
401 portList.add(portId);
402 builder.setPortList(portList);
403 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
404 subnetId.getValue(), portId.getValue());
406 if (null != directPortId) {
407 List<Uuid> existingDirectPortList = builder.getDirectPortList();
408 List<Uuid> directPortList = new ArrayList<>();
409 if (null != existingDirectPortList) {
410 directPortList.addAll(existingDirectPortList);
412 directPortList.add(directPortId);
413 builder.setDirectPortList(directPortList);
414 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
415 directPortId.getValue());
417 subnetmap = builder.build();
418 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
421 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
422 + "cache ", subnetId.getValue(), portId.getValue());
423 unprocessedPortsMap.put(portId, subnetId);
425 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
426 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
433 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
434 Uuid vpnId, @Nullable Uuid portId) {
435 Subnetmap subnetmap = null;
436 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
437 .child(Subnetmap.class, new SubnetmapKey(subnetId))
439 final ReentrantLock lock = lockForUuid(subnetId);
442 Optional<Subnetmap> sn =
443 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
445 if (sn.isPresent()) {
446 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
447 if (routerId != null) {
448 builder.setRouterId(null);
450 if (networkId != null) {
451 builder.setNetworkId(null);
454 builder.setVpnId(null);
456 builder.setInternetVpnId(null);
457 if (portId != null && builder.getPortList() != null) {
458 List<Uuid> portList = new ArrayList<>(builder.getPortList());
459 portList.remove(portId);
460 builder.setPortList(portList);
463 subnetmap = builder.build();
464 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
465 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
468 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
470 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
471 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
479 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
480 @Nullable Uuid directPortId) {
481 Subnetmap subnetmap = null;
482 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
483 new SubnetmapKey(subnetId)).build();
484 final ReentrantLock lock = lockForUuid(subnetId);
487 Optional<Subnetmap> sn =
488 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
490 if (sn.isPresent()) {
491 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
492 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
493 List<Uuid> portList = new ArrayList<>(builder.getPortList());
494 portList.remove(portId);
495 builder.setPortList(portList);
496 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
497 subnetId.getValue());
499 if (null != directPortId && null != builder.getDirectPortList()
500 && !builder.getDirectPortList().isEmpty()) {
501 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
502 directPortList.remove(directPortId);
503 builder.setDirectPortList(directPortList);
504 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
505 .getValue(), subnetId.getValue());
507 subnetmap = builder.build();
508 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
511 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
513 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
514 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
515 subnetId.getValue(), e);
522 // TODO Clean up the exception handling
523 @SuppressWarnings("checkstyle:IllegalCatch")
524 protected void deleteSubnetMapNode(Uuid subnetId) {
525 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
526 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
527 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
528 final ReentrantLock lock = lockForUuid(subnetId);
531 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
532 } catch (TransactionCommitFailedException e) {
533 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
539 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
540 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
541 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
543 Optional<VpnInstance> vpnInstanceConfig =
544 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
546 if (!vpnInstanceConfig.isPresent()) {
547 LOG.debug("updateVpnInstanceWithRDs: "
548 + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
551 VpnInstance vpnInstance = vpnInstanceConfig.get();
552 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
553 updateVpnInstanceBuilder.setRouteDistinguisher(rds);
554 LOG.debug("updateVpnInstanceWithRDs: "
555 + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
556 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
557 updateVpnInstanceBuilder.build());
558 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
559 LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
560 + "the list of RDs: {}", vpnInstanceId, rds, ex);
564 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
565 boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
566 String vpnName = vpnId.getValue();
567 VpnInstanceBuilder builder = null;
568 List<VpnTarget> vpnTargetList = new ArrayList<>();
569 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
570 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
571 Optional<VpnInstance> optionalVpn;
573 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
575 } catch (ExecutionException | InterruptedException e) {
576 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
580 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
581 if (optionalVpn.isPresent()) {
582 builder = new VpnInstanceBuilder(optionalVpn.get());
583 LOG.debug("updating existing vpninstance node");
585 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
586 .setL2vpn(isL2Vpn).setL3vni(l3vni);
588 if (irt != null && !irt.isEmpty()) {
589 if (ert != null && !ert.isEmpty()) {
590 List<String> commonRT = new ArrayList<>(irt);
591 commonRT.retainAll(ert);
593 for (String common : commonRT) {
596 VpnTarget vpnTarget =
597 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
598 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
599 vpnTargetList.add(vpnTarget);
602 for (String importRT : irt) {
603 VpnTarget vpnTarget =
604 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
605 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
606 vpnTargetList.add(vpnTarget);
610 if (ert != null && !ert.isEmpty()) {
611 for (String exportRT : ert) {
612 VpnTarget vpnTarget =
613 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
614 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
615 vpnTargetList.add(vpnTarget);
619 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
620 if (rd != null && !rd.isEmpty()) {
621 builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets);
624 builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
625 VpnInstance newVpn = builder.build();
626 try (AcquireResult lock = tryVpnLock(vpnId)) {
627 if (!lock.wasAcquired()) {
628 // FIXME: why do we even bother with locking if we do not honor it?!
629 logTryLockFailure(vpnId);
632 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
634 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
636 } catch (TransactionCommitFailedException e) {
637 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
642 private void deleteVpnMapsNode(Uuid vpnId) {
643 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
644 .child(VpnMap.class, new VpnMapKey(vpnId))
646 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
647 try (AcquireResult lock = tryVpnLock(vpnId)) {
648 if (!lock.wasAcquired()) {
649 // FIXME: why do we even bother with locking if we do not honor it?!
650 logTryLockFailure(vpnId);
654 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
656 } catch (TransactionCommitFailedException e) {
657 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
662 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
663 @Nullable List<Uuid> networks) {
664 VpnMapBuilder builder;
665 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
666 .child(VpnMap.class, new VpnMapKey(vpnId))
669 Optional<VpnMap> optionalVpnMap =
670 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
672 if (optionalVpnMap.isPresent()) {
673 builder = new VpnMapBuilder(optionalVpnMap.get());
675 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
679 builder.setName(name);
681 if (tenantId != null) {
682 builder.setTenantId(tenantId);
684 if (router != null) {
685 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
686 List<RouterIds> rtrIds = builder.getRouterIds() != null
687 ? new ArrayList<>(builder.getRouterIds()) : null;
688 if (rtrIds == null) {
689 rtrIds = Collections.singletonList(vpnRouterId);
691 rtrIds.add(vpnRouterId);
693 builder.setRouterIds(rtrIds);
695 if (networks != null) {
696 List<Uuid> nwList = builder.getNetworkIds() != null
697 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
698 nwList.addAll(networks);
699 builder.setNetworkIds(nwList);
702 try (AcquireResult lock = tryVpnLock(vpnId)) {
703 if (!lock.wasAcquired()) {
704 // FIXME: why do we even bother with locking if we do not honor it?!
705 logTryLockFailure(vpnId);
708 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
709 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
711 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
713 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
714 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
718 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
719 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
720 .child(VpnMap.class, new VpnMapKey(vpnId))
722 Optional<VpnMap> optionalVpnMap;
725 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
727 } catch (ExecutionException | InterruptedException e) {
728 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
731 if (optionalVpnMap.isPresent()) {
732 VpnMap vpnMap = optionalVpnMap.get();
733 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
734 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds());
735 if (rtrIds == null) {
736 rtrIds = new ArrayList<>();
738 if (routerId != null) {
739 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
740 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
741 vpnMapBuilder.setRouterIds(rtrIds);
743 try (AcquireResult lock = tryVpnLock(vpnId)) {
744 if (!lock.wasAcquired()) {
745 // FIXME: why do we even bother with locking if we do not honor it?!
746 logTryLockFailure(vpnId);
749 LOG.debug("removing vpnMaps node: {} ", vpnId);
751 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
753 } catch (TransactionCommitFailedException e) {
754 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
758 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
759 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
760 vpnMapBuilder.setRouterIds(rtrIds);
761 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
764 if (networkIds != null) {
765 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
766 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
767 vpnNw.removeAll(networkIds);
768 if (vpnNw.isEmpty()) {
769 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
770 vpnMapBuilder.setNetworkIds(null);
772 vpnMapBuilder.setNetworkIds(vpnNw);
776 try (AcquireResult lock = tryVpnLock(vpnId)) {
777 if (!lock.wasAcquired()) {
778 // FIXME: why do we even bother with locking if we do not honor it?!
779 logTryLockFailure(vpnId);
782 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
784 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
785 vpnMapIdentifier, vpnMapBuilder.build());
786 } catch (TransactionCommitFailedException e) {
787 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
791 LOG.error("VPN : {} not found", vpnId.getValue());
793 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
796 private void deleteVpnInstance(Uuid vpnId) {
797 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
798 .child(VpnInstance.class,
799 new VpnInstanceKey(vpnId.getValue()))
802 try (AcquireResult lock = tryVpnLock(vpnId)) {
803 if (!lock.wasAcquired()) {
804 // FIXME: why do we even bother with locking if we do not honor it?!
805 logTryLockFailure(vpnId);
808 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
810 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
811 } catch (TransactionCommitFailedException e) {
812 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
817 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
818 TypedWriteTransaction<Configuration> wrtConfigTxn,
819 @Nullable VpnInterface vpnIface) {
820 List<Adjacency> adjList = new ArrayList<>();
821 if (vpnIface != null) {
822 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
824 String infName = port.getUuid().getValue();
825 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
826 for (FixedIps ip : port.nonnullFixedIps()) {
827 String ipValue = ip.getIpAddress().stringValue();
828 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
829 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
830 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
831 snTemp.getSubnetIp(), false)) {
834 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
836 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
837 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
838 //Create Neutron port adjacency if VPN presence is existing for subnet
839 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
840 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
841 .setSubnetId(ip.getSubnetId()).build();
842 if (!adjList.contains(vmAdj)) {
846 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
847 if (snTemp != null && snTemp.getInternetVpnId() != null) {
848 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
849 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
851 if (routerId != null) {
852 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
853 if (rtr != null && rtr.getRoutes() != null) {
854 List<Routes> routeList = rtr.getRoutes();
855 // create extraroute Adjacence for each ipValue,
856 // because router can have IPv4 and IPv6 subnet ports, or can have
857 // more that one IPv4 subnet port or more than one IPv6 subnet port
858 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
859 if (!erAdjList.isEmpty()) {
860 adjList.addAll(erAdjList);
865 return new AdjacenciesBuilder().setAdjacency(adjList).build();
868 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
869 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
870 boolean isRouterInterface = false;
871 if (port.getDeviceOwner() != null) {
872 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
874 String infName = port.getUuid().getValue();
875 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
876 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
877 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
878 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
879 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
882 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
883 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
884 String infName = port.getUuid().getValue();
885 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
886 Optional<VpnInterface> optionalVpnInterface = null;
887 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
888 vpnId, internetVpnId, infName);
890 optionalVpnInterface = SingleTransactionDataBroker
891 .syncReadOptional(dataBroker, LogicalDatastoreType
892 .CONFIGURATION, vpnIfIdentifier);
893 } catch (ExecutionException | InterruptedException e) {
894 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
897 if (!optionalVpnInterface.isPresent()) {
900 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
901 sn != null ? sn.getSubnetIp() : "null");
902 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
903 List<Adjacency> updatedAdjsList = new ArrayList<>();
904 boolean isIpFromAnotherSubnet = false;
905 for (Adjacency adj : vpnAdjsList) {
906 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
907 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
908 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
909 isIpFromAnotherSubnet = true;
911 updatedAdjsList.add(adj);
914 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
915 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
918 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
919 String.valueOf(adjString), wrtConfigTxn);
921 if (internetVpnId != null) {
922 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
923 String.valueOf(adjString), wrtConfigTxn);
926 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
927 && sn.getRouterId() != null) {
928 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
929 if (rtr != null && rtr.getRoutes() != null) {
930 List<Routes> extraRoutesToRemove = new ArrayList<>();
931 for (Routes rt: rtr.getRoutes()) {
932 if (rt.getNexthop().toString().equals(adjString)) {
933 extraRoutesToRemove.add(rt);
937 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
938 extraRoutesToRemove, vpnId);
939 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
941 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
946 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
948 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
950 if (!isIpFromAnotherSubnet) {
951 // no more subnetworks for neutron port
952 if (sn != null && sn.getRouterId() != null) {
953 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
955 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
961 // TODO Clean up the exception handling
962 @SuppressWarnings("checkstyle:IllegalCatch")
963 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
964 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
965 if (wrtConfigTxn == null) {
966 ListenableFutures.addErrorLogging(
967 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
968 tx -> deleteVpnInterface(infName, vpnId, tx)),
969 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
973 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
974 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
975 Optional<VpnInterface> optionalVpnInterface;
977 optionalVpnInterface =
978 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
980 } catch (ExecutionException | InterruptedException ex) {
981 LOG.error("Error during deletion of vpninterface {}", infName, ex);
984 if (!optionalVpnInterface.isPresent()) {
985 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
989 VpnInterface vpnInterface = optionalVpnInterface.get();
990 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
992 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
993 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
994 if (!vpnList.isEmpty()) {
995 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
996 + "List not empty", infName);
999 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1000 .setVpnInstanceNames(vpnList);
1001 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1005 LOG.debug("Deleting vpn interface {}", infName);
1006 wrtConfigTxn.delete(vpnIfIdentifier);
1009 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1010 TypedWriteTransaction<Configuration> writeConfigTxn,
1012 if (vpnId == null || port == null) {
1015 String infName = port.getUuid().getValue();
1016 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1018 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1019 .syncReadOptional(dataBroker, LogicalDatastoreType
1020 .CONFIGURATION, vpnIfIdentifier);
1021 if (optionalVpnInterface.isPresent()) {
1022 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1024 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1025 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1027 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1028 .setVpnInstanceNames(listVpn);
1029 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1030 LOG.debug("Updating vpn interface {}", infName);
1031 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1032 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1033 while (adjacencyIter.hasNext()) {
1034 Adjacency adjacency = adjacencyIter.next();
1035 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1038 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1039 InstanceIdentifier<LearntVpnVipToPort> id =
1040 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1041 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1042 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1043 LogicalDatastoreType.OPERATIONAL, id);
1044 if (optionalVpnVipToPort.isPresent()) {
1045 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1047 if (listVpn == null || listVpn.isEmpty()) {
1048 adjacencyIter.remove();
1050 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1051 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1052 mipToQuery, infName, vpnId.getValue());
1055 for (FixedIps ip : port.nonnullFixedIps()) {
1056 String ipValue = ip.getIpAddress().stringValue();
1058 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1061 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1062 ipValue, writeConfigTxn);
1064 if (listVpn == null || listVpn.isEmpty()) {
1065 if (sm != null && sm.getRouterId() != null) {
1066 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1068 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1070 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1073 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1075 } catch (ExecutionException | InterruptedException ex) {
1076 LOG.error("Update of vpninterface {} failed", infName, ex);
1080 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1082 TypedWriteTransaction<Configuration> writeConfigTxn,
1083 boolean isInternetVpn) {
1084 if (vpnId == null || port == null) {
1087 String infName = port.getUuid().getValue();
1088 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1090 try (AcquireResult lock = tryInterfaceLock(infName)) {
1091 if (!lock.wasAcquired()) {
1092 // FIXME: why do we even bother with locking if we do not honor it?!
1093 logTryLockFailure(infName);
1097 Optional<VpnInterface> optionalVpnInterface =
1098 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1100 if (optionalVpnInterface.isPresent()) {
1101 VpnInstanceNames vpnInstance = VpnHelper
1102 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1103 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1104 .get().getVpnInstanceNames());
1105 if (oldVpnId != null
1106 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1107 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1109 if (vpnId.getValue() != null
1110 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1111 listVpn.add(vpnInstance);
1113 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1114 .setVpnInstanceNames(listVpn);
1115 LOG.debug("Updating vpn interface {}", infName);
1116 if (!isBeingAssociated) {
1117 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1118 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1119 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1120 while (adjacencyIter.hasNext()) {
1121 Adjacency adjacency = adjacencyIter.next();
1122 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1123 InstanceIdentifier<LearntVpnVipToPort> id =
1124 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1125 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1126 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1127 LogicalDatastoreType.OPERATIONAL, id);
1128 if (optionalVpnVipToPort.isPresent()
1129 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1130 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1131 + "from VPN {}", infName, vpnId, oldVpnId);
1132 adjacencyIter.remove();
1133 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1135 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1136 mipToQuery, infName, vpnId.getValue());
1138 InstanceIdentifier<VpnPortipToPort> build =
1139 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1140 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1141 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1142 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1143 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1144 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1145 mipToQuery, infName, vpnId.getValue());
1148 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1149 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1151 for (FixedIps ip : port.nonnullFixedIps()) {
1152 String ipValue = ip.getIpAddress().stringValue();
1153 if (oldVpnId != null) {
1154 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1155 ipValue, writeConfigTxn);
1157 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1158 && isInternetVpn == true) {
1162 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1163 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1165 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1167 LOG.error("VPN Interface {} not found", infName);
1169 } catch (ExecutionException | InterruptedException ex) {
1170 LOG.error("Updation of vpninterface {} failed", infName, ex);
1175 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1176 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1178 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1180 // Update VPN Instance node
1181 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
1183 // Update local vpn-subnet DS
1184 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1186 if (routerId != null) {
1187 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1188 if (existingVpn != null) {
1189 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1190 // if before reboot, router was already associated to VPN, should not proceed associating router to
1191 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1192 // preserved upon reboot.
1193 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1194 // RouterInterfacesMap via #createVPNInterface call.
1195 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1196 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1199 associateRouterToInternalVpn(vpnId, routerId);
1204 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1205 * specified Neutron Networks and Routers.
1207 * @param vpnId Uuid of the VPN tp be created
1208 * @param name Representative name of the new VPN
1209 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1210 * @param rdList Route-distinguisher for the VPN
1211 * @param irtList A list of Import Route Targets
1212 * @param ertList A list of Export Route Targets
1213 * @param routerIdsList ist of neutron router Id to associate with created VPN
1214 * @param networkList UUID of the neutron network the VPN may be associated to
1215 * @param isL2Vpn True if VPN Instance is of type L2, false if L3
1216 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1217 * @throws Exception if association of L3VPN failed
1219 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1220 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1221 boolean isL2Vpn, long l3vni) throws Exception {
1223 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1225 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1226 for (Uuid routerId : routerIdsList) {
1227 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1228 ipVersChoices = ipVersChoices.addVersion(vers);
1231 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
1233 // Please note that router and networks will be filled into VPNMaps
1234 // by subsequent calls here to associateRouterToVpn and
1235 // associateNetworksToVpn
1236 updateVpnMaps(vpnId, name, null, tenantId, null);
1237 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1238 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1241 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1242 for (Uuid routerId : routerIdsList) {
1243 associateRouterToVpn(vpnId, routerId);
1246 if (networkList != null) {
1247 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1248 if (!failStrings.isEmpty()) {
1249 LOG.error("VPN {} association to networks failed for networks: {}. ",
1250 vpnId.getValue(), failStrings);
1251 throw new Exception(failStrings.toString());
1257 * It handles the invocations to the createVPN RPC method.
1260 // TODO Clean up the exception handling
1261 @SuppressWarnings("checkstyle:IllegalCatch")
1262 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1264 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1265 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1266 List<RpcError> errorList = new ArrayList<>();
1267 int failurecount = 0;
1268 int warningcount = 0;
1270 List<L3vpn> vpns = input.getL3vpn();
1272 vpns = Collections.emptyList();
1274 for (L3vpn vpn : vpns) {
1275 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1276 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1277 formatAndLog(LOG::warn,
1278 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1279 vpn.getId().getValue())));
1283 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1284 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1285 formatAndLog(LOG::warn,
1286 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1287 vpn.getId().getValue())));
1292 if (vpn.getL3vni() != null) {
1293 l3vni = vpn.getL3vni().toJava();
1296 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1297 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1298 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1299 formatAndLog(LOG::warn,
1300 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1301 + "is already configured",
1302 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1306 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1307 if (operationalVpn.isPresent()) {
1308 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1309 formatAndLog(LOG::error,
1310 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1311 + "is still available. Please retry creation of a new vpn with the same RD"
1312 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1313 vpn.getRouteDistinguisher().get(0))));
1317 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1318 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1319 routerIdsList = vpn.getRouterIds();
1320 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1321 routerId : routerIdsList) {
1322 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1323 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1324 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1325 + "{}", vpn.getId(), routerId.getRouterId())));
1329 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1330 if (vpnId != null) {
1331 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1332 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1333 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1334 vpnId.getValue())));
1340 if (vpn.getNetworkIds() != null) {
1341 int initialWarningCount = warningcount;
1342 for (Uuid nw : vpn.getNetworkIds()) {
1343 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1344 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1345 if (network == null) {
1346 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1347 formatAndLog(LOG::warn,
1348 "Creation of L3VPN failed for VPN {} due to network not found {}",
1349 vpn.getId().getValue(), nw.getValue())));
1351 } else if (vpnId != null) {
1352 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1353 formatAndLog(LOG::warn,
1354 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1355 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1356 vpnId.getValue())));
1360 if (warningcount != initialWarningCount) {
1364 List<Uuid> rtrIdsList = new ArrayList<>();
1365 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1366 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1367 rtrId : vpn.getRouterIds()) {
1368 rtrIdsList.add(rtrId.getRouterId());
1372 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1373 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1374 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1375 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1377 List<String> rdList = vpn.getRouteDistinguisher() != null
1378 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1379 List<String> importRdList = vpn.getImportRT() != null
1380 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1381 List<String> exportRdList = vpn.getExportRT() != null
1382 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1384 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1385 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
1386 } catch (Exception ex) {
1387 LOG.error("VPN Creation exception :", ex);
1388 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1389 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1394 // if at least one succeeds; result is success
1395 // if none succeeds; result is failure
1396 if (failurecount + warningcount == vpns.size()) {
1397 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1399 List<String> errorResponseList = new ArrayList<>();
1400 if (!errorList.isEmpty()) {
1401 for (RpcError rpcError : errorList) {
1402 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1403 + ", ErrorMessage: " + rpcError.getMessage());
1406 errorResponseList.add("Operation successful with no errors");
1408 opBuilder.setResponse(errorResponseList);
1409 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1415 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1418 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1420 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1421 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1422 Uuid inputVpnId = input.getId();
1423 List<VpnInstance> vpns = new ArrayList<>();
1424 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1427 if (inputVpnId == null) {
1429 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1431 Optional<VpnInstances> optionalVpns =
1432 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1434 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1435 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1436 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1437 // from getL3VPN output
1438 if (vpn.getRouteDistinguisher() != null) {
1444 opBuilder.setL3vpnInstances(l3vpnList);
1445 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1449 String name = inputVpnId.getValue();
1450 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1451 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1452 // read VpnInstance Info
1453 Optional<VpnInstance> optionalVpn =
1454 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1456 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1458 if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
1459 vpns.add(optionalVpn.get());
1462 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1463 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1467 for (VpnInstance vpnInstance : vpns) {
1468 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1469 // create VpnMaps id
1470 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1471 List<String> rd = Collections.EMPTY_LIST;
1472 if (vpnInstance.getRouteDistinguisher() != null) {
1473 rd = vpnInstance.getRouteDistinguisher();
1475 List<String> ertList = new ArrayList<>();
1476 List<String> irtList = new ArrayList<>();
1478 if (vpnInstance.getVpnTargets() != null) {
1479 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1480 if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
1481 vpnTargetList = vpnInstance.getVpnTargets().getVpnTarget();
1483 if (!vpnTargetList.isEmpty()) {
1484 for (VpnTarget vpnTarget : vpnTargetList) {
1485 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1486 ertList.add(vpnTarget.getVrfRTValue());
1488 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1489 irtList.add(vpnTarget.getVrfRTValue());
1491 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1492 ertList.add(vpnTarget.getVrfRTValue());
1493 irtList.add(vpnTarget.getVrfRTValue());
1499 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1501 if (vpnInstance.getL3vni() != null) {
1502 l3vpn.setL3vni(vpnInstance.getL3vni());
1504 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1505 .class, new VpnMapKey(vpnId)).build();
1506 Optional<VpnMap> optionalVpnMap =
1507 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1509 if (optionalVpnMap.isPresent()) {
1510 VpnMap vpnMap = optionalVpnMap.get();
1511 List<Uuid> rtrIds = new ArrayList<>();
1512 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1513 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1514 rtrIds.add(rtrId.getRouterId());
1517 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1518 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1519 .setName(vpnMap.getName());
1522 l3vpnList.add(l3vpn.build());
1525 opBuilder.setL3vpnInstances(l3vpnList);
1526 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1528 } catch (ExecutionException | InterruptedException ex) {
1529 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1530 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1536 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1539 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1541 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1542 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1543 List<RpcError> errorList = new ArrayList<>();
1545 int failurecount = 0;
1546 int warningcount = 0;
1547 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1548 for (Uuid vpn : vpns) {
1550 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1551 InstanceIdentifier<VpnInstance> vpnIdentifier =
1552 InstanceIdentifier.builder(VpnInstances.class)
1553 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1554 Optional<VpnInstance> optionalVpn =
1555 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1557 if (optionalVpn.isPresent()) {
1560 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1561 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1564 } catch (ExecutionException | InterruptedException ex) {
1565 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1566 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1571 // if at least one succeeds; result is success
1572 // if none succeeds; result is failure
1573 if (failurecount + warningcount == vpns.size()) {
1574 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1576 List<String> errorResponseList = new ArrayList<>();
1577 if (!errorList.isEmpty()) {
1578 for (RpcError rpcError : errorList) {
1579 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1580 + ", ErrorMessage: " + rpcError.getMessage());
1583 errorResponseList.add("Operation successful with no errors");
1585 opBuilder.setResponse(errorResponseList);
1586 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1591 public void createVpnInstanceForSubnet(Uuid subnetId) {
1592 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1593 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1596 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1597 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1598 removeVpn(subnetId);
1601 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1602 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1603 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1604 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1606 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1607 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1610 if (vpnId != null) {
1611 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1612 if (vpnMap == null) {
1613 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1614 + " cannot add subnet {} to VPN", vpnId.getValue(),
1618 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1619 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1620 if (isVpnOfTypeL2(vpnInstance)) {
1621 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1622 NeutronEvpnUtils.Operation.ADD);
1625 if (internetVpnId != null) {
1626 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1627 if (vpnMap == null) {
1628 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1629 + "subnet {} to VPN", internetVpnId.getValue(),
1634 final Uuid internetId = internetVpnId;
1635 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1636 List<Uuid> portList = sn.getPortList();
1637 if (portList != null) {
1638 for (final Uuid portId : portList) {
1639 String vpnInfName = portId.getValue();
1640 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1641 Port port = neutronvpnUtils.getNeutronPort(portId);
1643 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1644 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1647 final Boolean isRouterInterface = port.getDeviceOwner()
1648 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1649 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1650 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1652 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1654 if (vpnIface == null) {
1655 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1656 Set<Uuid> listVpn = new HashSet<>();
1657 if (vpnId != null) {
1660 if (internetId != null) {
1661 listVpn.add(internetId);
1663 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1664 isRouterInterface, wrtConfigTxn);
1665 if (sn.getRouterId() != null) {
1666 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1669 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1670 if (vpnId != null) {
1671 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1673 if (internetId != null) {
1674 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1678 ListenableFutures.addErrorLogging(future, LOG,
1679 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1680 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1681 return Collections.singletonList(future);
1687 protected void removeSubnetFromVpn(final Uuid vpnId, Subnetmap subnetmap, @Nullable Uuid internetVpnId) {
1688 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1689 "removeSubnetFromVpn: at least one VPN must be not null");
1690 Uuid subnetId = subnetmap.getId();
1691 LOG.debug("Removing subnet {} from vpn {}/{}", subnetId.getValue(),
1692 vpnId, internetVpnId);
1693 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnetId.getValue());
1694 VpnMap vpnMap = null;
1695 VpnInstance vpnInstance = null;
1696 if (vpnId != null) {
1697 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1698 if (vpnMap == null) {
1699 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1700 vpnId.getValue(), subnetId.getValue());
1703 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1705 if (internetVpnId == null) {
1706 internetVpnId = subnetmap.getInternetVpnId();
1708 if (internetVpnId != null) {
1709 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1710 if (vpnMap == null) {
1711 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1712 + " from Internet VPN",
1713 internetVpnId.getValue(), subnetId.getValue());
1717 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1718 neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(),
1719 NeutronEvpnUtils.Operation.DELETE);
1721 boolean subnetVpnAssociation = false;
1722 if (vpnId != null && subnetmap.getVpnId() != null
1723 && subnetmap.getVpnId().getValue().equals(vpnId.getValue())) {
1724 subnetVpnAssociation = true;
1725 } else if (internetVpnId != null && subnetmap.getInternetVpnId() != null
1726 && subnetmap.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1727 subnetVpnAssociation = true;
1729 if (subnetVpnAssociation == false) {
1730 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1731 vpnId, internetVpnId, subnetmap.getVpnId(), subnetmap.getInternetVpnId());
1734 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1735 List<Uuid> portList = subnetmap.getPortList();
1736 final Uuid internetId = internetVpnId;
1737 if (portList != null) {
1738 for (final Uuid portId : portList) {
1739 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", subnetmap.getSubnetIp(), portId.getValue());
1740 final Port port = neutronvpnUtils.getNeutronPort(portId);
1741 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1742 List<ListenableFuture<Void>> futures = new ArrayList<>();
1743 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1744 CONFIGURATION, tx -> {
1746 withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx);
1748 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1749 + " port is absent in Neutron config DS", portId.getValue(),
1750 subnetId.getValue());
1753 ListenableFutures.addErrorLogging(future, LOG,
1754 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1755 + " belonging to subnet {} and vpnId {}",
1756 portId.getValue(), subnetId.getValue(), vpnId.getValue());
1757 futures.add(future);
1762 //update subnet-vpn association
1763 removeFromSubnetNode(subnetId, null, null, vpnId, null);
1766 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1767 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1768 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1770 Uuid internalVpnId = sm.getVpnId();
1771 if (internalVpnId == null) {
1772 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1773 sm.getId().getValue());
1776 if (isBeingAssociated) {
1777 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1779 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1782 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1783 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1784 if (isBeingAssociated) {
1785 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1786 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1788 removeInternetVpnFromVpnInterface(vpn,
1789 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1794 // Check for ports on this subnet and update association of
1795 // corresponding vpn-interfaces to internet vpn
1796 List<Uuid> portList = sm.getPortList();
1797 if (portList != null) {
1798 for (Uuid port : portList) {
1799 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1800 port.getValue(), isBeingAssociated);
1801 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1802 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1804 if (isBeingAssociated) {
1805 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1806 true, false, tx, true);
1808 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1816 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1817 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1818 oldVpnId.getValue(), newVpnId.getValue());
1819 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1820 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1821 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1822 Uuid vpnExtUuid = netIsExternal ? null
1823 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1824 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1826 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1829 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1830 * associated with internet BGP-VPN.
1832 if (vpnExtUuid != null) {
1833 /* Update V6 Internet default route match with new VPN metadata.
1834 * isBeingAssociated = true means oldVpnId is same as routerId
1835 * isBeingAssociated = false means newVpnId is same as routerId
1837 if (isBeingAssociated) {
1838 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1840 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1843 //Update Router Interface first synchronously.
1844 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1845 ListenableFuture<Void> future =
1846 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1847 tx -> updateVpnInterface(newVpnId, oldVpnId,
1848 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1849 isBeingAssociated, true, tx, false));
1850 Futures.addCallback(future, new FutureCallback<Void>() {
1852 public void onSuccess(Void result) {
1853 // Check for ports on this subnet and update association of
1854 // corresponding vpn-interfaces to external vpn
1855 List<Uuid> portList = sn.getPortList();
1856 if (portList != null) {
1857 for (Uuid port : portList) {
1858 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1859 port.getValue(), isBeingAssociated);
1860 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1861 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1862 tx -> updateVpnInterface(newVpnId, oldVpnId,
1863 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1870 public void onFailure(Throwable throwable) {
1872 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1874 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1876 }, MoreExecutors.directExecutor());
1881 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1882 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1883 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1886 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1887 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1888 final ReentrantLock lock = lockForUuid(routerId);
1891 Optional<RouterInterfaces> optRouterInterfaces =
1892 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1893 routerInterfacesId);
1894 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1895 .setInterfaceId(interfaceName).build();
1896 if (optRouterInterfaces.isPresent()) {
1897 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1898 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1900 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1901 List<Interfaces> interfaces = new ArrayList<>();
1902 interfaces.add(routerInterface);
1903 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1904 routerInterfacesId, builder.setInterfaces(interfaces).build());
1906 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1907 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1913 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1914 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1915 final ReentrantLock lock = lockForUuid(routerId);
1918 Optional<RouterInterfaces> optRouterInterfaces =
1919 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1920 routerInterfacesId);
1921 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1922 .setInterfaceId(interfaceName).build();
1923 if (optRouterInterfaces.isPresent()) {
1924 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1925 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
1926 if (interfaces != null && interfaces.remove(routerInterface)) {
1927 if (interfaces.isEmpty()) {
1928 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1929 routerInterfacesId);
1931 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1932 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1936 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1937 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1944 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1945 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1946 * route will be ignored.
1948 * @param vpnName the VPN identifier
1949 * @param interVpnLinkRoutes The list of static routes
1950 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1952 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1953 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1954 for (Routes route : interVpnLinkRoutes) {
1955 String nexthop = route.getNexthop().stringValue();
1956 String destination = route.getDestination().stringValue();
1957 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1958 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1959 AddStaticRouteInput rpcInput =
1960 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1961 .setVpnInstanceName(vpnName.getValue())
1963 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1964 RpcResult<AddStaticRouteOutput> rpcResult;
1966 rpcResult = labelOuputFtr.get();
1967 if (rpcResult.isSuccessful()) {
1968 LOG.debug("Label generated for destination {} is: {}",
1969 destination, rpcResult.getResult().getLabel());
1971 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1972 destination, nexthop, rpcResult.getErrors());
1974 } catch (InterruptedException | ExecutionException e) {
1975 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1976 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1979 // Any other case is a fault.
1980 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1981 route.getDestination().stringValue(), nexthop);
1988 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1989 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1991 * @param vpnName the VPN identifier
1992 * @param interVpnLinkRoutes The list of static routes
1993 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1995 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1996 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1997 for (Routes route : interVpnLinkRoutes) {
1998 String nexthop = route.getNexthop().stringValue();
1999 String destination = route.getDestination().stringValue();
2000 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2001 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2002 RemoveStaticRouteInput rpcInput =
2003 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2004 .setVpnInstanceName(vpnName.getValue())
2007 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2008 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2010 // Any other case is a fault.
2011 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2012 route.getDestination().stringValue(), nexthop);
2019 * Returns true if the specified nexthop is the other endpoint in an
2020 * InterVpnLink, regarding one of the VPN's point of view.
2022 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2023 InterVpnLink interVpnLink) {
2025 interVpnLink != null
2026 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2027 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2028 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2029 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2033 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2034 List<Adjacency> adjList = new ArrayList<>();
2035 Map<String, List<String>> adjMap = new HashMap<>();
2036 for (Routes route : routeList) {
2037 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2038 LOG.error("Incorrect input received for extra route. {}", route);
2040 String nextHop = route.getNexthop().stringValue();
2041 String destination = route.getDestination().stringValue();
2042 if (!nextHop.equals(fixedIp)) {
2043 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2046 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2048 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2049 if (!hops.contains(nextHop)) {
2055 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2056 final String destination = entry.getKey();
2057 final List<String> ipList = entry.getValue();
2058 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2059 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2060 .withKey(new AdjacencyKey(destination)).build();
2066 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2067 checkAlarmExtraRoutes(vpnId, routeList);
2069 for (Routes route : routeList) {
2070 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2071 LOG.error("Incorrect input received for extra route. {}", route);
2073 String nextHop = route.getNexthop().stringValue();
2074 String destination = route.getDestination().stringValue();
2075 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2077 if (infName != null) {
2078 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2079 destination, vpnId.getValue(), nextHop, infName);
2080 boolean isLockAcquired = false;
2082 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2083 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2084 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2085 .child(Adjacency.class, new AdjacencyKey(destination));
2086 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2087 LogicalDatastoreType.CONFIGURATION, path);
2088 if (existingAdjacency.isPresent()
2089 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2090 LOG.error("The route with destination {} nextHop {} is already present as"
2091 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2092 destination, nextHop, infName);
2095 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2096 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2097 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2099 try (AcquireResult lock = tryInterfaceLock(infName)) {
2100 if (!lock.wasAcquired()) {
2101 // FIXME: why do we even bother with locking if we do not honor it?!
2102 logTryLockFailure(infName);
2105 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2108 } catch (TransactionCommitFailedException e) {
2109 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2110 destination, nextHop, e);
2111 } catch (ExecutionException | InterruptedException e) {
2112 LOG.error("Exception on reading data-store ", e);
2115 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2116 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2123 * This method setup or down an alarm about extra route fault.
2124 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2125 * available RDs, then an alarm and an error is generated.<br>
2126 * <b>Be careful</b> the routeList could be changed.
2128 * @param vpnId the vpnId of vpn to control.
2129 * @param routeList the list of router to check, it could be modified.
2131 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2132 if (!neutronvpnAlarm.isAlarmEnabled()) {
2133 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2136 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2137 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2138 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2142 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2143 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2144 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2148 for (Routes route : routeList) {
2149 // count the number of nexthops for each same route.getDestingation().getValue()
2150 String destination = route.getDestination().stringValue();
2151 String nextHop = route.getNexthop().stringValue();
2152 List<String> nextHopList = new ArrayList<>();
2153 nextHopList.add(nextHop);
2155 for (Routes routeTmp : routeList) {
2156 String routeDest = routeTmp.getDestination().stringValue();
2157 if (!destination.equals(routeDest)) {
2160 String routeNextH = routeTmp.getNexthop().stringValue();
2161 if (nextHop.equals(routeNextH)) {
2165 nextHopList.add(routeTmp.getNexthop().stringValue());
2167 final List<String> rdList = new ArrayList<>();
2168 if (vpnInstance != null
2169 && vpnInstance.getRouteDistinguisher() != null) {
2170 vpnInstance.getRouteDistinguisher().forEach(rd -> {
2176 // 1. VPN Instance Name
2177 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2180 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2181 Uuid routerUuid = routerUuidList.get(0);
2182 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2183 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2185 // 3. List of RDs associated with the VPN
2186 detailsAlarm.append(" List of RDs associated with the VPN: ");
2187 for (String s : rdList) {
2188 detailsAlarm.append(s);
2189 detailsAlarm.append(", ");
2192 // 4. Prefix in question
2193 detailsAlarm.append(" for prefix: ");
2194 detailsAlarm.append(route.getDestination().stringValue());
2196 // 5. List of NHs for the prefix
2197 detailsAlarm.append(" for nextHops: ");
2198 for (String s : nextHopList) {
2199 detailsAlarm.append(s);
2200 detailsAlarm.append(", ");
2203 if (rdList.size() < nbNextHops) {
2204 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2206 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2211 // TODO Clean up the exception handling
2212 @SuppressWarnings("checkstyle:IllegalCatch")
2213 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2214 for (Routes route : routeList) {
2215 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2216 String nextHop = route.getNexthop().stringValue();
2217 String destination = route.getDestination().stringValue();
2218 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2220 if (infName == null) {
2221 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2222 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2223 // Proceed to remove the next extra-route
2226 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2227 destination, vpnId.getValue(), nextHop, infName);
2229 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2230 InstanceIdentifier.builder(VpnInterfaces.class)
2231 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2232 .augmentation(Adjacencies.class)
2233 .child(Adjacency.class, new AdjacencyKey(destination))
2237 // Looking for existing prefix in MDSAL database
2238 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2239 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2240 boolean updateNextHops = false;
2241 List<String> nextHopList = new ArrayList<>();
2242 if (adjacency.isPresent()) {
2243 List<String> nhListRead = adjacency.get().getNextHopIpList();
2244 if (nhListRead.size() > 1) { // ECMP case
2245 for (String nextHopRead : nhListRead) {
2246 if (nextHopRead.equals(nextHop)) {
2247 updateNextHops = true;
2249 nextHopList.add(nextHopRead);
2255 try (AcquireResult lock = tryInterfaceLock(infName)) {
2256 if (!lock.wasAcquired()) {
2257 // FIXME: why do we even bother with locking if we do not honor it?!
2258 logTryLockFailure(infName);
2261 if (updateNextHops) {
2262 // An update must be done, not including the current next hop
2263 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2264 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2265 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2266 .setNextHopIpList(nextHopList)
2267 .withKey(new AdjacencyKey(destination))
2269 Adjacencies erAdjs =
2270 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2271 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2272 .addAugmentation(Adjacencies.class, erAdjs).build();
2273 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2274 vpnIfIdentifier, vpnIf);
2276 // Remove the whole route
2277 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2278 adjacencyIdentifier);
2279 LOG.trace("extra route {} deleted successfully", route);
2282 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
2283 LOG.error("exception in deleting extra route with destination {} for interface {}",
2284 destination, infName, e);
2287 LOG.error("Incorrect input received for extra route: {}", route);
2292 public void removeVpn(Uuid vpnId) {
2294 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2295 if (vpnMap != null) {
2296 List<RouterIds> routerIdsList = vpnMap.getRouterIds();
2297 List<Uuid> routerUuidList = new ArrayList<>();
2298 // dissociate router
2299 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2300 for (RouterIds router : routerIdsList) {
2301 Uuid routerId = router.getRouterId();
2302 routerUuidList.add(routerId);
2303 dissociateRouterFromVpn(vpnId, routerId);
2306 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2307 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2310 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2312 // remove entire vpnMaps node
2313 deleteVpnMapsNode(vpnId);
2315 // remove vpn-instance
2316 deleteVpnInstance(vpnId);
2317 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2320 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2321 return vpnInstance != null && vpnInstance.isL2vpn();
2324 // TODO Clean up the exception handling
2325 @SuppressWarnings("checkstyle:IllegalCatch")
2326 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2327 updateVpnMaps(vpnId, null, routerId, null, null);
2328 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2329 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2330 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2331 for (Subnetmap sn : subMapList) {
2332 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2333 if (!ipVersion.isIpVersionChosen(ipVers)) {
2334 ipVersion = ipVersion.addVersion(ipVers);
2337 if (ipVersion != IpVersionChoice.UNDEFINED) {
2338 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2340 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2342 for (Subnetmap sn : subMapList) {
2343 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2347 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2348 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2349 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2350 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2351 for (Uuid subnet : routerSubnets) {
2352 IpVersionChoice version = NeutronvpnUtils
2353 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2354 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2355 addSubnetToVpn(vpnId, subnet, null);
2357 addSubnetToVpn(vpnId, subnet, internetVpnId);
2362 // TODO Clean up the exception handling
2363 @SuppressWarnings("checkstyle:IllegalCatch")
2364 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2366 clearFromVpnMaps(vpnId, routerId, null);
2367 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2368 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2369 for (Subnetmap sn : subMapList) {
2370 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2371 if (ipVersion.isIpVersionChosen(ipVers)) {
2372 ipVersion = ipVersion.addVersion(ipVers);
2374 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2375 routerId.getValue());
2376 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2378 if (ipVersion != IpVersionChoice.UNDEFINED) {
2379 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2381 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2387 * Parses and associates networks list with given VPN.
2389 * @param vpnId Uuid of given VPN.
2390 * @param networkList List list of network Ids (Uuid), which will be associated.
2391 * @return list of formatted strings with detailed error messages.
2394 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2395 List<String> failedNwList = new ArrayList<>();
2396 HashSet<Uuid> passedNwList = new HashSet<>();
2397 boolean isExternalNetwork = false;
2398 if (networkList.isEmpty()) {
2399 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2400 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2402 return failedNwList;
2404 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2405 if (vpnInstance == null) {
2406 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2407 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2408 + "in ConfigDS", vpnId.getValue()));
2409 return failedNwList;
2412 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2413 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2415 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2416 + "associated with", vpnId.getValue()));
2417 return failedNwList;
2419 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2420 for (Uuid nw : networkList) {
2421 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2422 if (network == null) {
2423 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2424 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2428 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2429 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2430 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2431 nw.getValue(), vpnId.getValue());
2432 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2433 nw.getValue(), vpnId.getValue()));
2436 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2437 if (networkVpnId != null) {
2438 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2439 nw.getValue(), networkVpnId.getValue());
2440 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2441 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2444 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2445 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2446 nw.getValue(), vpnId.getValue());
2447 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2448 nw.getValue(), vpnId.getValue()));
2451 if (NeutronvpnUtils.getIsExternal(network)) {
2452 isExternalNetwork = true;
2454 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2455 if (subnetmapList == null || subnetmapList.isEmpty()) {
2456 passedNwList.add(nw);
2459 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2462 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2463 for (Subnetmap subnetmap : subnetmapList) {
2464 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2465 if (!ipVersion.isIpVersionChosen(ipVers)) {
2466 ipVersion = ipVersion.addVersion(ipVers);
2469 if (ipVersion != IpVersionChoice.UNDEFINED) {
2470 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2471 + " for VPN {} ", ipVersion, vpnId);
2472 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2474 for (Subnetmap subnetmap : subnetmapList) {
2475 Uuid subnetId = subnetmap.getId();
2476 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2477 if (subnetVpnId != null) {
2478 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2479 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2480 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2481 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2484 if (!NeutronvpnUtils.getIsExternal(network)) {
2485 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2487 addSubnetToVpn(vpnId, subnetId, null);
2488 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2490 passedNwList.add(nw);
2493 passedNwList.add(nw);
2495 } catch (ExecutionException | InterruptedException e) {
2496 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2498 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2501 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2502 if (!isExternalNetwork) {
2503 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2505 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2506 return failedNwList;
2509 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2510 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2513 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2514 if (vpnOpDataEntry == null) {
2515 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2518 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2519 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2520 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2522 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2523 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2524 updateVpnMaps(vpnId, null, null, null, extNwList);
2525 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2526 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2527 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2529 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2532 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2533 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2536 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2537 updateVpnInternetForSubnet(sm, vpnId, true);
2539 if (!ipVersion.isIpVersionChosen(ipVers)) {
2540 ipVersion = ipVersion.addVersion(ipVers);
2543 if (ipVersion != IpVersionChoice.UNDEFINED) {
2544 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2545 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2546 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2552 * Parses and disassociates networks list from given VPN.
2554 * @param vpnId Uuid of given VPN.
2555 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2556 * @return list of formatted strings with detailed error messages.
2559 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2560 List<String> failedNwList = new ArrayList<>();
2561 HashSet<Uuid> passedNwList = new HashSet<>();
2562 if (networkList.isEmpty()) {
2563 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2564 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2566 return failedNwList;
2568 for (Uuid nw : networkList) {
2569 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2570 if (networkSubnets == null) {
2571 passedNwList.add(nw);
2574 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2575 if (network == null) {
2576 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2577 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2581 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2582 if (networkVpnId == null) {
2583 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2584 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2588 if (!vpnId.equals(networkVpnId)) {
2589 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2590 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2591 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2592 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2596 if (NeutronvpnUtils.getIsExternal(network)) {
2597 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2598 passedNwList.add(nw);
2600 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2601 nw.getValue(), vpnId.getValue());
2602 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2607 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2608 for (Uuid subnet : networkSubnets) {
2609 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2610 if (subnetmap == null) {
2611 failedNwList.add(String.format("subnetmap %s not found for network %s",
2612 subnet.getValue(), nw.getValue()));
2613 LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when "
2614 + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(),
2618 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2619 if (!ipVersion.isIpVersionChosen(ipVers)) {
2620 ipVersion = ipVersion.addVersion(ipVers);
2622 if (!NeutronvpnUtils.getIsExternal(network)) {
2623 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2625 removeSubnetFromVpn(vpnId, subnetmap, null);
2626 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2627 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2629 passedNwList.add(nw);
2632 if (ipVersion != IpVersionChoice.UNDEFINED) {
2633 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2634 + " for VPN {}", ipVersion, vpnId);
2635 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2638 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2639 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2640 passedNwList, vpnId.getValue());
2641 return failedNwList;
2644 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2645 if (!removeExternalNetworkFromVpn(extNet)) {
2648 // check, if there is another Provider Networks associated with given VPN
2649 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2650 if (vpnNets != null) {
2651 //Remove currently disassociated network from the list
2652 vpnNets.remove(extNet.getUuid());
2653 for (Uuid netId : vpnNets) {
2654 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2655 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2656 + "{}", vpnId.getValue(), netId.getValue());
2661 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2662 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2663 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2664 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2665 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2666 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2667 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2669 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2672 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2673 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2676 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2677 updateVpnInternetForSubnet(sm, vpnId, false);
2679 if (!ipVersion.isIpVersionChosen(ipVers)) {
2680 ipVersion = ipVersion.addVersion(ipVers);
2683 if (ipVersion != IpVersionChoice.UNDEFINED) {
2684 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2685 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2687 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2693 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2696 // TODO Clean up the exception handling
2697 @SuppressWarnings("checkstyle:IllegalCatch")
2698 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2700 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2701 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2702 StringBuilder returnMsg = new StringBuilder();
2703 Uuid vpnId = input.getVpnId();
2706 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2707 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2708 input.getNetworkId());
2709 List<Uuid> netIds = input.getNetworkId();
2710 if (netIds != null && !netIds.isEmpty()) {
2711 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2712 if (!failed.isEmpty()) {
2713 returnMsg.append(failed);
2717 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2719 if (returnMsg.length() != 0) {
2720 opBuilder.setResponse(
2721 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2722 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2723 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2725 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2727 } catch (Exception ex) {
2728 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2729 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2730 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2731 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2733 LOG.debug("associateNetworks returns..");
2738 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2741 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2743 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2744 LOG.debug("associateRouter {}", input);
2745 StringBuilder returnMsg = new StringBuilder();
2746 Uuid vpnId = input.getVpnId();
2747 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2748 routerIds = input.getRouterIds();
2749 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2750 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2751 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2752 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2753 .RouterIds routerId : routerIds) {
2754 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2755 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2756 if (vpnMap != null) {
2758 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2759 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2760 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2761 .append(routerId.getRouterId());
2762 } else if (extVpnId != null) {
2763 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2764 + "another VPN ").append(extVpnId.getValue());
2766 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2767 routerId.getRouterId());
2768 associateRouterToVpn(vpnId, routerId.getRouterId());
2771 returnMsg.append("router not found : ").append(routerId.getRouterId());
2774 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2776 if (returnMsg.length() != 0) {
2777 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2778 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2779 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2781 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2784 LOG.debug("associateRouter returns..");
2789 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2792 // TODO Clean up the exception handling
2793 @SuppressWarnings("checkstyle:IllegalCatch")
2794 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2795 GetFixedIPsForNeutronPortInput input) {
2796 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2797 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2798 Uuid portId = input.getPortId();
2799 StringBuilder returnMsg = new StringBuilder();
2801 List<String> fixedIPList = new ArrayList<>();
2802 Port port = neutronvpnUtils.getNeutronPort(portId);
2804 for (FixedIps ip : port.nonnullFixedIps()) {
2805 fixedIPList.add(ip.getIpAddress().stringValue());
2808 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2810 if (returnMsg.length() != 0) {
2811 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2813 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2814 returnMsg)).build());
2816 opBuilder.setFixedIPs(fixedIPList);
2817 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2819 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2821 } catch (Exception ex) {
2822 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2823 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2824 portId.getValue(), ex.getMessage(), ex)).build());
2830 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2833 // TODO Clean up the exception handling
2834 @SuppressWarnings("checkstyle:IllegalCatch")
2835 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2837 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2838 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2840 LOG.debug("dissociateNetworks {}", input);
2841 StringBuilder returnMsg = new StringBuilder();
2842 Uuid vpnId = input.getVpnId();
2845 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2846 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2847 input.getNetworkId());
2848 List<Uuid> netIds = input.getNetworkId();
2849 if (netIds != null && !netIds.isEmpty()) {
2850 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2851 if (!failed.isEmpty()) {
2852 returnMsg.append(failed);
2856 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2858 if (returnMsg.length() != 0) {
2859 opBuilder.setResponse(
2860 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2861 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2863 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2865 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2867 } catch (Exception ex) {
2868 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2869 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2870 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2872 LOG.debug("dissociateNetworks returns..");
2877 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2880 // TODO Clean up the exception handling
2881 @SuppressWarnings("checkstyle:IllegalCatch")
2882 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2884 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2886 LOG.debug("dissociateRouter {}", input);
2887 StringBuilder returnMsg = new StringBuilder();
2888 Uuid vpnId = input.getVpnId();
2889 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2890 .RouterIds> routerIdList = input.getRouterIds();
2891 String routerIdsString = "";
2892 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2893 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2894 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2895 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2896 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2897 .RouterIds routerId : routerIdList) {
2899 if (routerId != null) {
2900 routerIdsString += routerId.getRouterId() + ", ";
2901 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2903 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2904 if (routerVpnId == null) {
2905 returnMsg.append("input router ").append(routerId.getRouterId())
2906 .append(" not associated to any vpn yet");
2907 } else if (vpnId.equals(routerVpnId)) {
2908 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2910 returnMsg.append("input router ").append(routerId.getRouterId())
2911 .append(" associated to vpn ")
2912 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2915 returnMsg.append("router not found : ").append(routerId.getRouterId());
2918 if (returnMsg.length() != 0) {
2919 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2920 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2921 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2922 returnMsg)).build());
2924 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2926 } catch (Exception ex) {
2927 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2928 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2929 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2933 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2936 LOG.debug("dissociateRouter returns..");
2940 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2941 // check if the router is associated to some VPN
2942 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2943 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2944 if (vpnId != null) {
2945 // remove existing external vpn interfaces
2946 for (Uuid subnetId : routerSubnetIds) {
2947 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
2948 if (subnetmap != null) {
2949 removeSubnetFromVpn(vpnId, subnetmap, internetVpnId);
2951 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
2952 subnetId, routerId.getValue());
2955 clearFromVpnMaps(vpnId, routerId, null);
2957 // remove existing internal vpn interfaces
2958 for (Uuid subnetId : routerSubnetIds) {
2959 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
2960 if (subnetmap != null) {
2961 removeSubnetFromVpn(routerId, subnetmap, internetVpnId);
2963 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
2964 subnetId, routerId.getValue());
2968 // delete entire vpnMaps node for internal VPN
2969 deleteVpnMapsNode(routerId);
2971 // delete vpn-instance for internal VPN
2972 deleteVpnInstance(routerId);
2975 protected Subnet getNeutronSubnet(Uuid subnetId) {
2976 return neutronvpnUtils.getNeutronSubnet(subnetId);
2980 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2981 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2983 return sn.getGatewayIp();
2989 protected Network getNeutronNetwork(Uuid networkId) {
2990 return neutronvpnUtils.getNeutronNetwork(networkId);
2993 protected Port getNeutronPort(String name) {
2994 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2997 protected Port getNeutronPort(Uuid portId) {
2998 return neutronvpnUtils.getNeutronPort(portId);
3001 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3002 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3005 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3006 return neutronvpnUtils.getNetworksForVpn(vpnId);
3010 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3012 * @return a List of String to be printed on screen
3013 * @throws ExecutionException or InterruptedException if there was a problem reading from the data store
3015 public List<String> showNeutronPortsCLI() throws ExecutionException, InterruptedException {
3016 List<String> result = new ArrayList<>();
3017 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3019 result.add("-------------------------------------------------------------------------------------------");
3020 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3022 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3023 if (ports.isPresent() && ports.get().getPort() != null) {
3024 for (Port port : ports.get().nonnullPort()) {
3025 List<FixedIps> fixedIPs = port.getFixedIps();
3026 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3027 List<String> ipList = new ArrayList<>();
3028 for (FixedIps fixedIp : fixedIPs) {
3029 IpAddress ipAddress = fixedIp.getIpAddress();
3030 if (ipAddress.getIpv4Address() != null) {
3031 ipList.add(ipAddress.getIpv4Address().getValue());
3033 ipList.add(ipAddress.getIpv6Address().getValue());
3036 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3037 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3038 ipList.toString()));
3040 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3041 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3050 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3052 * @param vpnuuid Uuid of the VPN whose config must be shown
3053 * @return formatted output list
3054 * @throws InterruptedException if there was a thread related problem getting the data to display
3055 * @throws ExecutionException if there was any other problem getting the data to display
3057 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3058 List<String> result = new ArrayList<>();
3059 if (vpnuuid == null) {
3061 result.add("Displaying VPN config for all VPNs");
3062 result.add("To display VPN config for a particular VPN, use the following syntax");
3063 result.add(getshowVpnConfigCLIHelp());
3065 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3066 if (rpcResult.isSuccessful()) {
3068 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3070 result.add(String.format(" %-80s ", "Import-RTs"));
3072 result.add(String.format(" %-80s ", "Export-RTs"));
3074 result.add(String.format(" %-76s ", "Subnet IDs"));
3076 result.add("------------------------------------------------------------------------------------");
3078 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3079 rpcResult.getResult().nonnullL3vpnInstances()) {
3080 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3082 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3083 vpn.getRouteDistinguisher()));
3085 result.add(String.format(" %-80s ", vpn.getImportRT()));
3087 result.add(String.format(" %-80s ", vpn.getExportRT()));
3090 Uuid vpnid = vpn.getId();
3091 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3092 if (!subnetList.isEmpty()) {
3093 for (Uuid subnetuuid : subnetList) {
3094 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3097 result.add(String.format(" %-76s ", "\" \""));
3100 result.add("----------------------------------------");
3104 String errortag = rpcResult.getErrors().iterator().next().getTag();
3105 if (Objects.equals(errortag, "")) {
3107 result.add("No VPN has been configured yet");
3108 } else if (Objects.equals(errortag, "invalid-value")) {
3110 result.add("VPN " + vpnuuid.getValue() + " is not present");
3112 result.add("error getting VPN info : " + rpcResult.getErrors());
3113 result.add(getshowVpnConfigCLIHelp());
3119 protected void createExternalVpnInterfaces(Uuid extNetId) {
3120 if (extNetId == null) {
3121 LOG.error("createExternalVpnInterfaces: external network is null");
3125 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3126 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3127 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3131 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3132 for (String elanInterface : extElanInterfaces) {
3133 createExternalVpnInterface(extNetId, elanInterface, tx);
3135 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3138 // TODO Clean up the exception handling
3139 @SuppressWarnings("checkstyle:IllegalCatch")
3140 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3141 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3142 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3143 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3146 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3147 for (String elanInterface : extElanInterfaces) {
3148 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3149 .buildVpnInterfaceIdentifier(elanInterface);
3150 LOG.info("Removing vpn interface {}", elanInterface);
3151 tx.delete(vpnIfIdentifier);
3153 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3156 private void createExternalVpnInterface(Uuid vpnId, String infName,
3157 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3158 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3159 false /* not a router iface */, wrtConfigTxn);
3162 // TODO Clean up the exception handling
3163 @SuppressWarnings("checkstyle:IllegalCatch")
3164 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3165 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3166 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3167 if (vpnIdList.isEmpty() || infName == null) {
3168 LOG.error("vpnid is empty or interface({}) is null", infName);
3171 if (wrtConfigTxn == null) {
3172 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3173 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3174 "Error writing VPN interface");
3177 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3178 for (Uuid vpnId: vpnIdList) {
3179 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3180 AssociatedSubnetType.V4AndV6Subnets);
3181 vpnIdListStruct.add(vpnInstance);
3184 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3185 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3187 .setVpnInstanceNames(vpnIdListStruct)
3188 .setRouterInterface(isRouterInterface);
3189 LOG.info("Network Id is {}", networkUuid);
3190 if (networkUuid != null) {
3191 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3192 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3193 NetworkAttributes.NetworkType networkType = providerType != null
3194 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3195 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3196 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3197 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3200 if (adjacencies != null) {
3201 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3203 VpnInterface vpnIf = vpnb.build();
3205 LOG.info("Creating vpn interface {}", vpnIf);
3206 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3207 } catch (Exception ex) {
3208 LOG.error("Creation of vpninterface {} failed", infName, ex);
3212 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3213 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3214 if (vpnId == null || infName == null) {
3215 LOG.error("vpn id or interface is null");
3218 if (wrtConfigTxn == null) {
3219 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3220 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3221 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3222 }), LOG, "Error updating VPN interface with adjacencies");
3226 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3228 try (AcquireResult lock = tryInterfaceLock(infName)) {
3229 if (!lock.wasAcquired()) {
3230 // FIXME: why do we even bother with locking if we do not honor it?!
3231 logTryLockFailure(infName);
3235 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3236 .syncReadOptional(dataBroker, LogicalDatastoreType
3237 .CONFIGURATION, vpnIfIdentifier);
3238 if (optionalVpnInterface.isPresent()) {
3239 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3240 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3242 if (adjacencies == null) {
3245 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3246 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3247 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3248 optionalVpnInterface.get().getVpnInstanceNames());
3249 if (listVpnInstances.isEmpty()
3250 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3251 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3252 AssociatedSubnetType.V4AndV6Subnets);
3253 listVpnInstances.add(vpnInstance);
3254 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3257 VpnInstanceNames vpnInstance = VpnHelper
3258 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3259 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3260 listVpnInstances.add(vpnInstance);
3261 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3263 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3264 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3266 } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
3267 // FIXME: why are we catching IllegalStateException here?
3268 LOG.error("Update of vpninterface {} failed", infName, ex);
3273 private String getshowVpnConfigCLIHelp() {
3274 StringBuilder help = new StringBuilder("Usage:");
3275 help.append("display vpn-config [-vid/--vpnid <id>]");
3276 return help.toString();
3279 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3280 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3284 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3285 return neutronEvpnManager.createEVPN(input);
3289 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3290 return neutronEvpnManager.getEVPN(input);
3294 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3295 return neutronEvpnManager.deleteEVPN(input);
3298 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3299 Uuid extNetId = extNet.getUuid();
3300 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3301 .child(Networks.class, new NetworksKey(extNetId)).build();
3304 Optional<Networks> optionalExtNets =
3305 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3307 if (!optionalExtNets.isPresent()) {
3308 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3309 extNetId.getValue());
3312 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3313 builder.setVpnid(vpnId);
3314 Networks networks = builder.build();
3315 // Add Networks object to the ExternalNetworks list
3316 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3317 extNetId.getValue());
3318 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3321 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3322 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3323 extNetId.getValue(), ex);
3328 private boolean removeExternalNetworkFromVpn(Network extNet) {
3329 Uuid extNetId = extNet.getUuid();
3330 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3331 .child(Networks.class, new NetworksKey(extNetId)).build();
3333 Optional<Networks> optionalNets =
3334 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3336 NetworksBuilder builder = null;
3337 if (optionalNets.isPresent()) {
3338 builder = new NetworksBuilder(optionalNets.get());
3340 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3341 extNetId.getValue());
3344 builder.setVpnid(null);
3345 Networks networks = builder.build();
3346 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3347 extNetId.getValue());
3348 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3350 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3351 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3352 extNetId.getValue(), ex);
3357 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3358 Optional<String> existingVpnName = Optional.of(primaryRd);
3359 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3361 vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3362 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3363 } catch (ExecutionException | InterruptedException e) {
3364 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3366 /*Read failed. We don't know if a VPN exists or not.
3367 * Return primaryRd to halt caller execution, to be safe.*/
3368 return existingVpnName;
3370 if (vpnInstanceOpDataOptional.isPresent()) {
3371 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3373 existingVpnName = Optional.empty();
3375 return existingVpnName;
3378 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3379 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3382 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3383 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3386 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3387 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3390 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3391 String message = tuple.getMessage();
3392 logger.accept(message);
3396 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3397 @NonNull Subnetmap subnetMap) {
3398 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3399 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3400 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3401 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3402 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3403 subnetMap.getId().getValue(), internetVpnId.getValue());
3407 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3408 @NonNull Subnetmap subnetMap) {
3409 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3410 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3413 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3414 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3415 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3416 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3417 internetVpnId.getValue(), routerId.getValue());
3418 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3424 private AcquireResult tryInterfaceLock(final String infName) {
3425 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3429 private AcquireResult tryVpnLock(final Uuid vpnId) {
3430 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3433 private static ReentrantLock lockForUuid(Uuid uuid) {
3434 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3435 return JvmGlobalLocks.getLockForString(uuid.getValue());
3438 private static void logTryLockFailure(Object objectId) {
3439 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());