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.ConcurrentMap;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.Future;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.locks.ReentrantLock;
41 import java.util.function.Consumer;
42 import java.util.stream.Collectors;
43 import javax.annotation.PreDestroy;
44 import javax.inject.Inject;
45 import javax.inject.Singleton;
46 import org.eclipse.jdt.annotation.NonNull;
47 import org.eclipse.jdt.annotation.Nullable;
48 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
49 import org.opendaylight.genius.infra.Datastore.Configuration;
50 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
51 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
52 import org.opendaylight.genius.infra.TypedWriteTransaction;
53 import org.opendaylight.genius.mdsalutil.NwConstants;
54 import org.opendaylight.genius.utils.JvmGlobalLocks;
55 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
56 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
57 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
58 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
59 import org.opendaylight.mdsal.binding.api.DataBroker;
60 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
61 import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
62 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
63 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
64 import org.opendaylight.netvirt.elanmanager.api.IElanService;
65 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
66 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
67 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
68 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
69 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
70 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
71 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNamesKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsKey;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
181 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
182 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
183 import org.opendaylight.yangtools.yang.common.RpcError;
184 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
185 import org.opendaylight.yangtools.yang.common.RpcResult;
186 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
187 import org.slf4j.Logger;
188 import org.slf4j.LoggerFactory;
189 import org.slf4j.helpers.FormattingTuple;
190 import org.slf4j.helpers.MessageFormatter;
193 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
195 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
196 private static final long LOCK_WAIT_TIME = 10L;
198 private final DataBroker dataBroker;
199 private final ManagedNewTransactionRunner txRunner;
200 private final VpnRpcService vpnRpcService;
201 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
202 private final IElanService elanService;
203 private final NeutronvpnConfig neutronvpnConfig;
204 private final NeutronEvpnManager neutronEvpnManager;
205 private final NeutronEvpnUtils neutronEvpnUtils;
206 private final JobCoordinator jobCoordinator;
207 private final NeutronvpnUtils neutronvpnUtils;
208 private final IVpnManager vpnManager;
209 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
210 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
211 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
212 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
215 public NeutronvpnManager(
216 final DataBroker dataBroker,
217 final VpnRpcService vpnRpcSrv, final IElanService elanService,
218 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
219 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
220 final JobCoordinator jobCoordinator,
221 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
222 this.dataBroker = dataBroker;
223 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
224 vpnRpcService = vpnRpcSrv;
225 this.elanService = elanService;
226 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
227 this.neutronvpnConfig = neutronvpnConfig;
228 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
229 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
230 this.jobCoordinator = jobCoordinator;
231 this.neutronvpnUtils = neutronvpnUtils;
232 this.vpnManager = vpnManager;
239 public void close() {
240 LOG.info("{} close", getClass().getSimpleName());
243 private void configureFeatures() throws TransactionCommitFailedException {
244 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
245 Neutron.class).child(Features.class).child(
246 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
247 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
249 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
250 } catch (OptimisticLockFailedException e) {
251 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
253 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
254 Neutron.class).child(Features.class).child(
255 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
256 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
258 SingleTransactionDataBroker.syncWrite(
259 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
260 } catch (OptimisticLockFailedException e) {
261 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
265 public String getOpenDaylightVniRangesConfig() {
266 return neutronvpnConfig.getOpendaylightVniRanges();
269 // TODO Clean up the exception handling
270 @SuppressWarnings("checkstyle:IllegalCatch")
271 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
272 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
273 boolean isExternalNw) {
275 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
276 final ReentrantLock lock = lockForUuid(subnetId);
279 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
280 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
281 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
282 if (sn.isPresent()) {
283 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
284 subnetId.getValue());
287 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
288 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
289 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
290 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
291 subnetId.getValue());
292 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
293 subnetMapIdentifier, subnetmapBuilder.build());
297 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
298 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
300 // check if there are ports to update for already created Subnetmap node
301 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
302 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
303 if (entry.getValue().getValue().equals(subnetId.getValue())) {
304 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
305 unprocessedPortsMap.remove(entry.getKey());
311 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
312 @Nullable Uuid internetvpnId) {
313 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
314 .child(Subnetmap.class, new SubnetmapKey(subnetId))
316 final ReentrantLock lock = lockForUuid(subnetId);
319 Optional<Subnetmap> sn =
320 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
321 if (!sn.isPresent()) {
322 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
325 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
326 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
327 if (routerId != null) {
328 builder.setRouterId(routerId);
331 builder.setVpnId(vpnId);
333 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
334 builder.setInternetVpnId(internetvpnId);
336 Subnetmap subnetmap = builder.build();
337 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
338 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
340 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
341 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
348 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
349 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
350 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
351 InstanceIdentifier<Subnetmap> id =
352 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
353 final ReentrantLock lock = lockForUuid(subnetId);
356 Optional<Subnetmap> sn =
357 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
358 if (!sn.isPresent()) {
359 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
360 subnetId.getValue());
363 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
364 subnetId.getValue());
365 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
366 builder.setRouterId(routerId);
367 builder.setRouterInterfacePortId(routerInterfacePortId);
368 builder.setRouterIntfMacAddress(routerIntfMacAddress);
369 builder.setRouterInterfaceFixedIp(fixedIp);
371 builder.setVpnId(vpnId);
373 Subnetmap subnetmap = builder.build();
374 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
375 subnetId.getValue());
376 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
377 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
378 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
379 subnetId.getValue(), e);
385 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
386 @Nullable Uuid directPortId) {
387 Subnetmap subnetmap = null;
388 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
389 new SubnetmapKey(subnetId)).build();
390 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
391 final ReentrantLock lock = lockForUuid(subnetId);
394 Optional<Subnetmap> sn =
395 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
397 if (sn.isPresent()) {
398 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
399 if (null != portId) {
400 List<Uuid> existingPortList = builder.getPortList();
401 List<Uuid> portList = new ArrayList<>();
402 if (null != existingPortList) {
403 portList.addAll(existingPortList);
405 portList.add(portId);
406 builder.setPortList(portList);
407 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
408 subnetId.getValue(), portId.getValue());
410 if (null != directPortId) {
411 List<Uuid> existingDirectPortList = builder.getDirectPortList();
412 List<Uuid> directPortList = new ArrayList<>();
413 if (null != existingDirectPortList) {
414 directPortList.addAll(existingDirectPortList);
416 directPortList.add(directPortId);
417 builder.setDirectPortList(directPortList);
418 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
419 directPortId.getValue());
421 subnetmap = builder.build();
422 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
425 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
426 + "cache ", subnetId.getValue(), portId.getValue());
427 unprocessedPortsMap.put(portId, subnetId);
429 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
430 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
437 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
438 Uuid vpnId, @Nullable Uuid portId) {
439 Subnetmap subnetmap = null;
440 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
441 .child(Subnetmap.class, new SubnetmapKey(subnetId))
443 final ReentrantLock lock = lockForUuid(subnetId);
446 Optional<Subnetmap> sn =
447 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
449 if (sn.isPresent()) {
450 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
451 if (routerId != null) {
452 builder.setRouterId(null);
454 if (networkId != null) {
455 builder.setNetworkId(null);
458 builder.setVpnId(null);
460 builder.setInternetVpnId(null);
461 if (portId != null && builder.getPortList() != null) {
462 List<Uuid> portList = new ArrayList<>(builder.getPortList());
463 portList.remove(portId);
464 builder.setPortList(portList);
467 subnetmap = builder.build();
468 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
469 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
472 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
474 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
475 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
483 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
484 @Nullable Uuid directPortId) {
485 Subnetmap subnetmap = null;
486 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
487 new SubnetmapKey(subnetId)).build();
488 final ReentrantLock lock = lockForUuid(subnetId);
491 Optional<Subnetmap> sn =
492 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
494 if (sn.isPresent()) {
495 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
496 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
497 List<Uuid> portList = new ArrayList<>(builder.getPortList());
498 portList.remove(portId);
499 builder.setPortList(portList);
500 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
501 subnetId.getValue());
503 if (null != directPortId && null != builder.getDirectPortList()
504 && !builder.getDirectPortList().isEmpty()) {
505 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
506 directPortList.remove(directPortId);
507 builder.setDirectPortList(directPortList);
508 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
509 .getValue(), subnetId.getValue());
511 subnetmap = builder.build();
512 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
515 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
517 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
518 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
519 subnetId.getValue(), e);
526 // TODO Clean up the exception handling
527 @SuppressWarnings("checkstyle:IllegalCatch")
528 protected void deleteSubnetMapNode(Uuid subnetId) {
529 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
530 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
531 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
532 final ReentrantLock lock = lockForUuid(subnetId);
535 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
536 } catch (TransactionCommitFailedException e) {
537 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
543 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
544 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
545 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
547 Optional<VpnInstance> vpnInstanceConfig =
548 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
550 if (!vpnInstanceConfig.isPresent()) {
551 LOG.debug("updateVpnInstanceWithRDs: "
552 + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
555 VpnInstance vpnInstance = vpnInstanceConfig.get();
556 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
557 updateVpnInstanceBuilder.setRouteDistinguisher(rds);
558 LOG.debug("updateVpnInstanceWithRDs: "
559 + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
560 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
561 updateVpnInstanceBuilder.build());
562 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
563 LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
564 + "the list of RDs: {}", vpnInstanceId, rds, ex);
568 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
569 boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
570 String vpnName = vpnId.getValue();
571 VpnInstanceBuilder builder = null;
572 List<VpnTarget> vpnTargetList = new ArrayList<>();
573 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
574 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
575 Optional<VpnInstance> optionalVpn;
577 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
579 } catch (ExecutionException | InterruptedException e) {
580 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
584 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
585 if (optionalVpn.isPresent()) {
586 builder = new VpnInstanceBuilder(optionalVpn.get());
587 LOG.debug("updating existing vpninstance node");
589 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
590 .setL2vpn(isL2Vpn).setL3vni(l3vni).setBgpvpnType(VpnInstance.BgpvpnType.InternalVPN);
592 if (irt != null && !irt.isEmpty()) {
593 if (ert != null && !ert.isEmpty()) {
594 List<String> commonRT = new ArrayList<>(irt);
595 commonRT.retainAll(ert);
597 for (String common : commonRT) {
600 VpnTarget vpnTarget =
601 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
602 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
603 vpnTargetList.add(vpnTarget);
606 for (String importRT : irt) {
607 VpnTarget vpnTarget =
608 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
609 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
610 vpnTargetList.add(vpnTarget);
614 if (ert != null && !ert.isEmpty()) {
615 for (String exportRT : ert) {
616 VpnTarget vpnTarget =
617 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
618 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
619 vpnTargetList.add(vpnTarget);
623 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
624 if (rd != null && !rd.isEmpty()) {
625 builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets).setBgpvpnType(VpnInstance.BgpvpnType.BGPVPN);
628 builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
629 VpnInstance newVpn = builder.build();
630 try (AcquireResult lock = tryVpnLock(vpnId)) {
631 if (!lock.wasAcquired()) {
632 // FIXME: why do we even bother with locking if we do not honor it?!
633 logTryLockFailure(vpnId);
636 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
638 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
640 } catch (TransactionCommitFailedException e) {
641 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
646 private void deleteVpnMapsNode(Uuid vpnId) {
647 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
648 .child(VpnMap.class, new VpnMapKey(vpnId))
650 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
651 try (AcquireResult lock = tryVpnLock(vpnId)) {
652 if (!lock.wasAcquired()) {
653 // FIXME: why do we even bother with locking if we do not honor it?!
654 logTryLockFailure(vpnId);
658 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
660 } catch (TransactionCommitFailedException e) {
661 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
666 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
667 @Nullable List<Uuid> networks) {
668 VpnMapBuilder builder;
669 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
670 .child(VpnMap.class, new VpnMapKey(vpnId))
673 Optional<VpnMap> optionalVpnMap =
674 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
676 if (optionalVpnMap.isPresent()) {
677 builder = new VpnMapBuilder(optionalVpnMap.get());
679 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
683 builder.setName(name);
685 if (tenantId != null) {
686 builder.setTenantId(tenantId);
688 if (router != null) {
689 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
690 List<RouterIds> rtrIds = builder.getRouterIds() != null
691 ? new ArrayList<>(builder.getRouterIds().values()) : null;
692 if (rtrIds == null) {
693 rtrIds = Collections.singletonList(vpnRouterId);
695 rtrIds.add(vpnRouterId);
697 builder.setRouterIds(rtrIds);
699 if (networks != null) {
700 List<Uuid> nwList = builder.getNetworkIds() != null
701 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
702 nwList.addAll(networks);
703 builder.setNetworkIds(nwList);
706 try (AcquireResult lock = tryVpnLock(vpnId)) {
707 if (!lock.wasAcquired()) {
708 // FIXME: why do we even bother with locking if we do not honor it?!
709 logTryLockFailure(vpnId);
712 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
713 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
715 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
717 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
718 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
722 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
723 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
724 .child(VpnMap.class, new VpnMapKey(vpnId))
726 Optional<VpnMap> optionalVpnMap;
729 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
731 } catch (ExecutionException | InterruptedException e) {
732 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
735 if (optionalVpnMap.isPresent()) {
736 VpnMap vpnMap = optionalVpnMap.get();
737 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
738 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds().values());
739 if (rtrIds == null) {
740 rtrIds = new ArrayList<>();
742 if (routerId != null) {
743 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
744 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
745 vpnMapBuilder.setRouterIds(rtrIds);
747 try (AcquireResult lock = tryVpnLock(vpnId)) {
748 if (!lock.wasAcquired()) {
749 // FIXME: why do we even bother with locking if we do not honor it?!
750 logTryLockFailure(vpnId);
753 LOG.debug("removing vpnMaps node: {} ", vpnId);
755 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
757 } catch (TransactionCommitFailedException e) {
758 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
762 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
763 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
764 vpnMapBuilder.setRouterIds(rtrIds);
765 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
768 if (networkIds != null) {
769 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
770 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
771 vpnNw.removeAll(networkIds);
772 if (vpnNw.isEmpty()) {
773 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
774 vpnMapBuilder.setNetworkIds(null);
776 vpnMapBuilder.setNetworkIds(vpnNw);
780 try (AcquireResult lock = tryVpnLock(vpnId)) {
781 if (!lock.wasAcquired()) {
782 // FIXME: why do we even bother with locking if we do not honor it?!
783 logTryLockFailure(vpnId);
786 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
788 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
789 vpnMapIdentifier, vpnMapBuilder.build());
790 } catch (TransactionCommitFailedException e) {
791 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
795 LOG.error("VPN : {} not found", vpnId.getValue());
797 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
800 private void deleteVpnInstance(Uuid vpnId) {
801 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
802 .child(VpnInstance.class,
803 new VpnInstanceKey(vpnId.getValue()))
806 try (AcquireResult lock = tryVpnLock(vpnId)) {
807 if (!lock.wasAcquired()) {
808 // FIXME: why do we even bother with locking if we do not honor it?!
809 logTryLockFailure(vpnId);
812 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
814 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
815 } catch (TransactionCommitFailedException e) {
816 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
821 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
822 TypedWriteTransaction<Configuration> wrtConfigTxn,
823 @Nullable VpnInterface vpnIface) {
824 List<Adjacency> adjList = new ArrayList<>();
825 if (vpnIface != null) {
826 adjList = new ArrayList<Adjacency>(vpnIface.augmentation(Adjacencies.class).getAdjacency().values());
828 String infName = port.getUuid().getValue();
829 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
830 for (FixedIps ip : port.nonnullFixedIps().values()) {
831 String ipValue = ip.getIpAddress().stringValue();
832 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
833 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
834 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
835 snTemp.getSubnetIp(), false)) {
838 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
840 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
841 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
842 //Create Neutron port adjacency if VPN presence is existing for subnet
843 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
844 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
845 .setSubnetId(ip.getSubnetId()).build();
846 if (!adjList.contains(vmAdj)) {
850 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
851 if (snTemp != null && snTemp.getInternetVpnId() != null) {
852 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
853 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
855 if (routerId != null) {
856 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
857 if (rtr != null && rtr.getRoutes() != null) {
858 List<Routes> routeList = new ArrayList<Routes>(rtr.getRoutes().values());
859 // create extraroute Adjacence for each ipValue,
860 // because router can have IPv4 and IPv6 subnet ports, or can have
861 // more that one IPv4 subnet port or more than one IPv6 subnet port
862 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
863 if (!erAdjList.isEmpty()) {
864 adjList.addAll(erAdjList);
869 return new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(adjList)).build();
872 private Map<AdjacencyKey, Adjacency> getAdjacencyMap(List<Adjacency> adjList) {
873 //convert to set to remove duplicates.
874 Set<Adjacency> adjset = adjList.stream().collect(Collectors.toSet());
875 Map<AdjacencyKey, Adjacency> adjacencyMap = new HashMap<>();
876 for (Adjacency adj : adjset) {
877 adjacencyMap.put(new AdjacencyKey(adj.getIpAddress()), adj);
882 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
883 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
884 boolean isRouterInterface = false;
885 if (port.getDeviceOwner() != null) {
886 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
888 String infName = port.getUuid().getValue();
889 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
890 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
891 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
892 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
893 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
896 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
897 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
898 String infName = port.getUuid().getValue();
899 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
900 Optional<VpnInterface> optionalVpnInterface = null;
901 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
902 vpnId, internetVpnId, infName);
904 optionalVpnInterface = SingleTransactionDataBroker
905 .syncReadOptional(dataBroker, LogicalDatastoreType
906 .CONFIGURATION, vpnIfIdentifier);
907 } catch (ExecutionException | InterruptedException e) {
908 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
911 if (!optionalVpnInterface.isPresent()) {
914 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
915 sn != null ? sn.getSubnetIp() : "null");
916 Map<AdjacencyKey, Adjacency> keyAdjacencyMap
917 = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
918 List<Adjacency> updatedAdjsList = new ArrayList<>();
919 boolean isIpFromAnotherSubnet = false;
920 for (Adjacency adj : keyAdjacencyMap.values()) {
921 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
922 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
923 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
924 isIpFromAnotherSubnet = true;
926 updatedAdjsList.add(adj);
929 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
930 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
933 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
934 String.valueOf(adjString), wrtConfigTxn);
936 if (internetVpnId != null) {
937 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
938 String.valueOf(adjString), wrtConfigTxn);
941 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
942 && sn.getRouterId() != null) {
943 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
944 if (rtr != null && rtr.getRoutes() != null) {
945 List<Routes> extraRoutesToRemove = new ArrayList<>();
946 for (Routes rt: rtr.getRoutes().values()) {
947 if (rt.getNexthop().toString().equals(adjString)) {
948 extraRoutesToRemove.add(rt);
952 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
953 extraRoutesToRemove, vpnId);
954 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
956 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
961 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(updatedAdjsList)).build();
963 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
965 if (!isIpFromAnotherSubnet) {
966 // no more subnetworks for neutron port
967 if (sn != null && sn.getRouterId() != null) {
968 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
970 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
976 // TODO Clean up the exception handling
977 @SuppressWarnings("checkstyle:IllegalCatch")
978 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
979 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
980 if (wrtConfigTxn == null) {
981 LoggingFutures.addErrorLogging(
982 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
983 tx -> deleteVpnInterface(infName, vpnId, tx)),
984 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
988 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
989 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
990 Optional<VpnInterface> optionalVpnInterface;
992 optionalVpnInterface =
993 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
995 } catch (ExecutionException | InterruptedException ex) {
996 LOG.error("Error during deletion of vpninterface {}", infName, ex);
999 if (!optionalVpnInterface.isPresent()) {
1000 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
1003 if (vpnId != null) {
1004 VpnInterface vpnInterface = optionalVpnInterface.get();
1005 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap = vpnInterface.getVpnInstanceNames();
1006 if (keyVpnInstanceNamesMap != null
1007 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId,
1008 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
1009 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId,
1010 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
1011 if (!keyVpnInstanceNamesMap.isEmpty()) {
1012 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1013 + "List not empty", infName);
1016 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1017 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1018 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1022 LOG.debug("Deleting vpn interface {}", infName);
1023 wrtConfigTxn.delete(vpnIfIdentifier);
1026 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1027 TypedWriteTransaction<Configuration> writeConfigTxn,
1029 if (vpnId == null || port == null) {
1032 String infName = port.getUuid().getValue();
1033 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1035 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1036 .syncReadOptional(dataBroker, LogicalDatastoreType
1037 .CONFIGURATION, vpnIfIdentifier);
1038 if (optionalVpnInterface.isPresent()) {
1039 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap
1040 = optionalVpnInterface.get().getVpnInstanceNames();
1041 if (keyVpnInstanceNamesMap != null
1042 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),
1043 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
1044 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(),
1045 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
1047 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1048 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1049 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1050 LOG.debug("Updating vpn interface {}", infName);
1051 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency() : new HashMap<>();
1052 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1053 while (adjacencyIter.hasNext()) {
1054 Adjacency adjacency = adjacencyIter.next();
1055 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1058 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1059 InstanceIdentifier<LearntVpnVipToPort> id =
1060 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1061 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1062 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1063 LogicalDatastoreType.OPERATIONAL, id);
1064 if (optionalVpnVipToPort.isPresent()) {
1065 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1067 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1068 adjacencyIter.remove();
1070 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1071 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1072 mipToQuery, infName, vpnId.getValue());
1075 for (FixedIps ip : port.nonnullFixedIps().values()) {
1076 String ipValue = ip.getIpAddress().stringValue();
1078 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1081 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1082 ipValue, writeConfigTxn);
1084 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1085 if (sm != null && sm.getRouterId() != null) {
1086 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1088 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1090 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1093 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1095 } catch (ExecutionException | InterruptedException ex) {
1096 LOG.error("Update of vpninterface {} failed", infName, ex);
1100 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1102 TypedWriteTransaction<Configuration> writeConfigTxn,
1103 boolean isInternetVpn) {
1104 if (vpnId == null || port == null) {
1107 String infName = port.getUuid().getValue();
1108 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1110 try (AcquireResult lock = tryInterfaceLock(infName)) {
1111 if (!lock.wasAcquired()) {
1112 // FIXME: why do we even bother with locking if we do not honor it?!
1113 logTryLockFailure(infName);
1117 Optional<VpnInterface> optionalVpnInterface =
1118 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1120 if (optionalVpnInterface.isPresent()) {
1121 VpnInstanceNames vpnInstance = VpnHelper
1122 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1123 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface.get()
1124 .getVpnInstanceNames().values());
1125 if (oldVpnId != null
1126 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1127 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1129 if (vpnId.getValue() != null
1130 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1131 listVpn.add(vpnInstance);
1133 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1134 .setVpnInstanceNames(listVpn);
1135 LOG.debug("Updating vpn interface {}", infName);
1136 if (!isBeingAssociated) {
1137 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1138 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency()
1139 : new HashMap<AdjacencyKey, Adjacency>();
1140 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1141 while (adjacencyIter.hasNext()) {
1142 Adjacency adjacency = adjacencyIter.next();
1143 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1144 InstanceIdentifier<LearntVpnVipToPort> id =
1145 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1146 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1147 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1148 LogicalDatastoreType.OPERATIONAL, id);
1149 if (optionalVpnVipToPort.isPresent()
1150 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1151 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1152 + "from VPN {}", infName, vpnId, oldVpnId);
1153 adjacencyIter.remove();
1154 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1156 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1157 mipToQuery, infName, vpnId.getValue());
1159 InstanceIdentifier<VpnPortipToPort> build =
1160 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1161 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1162 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1163 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1164 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1165 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1166 mipToQuery, infName, vpnId.getValue());
1169 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(keyAdjacencyMap).build();
1170 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1172 for (FixedIps ip : port.nonnullFixedIps().values()) {
1173 String ipValue = ip.getIpAddress().stringValue();
1174 if (oldVpnId != null) {
1175 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1176 ipValue, writeConfigTxn);
1178 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1179 && isInternetVpn == true) {
1183 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1184 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1186 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1188 LOG.error("VPN Interface {} not found", infName);
1190 } catch (ExecutionException | InterruptedException ex) {
1191 LOG.error("Updation of vpninterface {} failed", infName, ex);
1196 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1197 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1199 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1201 // Update VPN Instance node
1202 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
1204 // Update local vpn-subnet DS
1205 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1207 if (routerId != null) {
1208 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1209 if (existingVpn != null) {
1210 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1211 // if before reboot, router was already associated to VPN, should not proceed associating router to
1212 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1213 // preserved upon reboot.
1214 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1215 // RouterInterfacesMap via #createVPNInterface call.
1216 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1217 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1220 associateRouterToInternalVpn(vpnId, routerId);
1225 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1226 * specified Neutron Networks and Routers.
1228 * @param vpnId Uuid of the VPN tp be created
1229 * @param name Representative name of the new VPN
1230 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1231 * @param rdList Route-distinguisher for the VPN
1232 * @param irtList A list of Import Route Targets
1233 * @param ertList A list of Export Route Targets
1234 * @param routerIdsList ist of neutron router Id to associate with created VPN
1235 * @param networkList UUID of the neutron network the VPN may be associated to
1236 * @param isL2Vpn True if VPN Instance is of type L2, false if L3
1237 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1238 * @throws Exception if association of L3VPN failed
1240 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1241 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1242 boolean isL2Vpn, long l3vni) throws Exception {
1244 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1246 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1247 for (Uuid routerId : routerIdsList) {
1248 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1249 ipVersChoices = ipVersChoices.addVersion(vers);
1252 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
1254 // Please note that router and networks will be filled into VPNMaps
1255 // by subsequent calls here to associateRouterToVpn and
1256 // associateNetworksToVpn
1257 updateVpnMaps(vpnId, name, null, tenantId, null);
1258 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1259 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1262 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1263 for (Uuid routerId : routerIdsList) {
1264 associateRouterToVpn(vpnId, routerId);
1267 if (networkList != null) {
1268 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1269 if (!failStrings.isEmpty()) {
1270 LOG.error("VPN {} association to networks failed for networks: {}. ",
1271 vpnId.getValue(), failStrings);
1272 throw new Exception(failStrings.toString());
1278 * It handles the invocations to the createVPN RPC method.
1281 // TODO Clean up the exception handling
1282 @SuppressWarnings("checkstyle:IllegalCatch")
1283 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1285 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1286 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1287 List<RpcError> errorList = new ArrayList<>();
1288 int failurecount = 0;
1289 int warningcount = 0;
1291 List<L3vpn> vpns = input.getL3vpn();
1293 vpns = Collections.emptyList();
1295 for (L3vpn vpn : vpns) {
1296 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1297 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1298 formatAndLog(LOG::warn,
1299 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1300 vpn.getId().getValue())));
1304 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1305 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1306 formatAndLog(LOG::warn,
1307 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1308 vpn.getId().getValue())));
1313 if (vpn.getL3vni() != null) {
1314 l3vni = vpn.getL3vni().toJava();
1317 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1318 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1319 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1320 formatAndLog(LOG::warn,
1321 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1322 + "is already configured",
1323 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1327 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1328 if (operationalVpn.isPresent()) {
1329 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1330 formatAndLog(LOG::error,
1331 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1332 + "is still available. Please retry creation of a new vpn with the same RD"
1333 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1334 vpn.getRouteDistinguisher().get(0))));
1338 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1339 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
1340 .neutronvpn.rev150602.vpn.instance.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight
1341 .netvirt.neutronvpn.rev150602.vpn.instance.RouterIds> keyRouterIdsMap = vpn.getRouterIds();
1342 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1343 routerId : keyRouterIdsMap.values()) {
1344 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1345 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1346 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1347 + "{}", vpn.getId(), routerId.getRouterId())));
1351 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1352 if (vpnId != null) {
1353 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1354 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1355 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1356 vpnId.getValue())));
1362 if (vpn.getNetworkIds() != null) {
1363 int initialWarningCount = warningcount;
1364 for (Uuid nw : vpn.getNetworkIds()) {
1365 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1366 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1367 if (network == null) {
1368 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1369 formatAndLog(LOG::warn,
1370 "Creation of L3VPN failed for VPN {} due to network not found {}",
1371 vpn.getId().getValue(), nw.getValue())));
1373 } else if (vpnId != null) {
1374 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1375 formatAndLog(LOG::warn,
1376 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1377 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1378 vpnId.getValue())));
1382 if (warningcount != initialWarningCount) {
1386 List<Uuid> rtrIdsList = new ArrayList<>();
1387 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1388 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1389 rtrId : vpn.getRouterIds().values()) {
1390 rtrIdsList.add(rtrId.getRouterId());
1394 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1395 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1396 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1397 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1399 List<String> rdList = vpn.getRouteDistinguisher() != null
1400 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1401 List<String> importRdList = vpn.getImportRT() != null
1402 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1403 List<String> exportRdList = vpn.getExportRT() != null
1404 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1406 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1407 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
1408 } catch (Exception ex) {
1409 LOG.error("VPN Creation exception :", ex);
1410 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1411 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1416 // if at least one succeeds; result is success
1417 // if none succeeds; result is failure
1418 if (failurecount + warningcount == vpns.size()) {
1419 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1421 List<String> errorResponseList = new ArrayList<>();
1422 if (!errorList.isEmpty()) {
1423 for (RpcError rpcError : errorList) {
1424 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1425 + ", ErrorMessage: " + rpcError.getMessage());
1428 errorResponseList.add("Operation successful with no errors");
1430 opBuilder.setResponse(errorResponseList);
1431 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1437 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1440 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1442 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1443 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1444 Uuid inputVpnId = input.getId();
1445 List<VpnInstance> vpns = new ArrayList<>();
1446 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1449 if (inputVpnId == null) {
1451 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1453 Optional<VpnInstances> optionalVpns =
1454 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1456 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1457 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance().values()) {
1458 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1459 // from getL3VPN output
1460 if (vpn.getRouteDistinguisher() != null) {
1466 opBuilder.setL3vpnInstances(l3vpnList);
1467 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1471 String name = inputVpnId.getValue();
1472 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1473 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1474 // read VpnInstance Info
1475 Optional<VpnInstance> optionalVpn =
1476 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1478 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1480 if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
1481 vpns.add(optionalVpn.get());
1484 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1485 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1489 for (VpnInstance vpnInstance : vpns) {
1490 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1491 // create VpnMaps id
1492 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1493 List<String> rd = Collections.EMPTY_LIST;
1494 if (vpnInstance.getRouteDistinguisher() != null) {
1495 rd = vpnInstance.getRouteDistinguisher();
1497 List<String> ertList = new ArrayList<>();
1498 List<String> irtList = new ArrayList<>();
1500 if (vpnInstance.getVpnTargets() != null) {
1501 Map<VpnTargetKey, VpnTarget> keyVpnTargetMap = Collections.EMPTY_MAP;
1502 if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
1503 keyVpnTargetMap = vpnInstance.getVpnTargets().getVpnTarget();
1505 if (!keyVpnTargetMap.isEmpty()) {
1506 for (VpnTarget vpnTarget : keyVpnTargetMap.values()) {
1507 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1508 ertList.add(vpnTarget.getVrfRTValue());
1510 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1511 irtList.add(vpnTarget.getVrfRTValue());
1513 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1514 ertList.add(vpnTarget.getVrfRTValue());
1515 irtList.add(vpnTarget.getVrfRTValue());
1521 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1523 if (vpnInstance.getL3vni() != null) {
1524 l3vpn.setL3vni(vpnInstance.getL3vni());
1526 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1527 .class, new VpnMapKey(vpnId)).build();
1528 Optional<VpnMap> optionalVpnMap =
1529 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1531 if (optionalVpnMap.isPresent()) {
1532 VpnMap vpnMap = optionalVpnMap.get();
1533 List<Uuid> rtrIds = new ArrayList<>();
1534 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1535 for (RouterIds rtrId : vpnMap.getRouterIds().values()) {
1536 rtrIds.add(rtrId.getRouterId());
1539 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1540 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1541 .setName(vpnMap.getName());
1544 l3vpnList.add(l3vpn.build());
1547 opBuilder.setL3vpnInstances(l3vpnList);
1548 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1550 } catch (ExecutionException | InterruptedException ex) {
1551 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1552 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1558 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1561 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1563 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1564 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1565 List<RpcError> errorList = new ArrayList<>();
1567 int failurecount = 0;
1568 int warningcount = 0;
1569 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1570 for (Uuid vpn : vpns) {
1572 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1573 InstanceIdentifier<VpnInstance> vpnIdentifier =
1574 InstanceIdentifier.builder(VpnInstances.class)
1575 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1576 Optional<VpnInstance> optionalVpn =
1577 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1579 if (optionalVpn.isPresent()) {
1582 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1583 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1586 } catch (ExecutionException | InterruptedException ex) {
1587 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1588 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1593 // if at least one succeeds; result is success
1594 // if none succeeds; result is failure
1595 if (failurecount + warningcount == vpns.size()) {
1596 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1598 List<String> errorResponseList = new ArrayList<>();
1599 if (!errorList.isEmpty()) {
1600 for (RpcError rpcError : errorList) {
1601 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1602 + ", ErrorMessage: " + rpcError.getMessage());
1605 errorResponseList.add("Operation successful with no errors");
1607 opBuilder.setResponse(errorResponseList);
1608 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1613 public void createVpnInstanceForSubnet(Uuid subnetId) {
1614 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1615 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1618 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1619 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1620 removeVpn(subnetId);
1623 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1624 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1625 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1626 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1628 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1629 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1632 if (vpnId != null) {
1633 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1634 if (vpnMap == null) {
1635 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1636 + " cannot add subnet {} to VPN", vpnId.getValue(),
1640 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1641 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1642 if (isVpnOfTypeL2(vpnInstance)) {
1643 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1644 NeutronEvpnUtils.Operation.ADD);
1647 if (internetVpnId != null) {
1648 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1649 if (vpnMap == null) {
1650 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1651 + "subnet {} to VPN", internetVpnId.getValue(),
1656 final Uuid internetId = internetVpnId;
1657 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1658 List<Uuid> portList = sn.getPortList();
1659 if (portList != null) {
1660 for (final Uuid portId : portList) {
1661 String vpnInfName = portId.getValue();
1662 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1663 Port port = neutronvpnUtils.getNeutronPort(portId);
1665 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1666 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1669 final Boolean isRouterInterface = port.getDeviceOwner()
1670 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1671 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1672 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1674 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1676 if (vpnIface == null) {
1677 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1678 Set<Uuid> listVpn = new HashSet<>();
1679 if (vpnId != null) {
1682 if (internetId != null) {
1683 listVpn.add(internetId);
1685 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1686 isRouterInterface, wrtConfigTxn);
1687 if (sn.getRouterId() != null) {
1688 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1691 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1692 if (vpnId != null) {
1693 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1695 if (internetId != null) {
1696 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1700 LoggingFutures.addErrorLogging(future, LOG,
1701 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1702 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1703 return Collections.singletonList(future);
1709 protected void removeSubnetFromVpn(final Uuid vpnId, Subnetmap subnetmap, @Nullable Uuid internetVpnId) {
1710 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1711 "removeSubnetFromVpn: at least one VPN must be not null");
1712 Uuid subnetId = subnetmap.getId();
1713 LOG.debug("Removing subnet {} from vpn {}/{}", subnetId.getValue(),
1714 vpnId, internetVpnId);
1715 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnetId.getValue());
1716 VpnMap vpnMap = null;
1717 VpnInstance vpnInstance = null;
1718 if (vpnId != null) {
1719 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1720 if (vpnMap == null) {
1721 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1722 vpnId.getValue(), subnetId.getValue());
1725 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1727 if (internetVpnId == null) {
1728 internetVpnId = subnetmap.getInternetVpnId();
1730 if (internetVpnId != null) {
1731 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1732 if (vpnMap == null) {
1733 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1734 + " from Internet VPN",
1735 internetVpnId.getValue(), subnetId.getValue());
1739 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1740 neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(),
1741 NeutronEvpnUtils.Operation.DELETE);
1743 boolean subnetVpnAssociation = false;
1744 if (vpnId != null && subnetmap.getVpnId() != null
1745 && subnetmap.getVpnId().getValue().equals(vpnId.getValue())) {
1746 subnetVpnAssociation = true;
1747 } else if (internetVpnId != null && subnetmap.getInternetVpnId() != null
1748 && subnetmap.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1749 subnetVpnAssociation = true;
1751 if (subnetVpnAssociation == false) {
1752 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1753 vpnId, internetVpnId, subnetmap.getVpnId(), subnetmap.getInternetVpnId());
1756 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1757 List<Uuid> portList = subnetmap.getPortList();
1758 final Uuid internetId = internetVpnId;
1759 if (portList != null) {
1760 for (final Uuid portId : portList) {
1761 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", subnetmap.getSubnetIp(), portId.getValue());
1762 final Port port = neutronvpnUtils.getNeutronPort(portId);
1763 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1764 List<ListenableFuture<Void>> futures = new ArrayList<>();
1765 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1766 CONFIGURATION, tx -> {
1768 withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx);
1770 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1771 + " port is absent in Neutron config DS", portId.getValue(),
1772 subnetId.getValue());
1775 LoggingFutures.addErrorLogging(future, LOG,
1776 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1777 + " belonging to subnet {} and vpnId {}",
1778 portId.getValue(), subnetId.getValue(), vpnId.getValue());
1779 futures.add(future);
1784 //update subnet-vpn association
1785 removeFromSubnetNode(subnetId, null, null, vpnId, null);
1788 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1789 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1790 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1792 Uuid internalVpnId = sm.getVpnId();
1793 if (internalVpnId == null) {
1794 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1795 sm.getId().getValue());
1798 if (isBeingAssociated) {
1799 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1801 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1804 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1805 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1806 if (isBeingAssociated) {
1807 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1808 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1810 removeInternetVpnFromVpnInterface(vpn,
1811 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1816 // Check for ports on this subnet and update association of
1817 // corresponding vpn-interfaces to internet vpn
1818 List<Uuid> portList = sm.getPortList();
1819 if (portList != null) {
1820 for (Uuid port : portList) {
1821 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1822 port.getValue(), isBeingAssociated);
1823 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1824 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1826 if (isBeingAssociated) {
1827 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1828 true, false, tx, true);
1830 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1838 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1839 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1840 oldVpnId.getValue(), newVpnId.getValue());
1841 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1842 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1843 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1844 Uuid vpnExtUuid = netIsExternal ? null
1845 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1846 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1848 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1851 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1852 * associated with internet BGP-VPN.
1854 if (vpnExtUuid != null) {
1855 /* Update V6 Internet default route match with new VPN metadata.
1856 * isBeingAssociated = true means oldVpnId is same as routerId
1857 * isBeingAssociated = false means newVpnId is same as routerId
1859 if (isBeingAssociated) {
1860 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1862 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1865 //Update Router Interface first synchronously.
1866 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1867 ListenableFuture<Void> future =
1868 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1869 tx -> updateVpnInterface(newVpnId, oldVpnId,
1870 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1871 isBeingAssociated, true, tx, false));
1872 Futures.addCallback(future, new FutureCallback<Void>() {
1874 public void onSuccess(Void result) {
1875 // Check for ports on this subnet and update association of
1876 // corresponding vpn-interfaces to external vpn
1877 List<Uuid> portList = sn.getPortList();
1878 if (portList != null) {
1879 for (Uuid port : portList) {
1880 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1881 port.getValue(), isBeingAssociated);
1882 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1883 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1884 tx -> updateVpnInterface(newVpnId, oldVpnId,
1885 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1892 public void onFailure(Throwable throwable) {
1894 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1896 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1898 }, MoreExecutors.directExecutor());
1903 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1904 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1905 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1908 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1909 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1910 final ReentrantLock lock = lockForUuid(routerId);
1913 Optional<RouterInterfaces> optRouterInterfaces =
1914 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1915 routerInterfacesId);
1916 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1917 .setInterfaceId(interfaceName).build();
1918 if (optRouterInterfaces.isPresent()) {
1919 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1920 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1922 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1923 List<Interfaces> interfaces = new ArrayList<>();
1924 interfaces.add(routerInterface);
1925 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1926 routerInterfacesId, builder.setInterfaces(interfaces).build());
1928 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1929 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1935 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1936 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1937 final ReentrantLock lock = lockForUuid(routerId);
1940 Optional<RouterInterfaces> optRouterInterfaces =
1941 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1942 routerInterfacesId);
1943 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1944 .setInterfaceId(interfaceName).build();
1945 if (optRouterInterfaces.isPresent()) {
1946 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1947 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces().values());
1948 if (interfaces != null && interfaces.remove(routerInterface)) {
1949 if (interfaces.isEmpty()) {
1950 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1951 routerInterfacesId);
1953 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1954 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1958 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1959 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1966 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1967 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1968 * route will be ignored.
1970 * @param vpnName the VPN identifier
1971 * @param interVpnLinkRoutes The list of static routes
1972 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1974 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1975 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1976 for (Routes route : interVpnLinkRoutes) {
1977 String nexthop = route.getNexthop().stringValue();
1978 String destination = route.getDestination().stringValue();
1979 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1980 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1981 AddStaticRouteInput rpcInput =
1982 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1983 .setVpnInstanceName(vpnName.getValue())
1985 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1986 RpcResult<AddStaticRouteOutput> rpcResult;
1988 rpcResult = labelOuputFtr.get();
1989 if (rpcResult.isSuccessful()) {
1990 LOG.debug("Label generated for destination {} is: {}",
1991 destination, rpcResult.getResult().getLabel());
1993 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1994 destination, nexthop, rpcResult.getErrors());
1996 } catch (InterruptedException | ExecutionException e) {
1997 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1998 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
2001 // Any other case is a fault.
2002 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2003 route.getDestination().stringValue(), nexthop);
2010 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2011 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2013 * @param vpnName the VPN identifier
2014 * @param interVpnLinkRoutes The list of static routes
2015 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2017 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2018 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2019 for (Routes route : interVpnLinkRoutes) {
2020 String nexthop = route.getNexthop().stringValue();
2021 String destination = route.getDestination().stringValue();
2022 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2023 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2024 RemoveStaticRouteInput rpcInput =
2025 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2026 .setVpnInstanceName(vpnName.getValue())
2029 LoggingFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2030 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2032 // Any other case is a fault.
2033 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2034 route.getDestination().stringValue(), nexthop);
2041 * Returns true if the specified nexthop is the other endpoint in an
2042 * InterVpnLink, regarding one of the VPN's point of view.
2044 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2045 InterVpnLink interVpnLink) {
2047 interVpnLink != null
2048 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2049 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2050 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2051 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2055 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2056 List<Adjacency> adjList = new ArrayList<>();
2057 Map<String, List<String>> adjMap = new HashMap<>();
2058 for (Routes route : routeList) {
2059 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2060 LOG.error("Incorrect input received for extra route. {}", route);
2062 String nextHop = route.getNexthop().stringValue();
2063 String destination = route.getDestination().stringValue();
2064 if (!nextHop.equals(fixedIp)) {
2065 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2068 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2070 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2071 if (!hops.contains(nextHop)) {
2077 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2078 final String destination = entry.getKey();
2079 final List<String> ipList = entry.getValue();
2080 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2081 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2082 .withKey(new AdjacencyKey(destination)).build();
2088 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2089 checkAlarmExtraRoutes(vpnId, routeList);
2091 for (Routes route : routeList) {
2092 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2093 LOG.error("Incorrect input received for extra route. {}", route);
2095 String nextHop = route.getNexthop().stringValue();
2096 String destination = route.getDestination().stringValue();
2097 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2099 if (infName != null) {
2100 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2101 destination, vpnId.getValue(), nextHop, infName);
2102 boolean isLockAcquired = false;
2104 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2105 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2106 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2107 .child(Adjacency.class, new AdjacencyKey(destination));
2108 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2109 LogicalDatastoreType.CONFIGURATION, path);
2110 if (existingAdjacency.isPresent()
2111 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2112 LOG.error("The route with destination {} nextHop {} is already present as"
2113 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2114 destination, nextHop, infName);
2117 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2118 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2119 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2121 try (AcquireResult lock = tryInterfaceLock(infName)) {
2122 if (!lock.wasAcquired()) {
2123 // FIXME: why do we even bother with locking if we do not honor it?!
2124 logTryLockFailure(infName);
2127 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2130 } catch (TransactionCommitFailedException e) {
2131 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2132 destination, nextHop, e);
2133 } catch (ExecutionException | InterruptedException e) {
2134 LOG.error("Exception on reading data-store ", e);
2137 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2138 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2145 * This method setup or down an alarm about extra route fault.
2146 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2147 * available RDs, then an alarm and an error is generated.<br>
2148 * <b>Be careful</b> the routeList could be changed.
2150 * @param vpnId the vpnId of vpn to control.
2151 * @param routeList the list of router to check, it could be modified.
2153 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2154 if (!neutronvpnAlarm.isAlarmEnabled()) {
2155 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2158 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2159 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2160 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2164 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2165 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2166 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2170 for (Routes route : routeList) {
2171 // count the number of nexthops for each same route.getDestingation().getValue()
2172 String destination = route.getDestination().stringValue();
2173 String nextHop = route.getNexthop().stringValue();
2174 List<String> nextHopList = new ArrayList<>();
2175 nextHopList.add(nextHop);
2177 for (Routes routeTmp : routeList) {
2178 String routeDest = routeTmp.getDestination().stringValue();
2179 if (!destination.equals(routeDest)) {
2182 String routeNextH = routeTmp.getNexthop().stringValue();
2183 if (nextHop.equals(routeNextH)) {
2187 nextHopList.add(routeTmp.getNexthop().stringValue());
2189 final List<String> rdList = new ArrayList<>();
2190 if (vpnInstance != null
2191 && vpnInstance.getRouteDistinguisher() != null) {
2192 vpnInstance.getRouteDistinguisher().forEach(rd -> {
2198 // 1. VPN Instance Name
2199 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2202 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2203 Uuid routerUuid = routerUuidList.get(0);
2204 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2205 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2207 // 3. List of RDs associated with the VPN
2208 detailsAlarm.append(" List of RDs associated with the VPN: ");
2209 for (String s : rdList) {
2210 detailsAlarm.append(s);
2211 detailsAlarm.append(", ");
2214 // 4. Prefix in question
2215 detailsAlarm.append(" for prefix: ");
2216 detailsAlarm.append(route.getDestination().stringValue());
2218 // 5. List of NHs for the prefix
2219 detailsAlarm.append(" for nextHops: ");
2220 for (String s : nextHopList) {
2221 detailsAlarm.append(s);
2222 detailsAlarm.append(", ");
2225 if (rdList.size() < nbNextHops) {
2226 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2228 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2233 // TODO Clean up the exception handling
2234 @SuppressWarnings("checkstyle:IllegalCatch")
2235 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2236 for (Routes route : routeList) {
2237 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2238 String nextHop = route.getNexthop().stringValue();
2239 String destination = route.getDestination().stringValue();
2240 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2242 if (infName == null) {
2243 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2244 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2245 // Proceed to remove the next extra-route
2248 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2249 destination, vpnId.getValue(), nextHop, infName);
2251 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2252 InstanceIdentifier.builder(VpnInterfaces.class)
2253 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2254 .augmentation(Adjacencies.class)
2255 .child(Adjacency.class, new AdjacencyKey(destination))
2259 // Looking for existing prefix in MDSAL database
2260 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2261 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2262 boolean updateNextHops = false;
2263 List<String> nextHopList = new ArrayList<>();
2264 if (adjacency.isPresent()) {
2265 List<String> nhListRead = adjacency.get().getNextHopIpList();
2266 if (nhListRead.size() > 1) { // ECMP case
2267 for (String nextHopRead : nhListRead) {
2268 if (nextHopRead.equals(nextHop)) {
2269 updateNextHops = true;
2271 nextHopList.add(nextHopRead);
2277 try (AcquireResult lock = tryInterfaceLock(infName)) {
2278 if (!lock.wasAcquired()) {
2279 // FIXME: why do we even bother with locking if we do not honor it?!
2280 logTryLockFailure(infName);
2283 if (updateNextHops) {
2284 // An update must be done, not including the current next hop
2285 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2286 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2287 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2288 .setNextHopIpList(nextHopList)
2289 .withKey(new AdjacencyKey(destination))
2291 List<Adjacency> newAdjList = Collections.singletonList(newAdj);
2292 Adjacencies erAdjs =
2293 new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(newAdjList)).build();
2294 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2295 .addAugmentation(Adjacencies.class, erAdjs).build();
2296 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2297 vpnIfIdentifier, vpnIf);
2299 // Remove the whole route
2300 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2301 adjacencyIdentifier);
2302 LOG.trace("extra route {} deleted successfully", route);
2305 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
2306 LOG.error("exception in deleting extra route with destination {} for interface {}",
2307 destination, infName, e);
2310 LOG.error("Incorrect input received for extra route: {}", route);
2315 public void removeVpn(Uuid vpnId) {
2317 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2318 if (vpnMap != null) {
2319 Map<RouterIdsKey, RouterIds> keyRouterIdsMap = vpnMap.getRouterIds();
2320 List<Uuid> routerUuidList = new ArrayList<>();
2321 // dissociate router
2322 if (keyRouterIdsMap != null && !keyRouterIdsMap.isEmpty()) {
2323 for (RouterIds router : keyRouterIdsMap.values()) {
2324 Uuid routerId = router.getRouterId();
2325 routerUuidList.add(routerId);
2326 dissociateRouterFromVpn(vpnId, routerId);
2329 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2330 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2333 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2335 // remove entire vpnMaps node
2336 deleteVpnMapsNode(vpnId);
2338 // remove vpn-instance
2339 deleteVpnInstance(vpnId);
2340 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2343 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2344 return vpnInstance != null && vpnInstance.isL2vpn();
2347 // TODO Clean up the exception handling
2348 @SuppressWarnings("checkstyle:IllegalCatch")
2349 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2350 updateVpnMaps(vpnId, null, routerId, null, null);
2351 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2352 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2353 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2354 for (Subnetmap sn : subMapList) {
2355 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2356 if (!ipVersion.isIpVersionChosen(ipVers)) {
2357 ipVersion = ipVersion.addVersion(ipVers);
2360 if (ipVersion != IpVersionChoice.UNDEFINED) {
2361 LOG.debug("associateRouterToVpn: Updating vpnInstance ip address family {} for VPN {} ",
2363 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2365 for (Subnetmap sn : subMapList) {
2366 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2370 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2371 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2372 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2373 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2374 for (Uuid subnet : routerSubnets) {
2375 IpVersionChoice version = NeutronvpnUtils
2376 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2377 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2378 addSubnetToVpn(vpnId, subnet, null);
2380 addSubnetToVpn(vpnId, subnet, internetVpnId);
2385 // TODO Clean up the exception handling
2386 @SuppressWarnings("checkstyle:IllegalCatch")
2387 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2389 clearFromVpnMaps(vpnId, routerId, null);
2390 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2391 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2392 for (Subnetmap sn : subMapList) {
2393 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2394 if (ipVersion.isIpVersionChosen(ipVers)) {
2395 ipVersion = ipVersion.addVersion(ipVers);
2397 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2398 routerId.getValue());
2399 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2401 if (ipVersion != IpVersionChoice.UNDEFINED) {
2402 LOG.debug("dissociateRouterFromVpn; Updating vpnInstance with ip address family {} for VPN {} ",
2404 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2410 * Parses and associates networks list with given VPN.
2412 * @param vpnId Uuid of given VPN.
2413 * @param networkList List list of network Ids (Uuid), which will be associated.
2414 * @return list of formatted strings with detailed error messages.
2417 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2418 List<String> failedNwList = new ArrayList<>();
2419 HashSet<Uuid> passedNwList = new HashSet<>();
2420 ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
2421 boolean isExternalNetwork = false;
2422 if (networkList.isEmpty()) {
2423 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2424 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2426 return failedNwList;
2428 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2429 if (vpnInstance == null) {
2430 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2431 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2432 + "in ConfigDS", vpnId.getValue()));
2433 return failedNwList;
2436 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2437 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2439 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2440 + "associated with", vpnId.getValue()));
2441 return failedNwList;
2443 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2444 boolean isIpFamilyUpdated = false;
2445 for (Uuid nw : networkList) {
2446 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2447 if (network == null) {
2448 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2449 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2453 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2454 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2455 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2456 nw.getValue(), vpnId.getValue());
2457 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2458 nw.getValue(), vpnId.getValue()));
2461 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2462 if (networkVpnId != null) {
2463 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2464 nw.getValue(), networkVpnId.getValue());
2465 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2466 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2469 /* Handle association of external network(s) to Internet BGP-VPN use case outside of the
2470 * networkList iteration
2472 if (neutronvpnUtils.getIsExternal(network)) {
2473 extNwMap.put(nw, network);
2475 if (NeutronvpnUtils.getIsExternal(network)) {
2476 isExternalNetwork = true;
2478 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2479 if (subnetmapList == null || subnetmapList.isEmpty()) {
2480 passedNwList.add(nw);
2483 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2486 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2487 for (Subnetmap subnetmap : subnetmapList) {
2488 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2489 if (!ipVersion.isIpVersionChosen(ipVers)) {
2490 ipVersion = ipVersion.addVersion(ipVers);
2493 //Update vpnInstance for IP address family
2494 if (ipVersion != IpVersionChoice.UNDEFINED && !isIpFamilyUpdated) {
2495 LOG.debug("associateNetworksToVpn: Updating vpnInstance with ip address family {}"
2496 + " for VPN {} ", ipVersion, vpnId);
2497 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2498 isIpFamilyUpdated = true;
2500 for (Subnetmap subnetmap : subnetmapList) {
2501 Uuid subnetId = subnetmap.getId();
2502 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2503 if (subnetVpnId != null) {
2504 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2505 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2506 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2507 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2510 if (!NeutronvpnUtils.getIsExternal(network)) {
2511 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2513 addSubnetToVpn(vpnId, subnetId, null);
2514 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2516 passedNwList.add(nw);
2519 passedNwList.add(nw);
2520 //Handle association of external network(s) to Internet BGP-VPN Instance use case
2521 if (!extNwMap.isEmpty() || extNwMap != null) {
2522 for (Network extNw : extNwMap.values()) {
2523 if (!associateExtNetworkToVpn(vpnId, extNw, vpnInstance.getBgpvpnType())) {
2524 LOG.error("associateNetworksToVpn: Failed to associate Provider External Network {} with "
2525 + "VPN {}", extNw, vpnId.getValue());
2526 failedNwList.add(String.format("Failed to associate Provider External Network %s with "
2527 + "VPN %s", extNw, vpnId.getValue()));
2533 } catch (ExecutionException | InterruptedException e) {
2534 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2536 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2539 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2540 if (!isExternalNetwork) {
2541 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2543 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2544 return failedNwList;
2547 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet,
2548 VpnInstance.BgpvpnType bgpVpnType) {
2549 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2552 if (!bgpVpnType.equals(VpnInstance.BgpvpnType.InternetBGPVPN)) {
2553 LOG.info("associateExtNetworkToVpn: External network {} is associated to VPN {}."
2554 + "Hence set vpnInstance type to {} from {} ", extNet.key().getUuid().getValue(),
2555 vpnId.getValue(), VpnInstance.BgpvpnType.InternetBGPVPN.getName(),
2556 VpnInstance.BgpvpnType.BGPVPN.getName());
2557 neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.InternetBGPVPN, vpnId);
2559 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2560 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2561 updateVpnMaps(vpnId, null, null, null, extNwList);
2562 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2563 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2564 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2566 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2569 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2570 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2573 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2574 updateVpnInternetForSubnet(sm, vpnId, true);
2576 if (!ipVersion.isIpVersionChosen(ipVers)) {
2577 ipVersion = ipVersion.addVersion(ipVers);
2580 if (ipVersion != IpVersionChoice.UNDEFINED) {
2581 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2582 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2583 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2589 * Parses and disassociates networks list from given VPN.
2591 * @param vpnId Uuid of given VPN.
2592 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2593 * @return list of formatted strings with detailed error messages.
2596 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2597 List<String> failedNwList = new ArrayList<>();
2598 HashSet<Uuid> passedNwList = new HashSet<>();
2599 ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
2600 if (networkList.isEmpty()) {
2601 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2602 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2604 return failedNwList;
2606 for (Uuid nw : networkList) {
2607 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2608 if (networkSubnets == null) {
2609 passedNwList.add(nw);
2612 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2613 if (network == null) {
2614 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2615 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2619 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2620 if (networkVpnId == null) {
2621 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2622 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2626 if (!vpnId.equals(networkVpnId)) {
2627 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2628 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2629 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2630 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2634 /* Handle disassociation of external network(s) from Internet BGP-VPN use case outside of the
2635 * networkList iteration
2637 if (neutronvpnUtils.getIsExternal(network)) {
2638 extNwMap.put(nw, network);
2640 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2641 for (Uuid subnet : networkSubnets) {
2642 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2643 if (subnetmap == null) {
2644 failedNwList.add(String.format("subnetmap %s not found for network %s",
2645 subnet.getValue(), nw.getValue()));
2646 LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when "
2647 + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(),
2651 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2652 if (!ipVersion.isIpVersionChosen(ipVers)) {
2653 ipVersion = ipVersion.addVersion(ipVers);
2655 if (!NeutronvpnUtils.getIsExternal(network)) {
2656 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2658 removeSubnetFromVpn(vpnId, subnetmap, null);
2659 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2660 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2662 passedNwList.add(nw);
2665 if (ipVersion != IpVersionChoice.UNDEFINED) {
2666 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstance with ip address family {}"
2667 + " for VPN {}", ipVersion, vpnId);
2668 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2671 //Handle disassociation of external network(s) from Internet BGP-VPN Instance use case
2672 if (!extNwMap.isEmpty() || extNwMap != null) {
2673 for (Network extNw : extNwMap.values()) {
2674 if (disassociateExtNetworkFromVpn(vpnId, extNw)) {
2675 passedNwList.add(extNw.getUuid());
2677 LOG.error("dissociateNetworksFromVpn: Failed to withdraw External Provider Network {} from VPN {}",
2678 extNw, vpnId.getValue());
2679 failedNwList.add(String.format("Failed to withdraw External Provider Network %s from VPN %s",
2680 extNw, vpnId.getValue()));
2685 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2686 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2687 passedNwList, vpnId.getValue());
2688 return failedNwList;
2691 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2692 if (!removeExternalNetworkFromVpn(extNet)) {
2695 // check, if there is another Provider Networks associated with given VPN
2696 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2697 if (vpnNets != null) {
2698 //Remove currently disassociated network from the list
2699 vpnNets.remove(extNet.getUuid());
2700 for (Uuid netId : vpnNets) {
2701 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2702 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2703 + "{}", vpnId.getValue(), netId.getValue());
2708 ///Set VPN Type is BGPVPN from InternetBGPVPN
2709 LOG.info("disassociateExtNetworkFromVpn: Set BGP-VPN type with {} for VPN {} and update IPv6 address family. "
2710 + "Since external network is disassociated from VPN {}",
2711 VpnInstance.BgpvpnType.BGPVPN, extNet, vpnId.getValue());
2712 neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.BGPVPN, vpnId);
2713 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2714 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2715 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2717 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2720 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2721 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2724 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2725 updateVpnInternetForSubnet(sm, vpnId, false);
2727 if (!ipVersion.isIpVersionChosen(ipVers)) {
2728 ipVersion = ipVersion.addVersion(ipVers);
2731 if (ipVersion != IpVersionChoice.UNDEFINED) {
2732 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2733 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2735 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2741 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2744 // TODO Clean up the exception handling
2745 @SuppressWarnings("checkstyle:IllegalCatch")
2746 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2748 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2749 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2750 StringBuilder returnMsg = new StringBuilder();
2751 Uuid vpnId = input.getVpnId();
2754 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2755 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2756 input.getNetworkId());
2757 List<Uuid> netIds = input.getNetworkId();
2758 if (netIds != null && !netIds.isEmpty()) {
2759 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2760 if (!failed.isEmpty()) {
2761 returnMsg.append(failed);
2765 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2767 if (returnMsg.length() != 0) {
2768 opBuilder.setResponse(
2769 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2770 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2771 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2773 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2775 } catch (Exception ex) {
2776 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2777 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2778 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2779 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2781 LOG.debug("associateNetworks returns..");
2786 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2789 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2791 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2792 LOG.debug("associateRouter {}", input);
2793 StringBuilder returnMsg = new StringBuilder();
2794 Uuid vpnId = input.getVpnId();
2795 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter
2796 .input.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2797 .associaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2798 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "associateRouter: RouterIds list is empty!");
2799 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2800 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2801 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2802 .RouterIds routerId : keyRouterIdsMap.values()) {
2803 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2804 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2805 if (vpnMap != null) {
2807 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2808 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2809 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2810 .append(routerId.getRouterId());
2811 } else if (extVpnId != null) {
2812 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2813 + "another VPN ").append(extVpnId.getValue());
2815 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2816 routerId.getRouterId());
2817 associateRouterToVpn(vpnId, routerId.getRouterId());
2820 returnMsg.append("router not found : ").append(routerId.getRouterId());
2823 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2825 if (returnMsg.length() != 0) {
2826 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2827 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2828 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2830 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2833 LOG.debug("associateRouter returns..");
2838 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2841 // TODO Clean up the exception handling
2842 @SuppressWarnings("checkstyle:IllegalCatch")
2843 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2844 GetFixedIPsForNeutronPortInput input) {
2845 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2846 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2847 Uuid portId = input.getPortId();
2848 StringBuilder returnMsg = new StringBuilder();
2850 List<String> fixedIPList = new ArrayList<>();
2851 Port port = neutronvpnUtils.getNeutronPort(portId);
2853 for (FixedIps ip : port.nonnullFixedIps().values()) {
2854 fixedIPList.add(ip.getIpAddress().stringValue());
2857 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2859 if (returnMsg.length() != 0) {
2860 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2862 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2863 returnMsg)).build());
2865 opBuilder.setFixedIPs(fixedIPList);
2866 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2868 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2870 } catch (Exception ex) {
2871 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2872 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2873 portId.getValue(), ex.getMessage(), ex)).build());
2879 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2882 // TODO Clean up the exception handling
2883 @SuppressWarnings("checkstyle:IllegalCatch")
2884 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2886 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2887 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2889 LOG.debug("dissociateNetworks {}", input);
2890 StringBuilder returnMsg = new StringBuilder();
2891 Uuid vpnId = input.getVpnId();
2894 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2895 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2896 input.getNetworkId());
2897 List<Uuid> netIds = input.getNetworkId();
2898 if (netIds != null && !netIds.isEmpty()) {
2899 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2900 if (!failed.isEmpty()) {
2901 returnMsg.append(failed);
2905 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2907 if (returnMsg.length() != 0) {
2908 opBuilder.setResponse(
2909 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2910 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2912 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2914 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2916 } catch (Exception ex) {
2917 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2918 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2919 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2921 LOG.debug("dissociateNetworks returns..");
2926 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2929 // TODO Clean up the exception handling
2930 @SuppressWarnings("checkstyle:IllegalCatch")
2931 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2933 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2935 LOG.debug("dissociateRouter {}", input);
2936 StringBuilder returnMsg = new StringBuilder();
2937 Uuid vpnId = input.getVpnId();
2938 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2939 .RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2940 .dissociaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2941 String routerIdsString = "";
2942 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2943 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2944 Preconditions.checkNotNull(keyRouterIdsMap, "dissociateRouter: keyRouterIdsMap not found!");
2945 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2946 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2947 .RouterIds routerId : keyRouterIdsMap.values()) {
2949 if (routerId != null) {
2950 routerIdsString += routerId.getRouterId() + ", ";
2951 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2953 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2954 if (routerVpnId == null) {
2955 returnMsg.append("input router ").append(routerId.getRouterId())
2956 .append(" not associated to any vpn yet");
2957 } else if (vpnId.equals(routerVpnId)) {
2958 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2960 returnMsg.append("input router ").append(routerId.getRouterId())
2961 .append(" associated to vpn ")
2962 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2965 returnMsg.append("router not found : ").append(routerId.getRouterId());
2968 if (returnMsg.length() != 0) {
2969 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2970 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2971 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2972 returnMsg)).build());
2974 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2976 } catch (Exception ex) {
2977 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2978 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2979 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2983 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2986 LOG.debug("dissociateRouter returns..");
2990 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2991 // check if the router is associated to some VPN
2992 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2993 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2994 if (vpnId != null) {
2995 // remove existing external vpn interfaces
2996 for (Uuid subnetId : routerSubnetIds) {
2997 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
2998 if (subnetmap != null) {
2999 removeSubnetFromVpn(vpnId, subnetmap, internetVpnId);
3001 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
3002 subnetId, routerId.getValue());
3005 clearFromVpnMaps(vpnId, routerId, null);
3007 // remove existing internal vpn interfaces
3008 for (Uuid subnetId : routerSubnetIds) {
3009 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
3010 if (subnetmap != null) {
3011 removeSubnetFromVpn(routerId, subnetmap, internetVpnId);
3013 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
3014 subnetId, routerId.getValue());
3018 // delete entire vpnMaps node for internal VPN
3019 deleteVpnMapsNode(routerId);
3021 // delete vpn-instance for internal VPN
3022 deleteVpnInstance(routerId);
3025 protected Subnet getNeutronSubnet(Uuid subnetId) {
3026 return neutronvpnUtils.getNeutronSubnet(subnetId);
3030 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
3031 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
3033 return sn.getGatewayIp();
3039 protected Network getNeutronNetwork(Uuid networkId) {
3040 return neutronvpnUtils.getNeutronNetwork(networkId);
3043 protected Port getNeutronPort(String name) {
3044 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3047 protected Port getNeutronPort(Uuid portId) {
3048 return neutronvpnUtils.getNeutronPort(portId);
3051 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3052 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3055 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3056 return neutronvpnUtils.getNetworksForVpn(vpnId);
3060 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3062 * @return a List of String to be printed on screen
3063 * @throws ExecutionException or InterruptedException if there was a problem reading from the data store
3065 public List<String> showNeutronPortsCLI() throws ExecutionException, InterruptedException {
3066 List<String> result = new ArrayList<>();
3067 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3069 result.add("-------------------------------------------------------------------------------------------");
3070 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3072 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3073 if (ports.isPresent() && ports.get().getPort() != null) {
3074 for (Port port : ports.get().nonnullPort().values()) {
3075 Map<FixedIpsKey, FixedIps> keyFixedIpsMap = port.getFixedIps();
3076 if (keyFixedIpsMap != null && !keyFixedIpsMap.isEmpty()) {
3077 List<String> ipList = new ArrayList<>();
3078 for (FixedIps fixedIp : keyFixedIpsMap.values()) {
3079 IpAddress ipAddress = fixedIp.getIpAddress();
3080 if (ipAddress.getIpv4Address() != null) {
3081 ipList.add(ipAddress.getIpv4Address().getValue());
3083 ipList.add(ipAddress.getIpv6Address().getValue());
3086 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3087 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3088 ipList.toString()));
3090 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3091 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3100 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3102 * @param vpnuuid Uuid of the VPN whose config must be shown
3103 * @return formatted output list
3104 * @throws InterruptedException if there was a thread related problem getting the data to display
3105 * @throws ExecutionException if there was any other problem getting the data to display
3107 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3108 List<String> result = new ArrayList<>();
3109 if (vpnuuid == null) {
3111 result.add("Displaying VPN config for all VPNs");
3112 result.add("To display VPN config for a particular VPN, use the following syntax");
3113 result.add(getshowVpnConfigCLIHelp());
3115 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3116 if (rpcResult.isSuccessful()) {
3118 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3120 result.add(String.format(" %-80s ", "Import-RTs"));
3122 result.add(String.format(" %-80s ", "Export-RTs"));
3124 result.add(String.format(" %-76s ", "Subnet IDs"));
3126 result.add("------------------------------------------------------------------------------------");
3128 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3129 rpcResult.getResult().nonnullL3vpnInstances()) {
3130 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3132 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3133 vpn.getRouteDistinguisher()));
3135 result.add(String.format(" %-80s ", vpn.getImportRT()));
3137 result.add(String.format(" %-80s ", vpn.getExportRT()));
3140 Uuid vpnid = vpn.getId();
3141 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3142 if (!subnetList.isEmpty()) {
3143 for (Uuid subnetuuid : subnetList) {
3144 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3147 result.add(String.format(" %-76s ", "\" \""));
3150 result.add("----------------------------------------");
3154 String errortag = rpcResult.getErrors().iterator().next().getTag();
3155 if (Objects.equals(errortag, "")) {
3157 result.add("No VPN has been configured yet");
3158 } else if (Objects.equals(errortag, "invalid-value")) {
3160 result.add("VPN " + vpnuuid.getValue() + " is not present");
3162 result.add("error getting VPN info : " + rpcResult.getErrors());
3163 result.add(getshowVpnConfigCLIHelp());
3169 protected void createExternalVpnInterfaces(Uuid extNetId) {
3170 if (extNetId == null) {
3171 LOG.error("createExternalVpnInterfaces: external network is null");
3175 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3176 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3177 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3181 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3182 for (String elanInterface : extElanInterfaces) {
3183 createExternalVpnInterface(extNetId, elanInterface, tx);
3185 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3188 // TODO Clean up the exception handling
3189 @SuppressWarnings("checkstyle:IllegalCatch")
3190 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3191 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3192 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3193 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3196 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3197 for (String elanInterface : extElanInterfaces) {
3198 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3199 .buildVpnInterfaceIdentifier(elanInterface);
3200 LOG.info("Removing vpn interface {}", elanInterface);
3201 tx.delete(vpnIfIdentifier);
3203 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3206 private void createExternalVpnInterface(Uuid vpnId, String infName,
3207 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3208 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3209 false /* not a router iface */, wrtConfigTxn);
3212 // TODO Clean up the exception handling
3213 @SuppressWarnings("checkstyle:IllegalCatch")
3214 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3215 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3216 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3217 if (vpnIdList.isEmpty() || infName == null) {
3218 LOG.error("vpnid is empty or interface({}) is null", infName);
3221 if (wrtConfigTxn == null) {
3222 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3223 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3224 "Error writing VPN interface");
3227 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3228 for (Uuid vpnId: vpnIdList) {
3229 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3230 AssociatedSubnetType.V4AndV6Subnets);
3231 vpnIdListStruct.add(vpnInstance);
3234 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3235 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3237 .setVpnInstanceNames(vpnIdListStruct)
3238 .setRouterInterface(isRouterInterface);
3239 LOG.info("Network Id is {}", networkUuid);
3240 if (networkUuid != null) {
3241 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3242 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3243 NetworkAttributes.NetworkType networkType = providerType != null
3244 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3245 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3246 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3247 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3250 if (adjacencies != null) {
3251 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3253 VpnInterface vpnIf = vpnb.build();
3255 LOG.info("Creating vpn interface {}", vpnIf);
3256 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3257 } catch (Exception ex) {
3258 LOG.error("Creation of vpninterface {} failed", infName, ex);
3262 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3263 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3264 if (vpnId == null || infName == null) {
3265 LOG.error("vpn id or interface is null");
3268 if (wrtConfigTxn == null) {
3269 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3270 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3271 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3272 }), LOG, "Error updating VPN interface with adjacencies");
3276 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3278 try (AcquireResult lock = tryInterfaceLock(infName)) {
3279 if (!lock.wasAcquired()) {
3280 // FIXME: why do we even bother with locking if we do not honor it?!
3281 logTryLockFailure(infName);
3285 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3286 .syncReadOptional(dataBroker, LogicalDatastoreType
3287 .CONFIGURATION, vpnIfIdentifier);
3288 if (optionalVpnInterface.isPresent()) {
3289 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3290 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3292 if (adjacencies == null) {
3295 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3296 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3297 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3298 optionalVpnInterface.get().getVpnInstanceNames().values());
3299 if (listVpnInstances.isEmpty()
3300 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3301 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3302 AssociatedSubnetType.V4AndV6Subnets);
3303 listVpnInstances.add(vpnInstance);
3304 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3307 VpnInstanceNames vpnInstance = VpnHelper
3308 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3309 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3310 listVpnInstances.add(vpnInstance);
3311 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3313 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3314 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3316 } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
3317 // FIXME: why are we catching IllegalStateException here?
3318 LOG.error("Update of vpninterface {} failed", infName, ex);
3323 private String getshowVpnConfigCLIHelp() {
3324 StringBuilder help = new StringBuilder("Usage:");
3325 help.append("display vpn-config [-vid/--vpnid <id>]");
3326 return help.toString();
3329 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3330 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3334 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3335 return neutronEvpnManager.createEVPN(input);
3339 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3340 return neutronEvpnManager.getEVPN(input);
3344 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3345 return neutronEvpnManager.deleteEVPN(input);
3348 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3349 Uuid extNetId = extNet.getUuid();
3350 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3351 .child(Networks.class, new NetworksKey(extNetId)).build();
3354 Optional<Networks> optionalExtNets =
3355 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3357 if (!optionalExtNets.isPresent()) {
3358 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3359 extNetId.getValue());
3362 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3363 builder.setVpnid(vpnId);
3364 Networks networks = builder.build();
3365 // Add Networks object to the ExternalNetworks list
3366 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3367 extNetId.getValue());
3368 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3371 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3372 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3373 extNetId.getValue(), ex);
3378 private boolean removeExternalNetworkFromVpn(Network extNet) {
3379 Uuid extNetId = extNet.getUuid();
3380 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3381 .child(Networks.class, new NetworksKey(extNetId)).build();
3383 Optional<Networks> optionalNets =
3384 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3386 NetworksBuilder builder = null;
3387 if (optionalNets.isPresent()) {
3388 builder = new NetworksBuilder(optionalNets.get());
3390 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3391 extNetId.getValue());
3394 builder.setVpnid(null);
3395 Networks networks = builder.build();
3396 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3397 extNetId.getValue());
3398 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3400 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3401 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3402 extNetId.getValue(), ex);
3407 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3408 Optional<String> existingVpnName = Optional.of(primaryRd);
3409 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3411 vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3412 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3413 } catch (ExecutionException | InterruptedException e) {
3414 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3416 /*Read failed. We don't know if a VPN exists or not.
3417 * Return primaryRd to halt caller execution, to be safe.*/
3418 return existingVpnName;
3420 if (vpnInstanceOpDataOptional.isPresent()) {
3421 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3423 existingVpnName = Optional.empty();
3425 return existingVpnName;
3428 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3429 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3432 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3433 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3436 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3437 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3440 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3441 String message = tuple.getMessage();
3442 logger.accept(message);
3446 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3447 @NonNull Subnetmap subnetMap) {
3448 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3449 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3450 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3451 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3452 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3453 subnetMap.getId().getValue(), internetVpnId.getValue());
3457 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3458 @NonNull Subnetmap subnetMap) {
3459 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3460 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3463 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3464 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3465 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3466 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3467 internetVpnId.getValue(), routerId.getValue());
3468 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3474 private AcquireResult tryInterfaceLock(final String infName) {
3475 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3479 private AcquireResult tryVpnLock(final Uuid vpnId) {
3480 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3483 private static ReentrantLock lockForUuid(Uuid uuid) {
3484 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3485 return JvmGlobalLocks.getLockForString(uuid.getValue());
3488 private static void logTryLockFailure(Object objectId) {
3489 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());