2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
14 import com.google.common.base.Preconditions;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.JdkFutureAdapters;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
33 import java.util.Optional;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.locks.ReentrantLock;
40 import java.util.function.Consumer;
41 import java.util.stream.Collectors;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
45 import org.eclipse.jdt.annotation.NonNull;
46 import org.eclipse.jdt.annotation.Nullable;
47 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
48 import org.opendaylight.genius.infra.Datastore.Configuration;
49 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
50 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
51 import org.opendaylight.genius.infra.TypedWriteTransaction;
52 import org.opendaylight.genius.mdsalutil.NwConstants;
53 import org.opendaylight.genius.utils.JvmGlobalLocks;
54 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
55 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
56 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
57 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
58 import org.opendaylight.mdsal.binding.api.DataBroker;
59 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
60 import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
61 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
62 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
63 import org.opendaylight.netvirt.elanmanager.api.IElanService;
64 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
65 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
66 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
67 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
68 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
69 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
70 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.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);
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);
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 vpnInstanceOpDataEntrywith 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 vpnInstanceOpDataEntry 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 boolean isExternalNetwork = false;
2421 if (networkList.isEmpty()) {
2422 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2423 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2425 return failedNwList;
2427 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2428 if (vpnInstance == null) {
2429 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2430 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2431 + "in ConfigDS", vpnId.getValue()));
2432 return failedNwList;
2435 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2436 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2438 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2439 + "associated with", vpnId.getValue()));
2440 return failedNwList;
2442 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2443 for (Uuid nw : networkList) {
2444 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2445 if (network == null) {
2446 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2447 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2451 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2452 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2453 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2454 nw.getValue(), vpnId.getValue());
2455 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2456 nw.getValue(), vpnId.getValue()));
2459 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2460 if (networkVpnId != null) {
2461 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2462 nw.getValue(), networkVpnId.getValue());
2463 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2464 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2467 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2468 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2469 nw.getValue(), vpnId.getValue());
2470 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2471 nw.getValue(), vpnId.getValue()));
2474 if (NeutronvpnUtils.getIsExternal(network)) {
2475 isExternalNetwork = true;
2477 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2478 if (subnetmapList == null || subnetmapList.isEmpty()) {
2479 passedNwList.add(nw);
2482 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2485 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2486 for (Subnetmap subnetmap : subnetmapList) {
2487 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2488 if (!ipVersion.isIpVersionChosen(ipVers)) {
2489 ipVersion = ipVersion.addVersion(ipVers);
2492 if (ipVersion != IpVersionChoice.UNDEFINED) {
2493 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2494 + " for VPN {} ", ipVersion, vpnId);
2495 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2497 for (Subnetmap subnetmap : subnetmapList) {
2498 Uuid subnetId = subnetmap.getId();
2499 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2500 if (subnetVpnId != null) {
2501 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2502 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2503 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2504 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2507 if (!NeutronvpnUtils.getIsExternal(network)) {
2508 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2510 addSubnetToVpn(vpnId, subnetId, null);
2511 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2513 passedNwList.add(nw);
2516 passedNwList.add(nw);
2518 } catch (ExecutionException | InterruptedException e) {
2519 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2521 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2524 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2525 if (!isExternalNetwork) {
2526 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2528 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2529 return failedNwList;
2532 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2533 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2536 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2537 if (vpnOpDataEntry == null) {
2538 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2541 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2542 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2543 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2545 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2546 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2547 updateVpnMaps(vpnId, null, null, null, extNwList);
2548 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2549 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2550 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2552 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2555 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2556 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2559 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2560 updateVpnInternetForSubnet(sm, vpnId, true);
2562 if (!ipVersion.isIpVersionChosen(ipVers)) {
2563 ipVersion = ipVersion.addVersion(ipVers);
2566 if (ipVersion != IpVersionChoice.UNDEFINED) {
2567 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2568 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2569 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2575 * Parses and disassociates networks list from given VPN.
2577 * @param vpnId Uuid of given VPN.
2578 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2579 * @return list of formatted strings with detailed error messages.
2582 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2583 List<String> failedNwList = new ArrayList<>();
2584 HashSet<Uuid> passedNwList = new HashSet<>();
2585 if (networkList.isEmpty()) {
2586 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2587 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2589 return failedNwList;
2591 for (Uuid nw : networkList) {
2592 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2593 if (networkSubnets == null) {
2594 passedNwList.add(nw);
2597 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2598 if (network == null) {
2599 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2600 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2604 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2605 if (networkVpnId == null) {
2606 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2607 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2611 if (!vpnId.equals(networkVpnId)) {
2612 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2613 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2614 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2615 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2619 if (NeutronvpnUtils.getIsExternal(network)) {
2620 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2621 passedNwList.add(nw);
2623 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2624 nw.getValue(), vpnId.getValue());
2625 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2630 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2631 for (Uuid subnet : networkSubnets) {
2632 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2633 if (subnetmap == null) {
2634 failedNwList.add(String.format("subnetmap %s not found for network %s",
2635 subnet.getValue(), nw.getValue()));
2636 LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when "
2637 + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(),
2641 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2642 if (!ipVersion.isIpVersionChosen(ipVers)) {
2643 ipVersion = ipVersion.addVersion(ipVers);
2645 if (!NeutronvpnUtils.getIsExternal(network)) {
2646 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2648 removeSubnetFromVpn(vpnId, subnetmap, null);
2649 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2650 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2652 passedNwList.add(nw);
2655 if (ipVersion != IpVersionChoice.UNDEFINED) {
2656 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2657 + " for VPN {}", ipVersion, vpnId);
2658 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2661 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2662 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2663 passedNwList, vpnId.getValue());
2664 return failedNwList;
2667 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2668 if (!removeExternalNetworkFromVpn(extNet)) {
2671 // check, if there is another Provider Networks associated with given VPN
2672 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2673 if (vpnNets != null) {
2674 //Remove currently disassociated network from the list
2675 vpnNets.remove(extNet.getUuid());
2676 for (Uuid netId : vpnNets) {
2677 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2678 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2679 + "{}", vpnId.getValue(), netId.getValue());
2684 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2685 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2686 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2687 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2688 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2689 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2690 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2692 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2695 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2696 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2699 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2700 updateVpnInternetForSubnet(sm, vpnId, false);
2702 if (!ipVersion.isIpVersionChosen(ipVers)) {
2703 ipVersion = ipVersion.addVersion(ipVers);
2706 if (ipVersion != IpVersionChoice.UNDEFINED) {
2707 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2708 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2710 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2716 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2719 // TODO Clean up the exception handling
2720 @SuppressWarnings("checkstyle:IllegalCatch")
2721 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2723 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2724 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2725 StringBuilder returnMsg = new StringBuilder();
2726 Uuid vpnId = input.getVpnId();
2729 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2730 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2731 input.getNetworkId());
2732 List<Uuid> netIds = input.getNetworkId();
2733 if (netIds != null && !netIds.isEmpty()) {
2734 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2735 if (!failed.isEmpty()) {
2736 returnMsg.append(failed);
2740 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2742 if (returnMsg.length() != 0) {
2743 opBuilder.setResponse(
2744 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2745 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2746 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2748 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2750 } catch (Exception ex) {
2751 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2752 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2753 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2754 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2756 LOG.debug("associateNetworks returns..");
2761 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2764 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2766 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2767 LOG.debug("associateRouter {}", input);
2768 StringBuilder returnMsg = new StringBuilder();
2769 Uuid vpnId = input.getVpnId();
2770 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter
2771 .input.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2772 .associaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2773 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "associateRouter: RouterIds list is empty!");
2774 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2775 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2776 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2777 .RouterIds routerId : keyRouterIdsMap.values()) {
2778 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2779 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2780 if (vpnMap != null) {
2782 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2783 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2784 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2785 .append(routerId.getRouterId());
2786 } else if (extVpnId != null) {
2787 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2788 + "another VPN ").append(extVpnId.getValue());
2790 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2791 routerId.getRouterId());
2792 associateRouterToVpn(vpnId, routerId.getRouterId());
2795 returnMsg.append("router not found : ").append(routerId.getRouterId());
2798 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2800 if (returnMsg.length() != 0) {
2801 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2802 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2803 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2805 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2808 LOG.debug("associateRouter returns..");
2813 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2816 // TODO Clean up the exception handling
2817 @SuppressWarnings("checkstyle:IllegalCatch")
2818 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2819 GetFixedIPsForNeutronPortInput input) {
2820 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2821 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2822 Uuid portId = input.getPortId();
2823 StringBuilder returnMsg = new StringBuilder();
2825 List<String> fixedIPList = new ArrayList<>();
2826 Port port = neutronvpnUtils.getNeutronPort(portId);
2828 for (FixedIps ip : port.nonnullFixedIps().values()) {
2829 fixedIPList.add(ip.getIpAddress().stringValue());
2832 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2834 if (returnMsg.length() != 0) {
2835 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2837 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2838 returnMsg)).build());
2840 opBuilder.setFixedIPs(fixedIPList);
2841 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2843 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2845 } catch (Exception ex) {
2846 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2847 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2848 portId.getValue(), ex.getMessage(), ex)).build());
2854 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2857 // TODO Clean up the exception handling
2858 @SuppressWarnings("checkstyle:IllegalCatch")
2859 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2861 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2862 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2864 LOG.debug("dissociateNetworks {}", input);
2865 StringBuilder returnMsg = new StringBuilder();
2866 Uuid vpnId = input.getVpnId();
2869 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2870 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2871 input.getNetworkId());
2872 List<Uuid> netIds = input.getNetworkId();
2873 if (netIds != null && !netIds.isEmpty()) {
2874 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2875 if (!failed.isEmpty()) {
2876 returnMsg.append(failed);
2880 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2882 if (returnMsg.length() != 0) {
2883 opBuilder.setResponse(
2884 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2885 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2887 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2889 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2891 } catch (Exception ex) {
2892 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2893 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2894 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2896 LOG.debug("dissociateNetworks returns..");
2901 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2904 // TODO Clean up the exception handling
2905 @SuppressWarnings("checkstyle:IllegalCatch")
2906 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2908 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2910 LOG.debug("dissociateRouter {}", input);
2911 StringBuilder returnMsg = new StringBuilder();
2912 Uuid vpnId = input.getVpnId();
2913 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2914 .RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2915 .dissociaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2916 String routerIdsString = "";
2917 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2918 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2919 Preconditions.checkNotNull(keyRouterIdsMap, "dissociateRouter: keyRouterIdsMap not found!");
2920 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2921 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2922 .RouterIds routerId : keyRouterIdsMap.values()) {
2924 if (routerId != null) {
2925 routerIdsString += routerId.getRouterId() + ", ";
2926 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2928 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2929 if (routerVpnId == null) {
2930 returnMsg.append("input router ").append(routerId.getRouterId())
2931 .append(" not associated to any vpn yet");
2932 } else if (vpnId.equals(routerVpnId)) {
2933 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2935 returnMsg.append("input router ").append(routerId.getRouterId())
2936 .append(" associated to vpn ")
2937 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2940 returnMsg.append("router not found : ").append(routerId.getRouterId());
2943 if (returnMsg.length() != 0) {
2944 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2945 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2946 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2947 returnMsg)).build());
2949 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2951 } catch (Exception ex) {
2952 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2953 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2954 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2958 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2961 LOG.debug("dissociateRouter returns..");
2965 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2966 // check if the router is associated to some VPN
2967 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2968 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2969 if (vpnId != null) {
2970 // remove existing external vpn interfaces
2971 for (Uuid subnetId : routerSubnetIds) {
2972 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
2973 if (subnetmap != null) {
2974 removeSubnetFromVpn(vpnId, subnetmap, internetVpnId);
2976 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
2977 subnetId, routerId.getValue());
2980 clearFromVpnMaps(vpnId, routerId, null);
2982 // remove existing internal vpn interfaces
2983 for (Uuid subnetId : routerSubnetIds) {
2984 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
2985 if (subnetmap != null) {
2986 removeSubnetFromVpn(routerId, subnetmap, internetVpnId);
2988 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
2989 subnetId, routerId.getValue());
2993 // delete entire vpnMaps node for internal VPN
2994 deleteVpnMapsNode(routerId);
2996 // delete vpn-instance for internal VPN
2997 deleteVpnInstance(routerId);
3000 protected Subnet getNeutronSubnet(Uuid subnetId) {
3001 return neutronvpnUtils.getNeutronSubnet(subnetId);
3005 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
3006 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
3008 return sn.getGatewayIp();
3014 protected Network getNeutronNetwork(Uuid networkId) {
3015 return neutronvpnUtils.getNeutronNetwork(networkId);
3018 protected Port getNeutronPort(String name) {
3019 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3022 protected Port getNeutronPort(Uuid portId) {
3023 return neutronvpnUtils.getNeutronPort(portId);
3026 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3027 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3030 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3031 return neutronvpnUtils.getNetworksForVpn(vpnId);
3035 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3037 * @return a List of String to be printed on screen
3038 * @throws ExecutionException or InterruptedException if there was a problem reading from the data store
3040 public List<String> showNeutronPortsCLI() throws ExecutionException, InterruptedException {
3041 List<String> result = new ArrayList<>();
3042 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3044 result.add("-------------------------------------------------------------------------------------------");
3045 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3047 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3048 if (ports.isPresent() && ports.get().getPort() != null) {
3049 for (Port port : ports.get().nonnullPort().values()) {
3050 Map<FixedIpsKey, FixedIps> keyFixedIpsMap = port.getFixedIps();
3051 if (keyFixedIpsMap != null && !keyFixedIpsMap.isEmpty()) {
3052 List<String> ipList = new ArrayList<>();
3053 for (FixedIps fixedIp : keyFixedIpsMap.values()) {
3054 IpAddress ipAddress = fixedIp.getIpAddress();
3055 if (ipAddress.getIpv4Address() != null) {
3056 ipList.add(ipAddress.getIpv4Address().getValue());
3058 ipList.add(ipAddress.getIpv6Address().getValue());
3061 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3062 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3063 ipList.toString()));
3065 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3066 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3075 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3077 * @param vpnuuid Uuid of the VPN whose config must be shown
3078 * @return formatted output list
3079 * @throws InterruptedException if there was a thread related problem getting the data to display
3080 * @throws ExecutionException if there was any other problem getting the data to display
3082 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3083 List<String> result = new ArrayList<>();
3084 if (vpnuuid == null) {
3086 result.add("Displaying VPN config for all VPNs");
3087 result.add("To display VPN config for a particular VPN, use the following syntax");
3088 result.add(getshowVpnConfigCLIHelp());
3090 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3091 if (rpcResult.isSuccessful()) {
3093 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3095 result.add(String.format(" %-80s ", "Import-RTs"));
3097 result.add(String.format(" %-80s ", "Export-RTs"));
3099 result.add(String.format(" %-76s ", "Subnet IDs"));
3101 result.add("------------------------------------------------------------------------------------");
3103 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3104 rpcResult.getResult().nonnullL3vpnInstances()) {
3105 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3107 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3108 vpn.getRouteDistinguisher()));
3110 result.add(String.format(" %-80s ", vpn.getImportRT()));
3112 result.add(String.format(" %-80s ", vpn.getExportRT()));
3115 Uuid vpnid = vpn.getId();
3116 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3117 if (!subnetList.isEmpty()) {
3118 for (Uuid subnetuuid : subnetList) {
3119 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3122 result.add(String.format(" %-76s ", "\" \""));
3125 result.add("----------------------------------------");
3129 String errortag = rpcResult.getErrors().iterator().next().getTag();
3130 if (Objects.equals(errortag, "")) {
3132 result.add("No VPN has been configured yet");
3133 } else if (Objects.equals(errortag, "invalid-value")) {
3135 result.add("VPN " + vpnuuid.getValue() + " is not present");
3137 result.add("error getting VPN info : " + rpcResult.getErrors());
3138 result.add(getshowVpnConfigCLIHelp());
3144 protected void createExternalVpnInterfaces(Uuid extNetId) {
3145 if (extNetId == null) {
3146 LOG.error("createExternalVpnInterfaces: external network is null");
3150 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3151 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3152 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3156 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3157 for (String elanInterface : extElanInterfaces) {
3158 createExternalVpnInterface(extNetId, elanInterface, tx);
3160 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3163 // TODO Clean up the exception handling
3164 @SuppressWarnings("checkstyle:IllegalCatch")
3165 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3166 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3167 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3168 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3171 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3172 for (String elanInterface : extElanInterfaces) {
3173 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3174 .buildVpnInterfaceIdentifier(elanInterface);
3175 LOG.info("Removing vpn interface {}", elanInterface);
3176 tx.delete(vpnIfIdentifier);
3178 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3181 private void createExternalVpnInterface(Uuid vpnId, String infName,
3182 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3183 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3184 false /* not a router iface */, wrtConfigTxn);
3187 // TODO Clean up the exception handling
3188 @SuppressWarnings("checkstyle:IllegalCatch")
3189 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3190 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3191 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3192 if (vpnIdList.isEmpty() || infName == null) {
3193 LOG.error("vpnid is empty or interface({}) is null", infName);
3196 if (wrtConfigTxn == null) {
3197 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3198 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3199 "Error writing VPN interface");
3202 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3203 for (Uuid vpnId: vpnIdList) {
3204 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3205 AssociatedSubnetType.V4AndV6Subnets);
3206 vpnIdListStruct.add(vpnInstance);
3209 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3210 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3212 .setVpnInstanceNames(vpnIdListStruct)
3213 .setRouterInterface(isRouterInterface);
3214 LOG.info("Network Id is {}", networkUuid);
3215 if (networkUuid != null) {
3216 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3217 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3218 NetworkAttributes.NetworkType networkType = providerType != null
3219 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3220 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3221 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3222 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3225 if (adjacencies != null) {
3226 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3228 VpnInterface vpnIf = vpnb.build();
3230 LOG.info("Creating vpn interface {}", vpnIf);
3231 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3232 } catch (Exception ex) {
3233 LOG.error("Creation of vpninterface {} failed", infName, ex);
3237 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3238 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3239 if (vpnId == null || infName == null) {
3240 LOG.error("vpn id or interface is null");
3243 if (wrtConfigTxn == null) {
3244 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3245 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3246 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3247 }), LOG, "Error updating VPN interface with adjacencies");
3251 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3253 try (AcquireResult lock = tryInterfaceLock(infName)) {
3254 if (!lock.wasAcquired()) {
3255 // FIXME: why do we even bother with locking if we do not honor it?!
3256 logTryLockFailure(infName);
3260 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3261 .syncReadOptional(dataBroker, LogicalDatastoreType
3262 .CONFIGURATION, vpnIfIdentifier);
3263 if (optionalVpnInterface.isPresent()) {
3264 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3265 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3267 if (adjacencies == null) {
3270 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3271 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3272 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3273 optionalVpnInterface.get().getVpnInstanceNames().values());
3274 if (listVpnInstances.isEmpty()
3275 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3276 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3277 AssociatedSubnetType.V4AndV6Subnets);
3278 listVpnInstances.add(vpnInstance);
3279 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3282 VpnInstanceNames vpnInstance = VpnHelper
3283 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3284 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3285 listVpnInstances.add(vpnInstance);
3286 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3288 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3289 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3291 } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
3292 // FIXME: why are we catching IllegalStateException here?
3293 LOG.error("Update of vpninterface {} failed", infName, ex);
3298 private String getshowVpnConfigCLIHelp() {
3299 StringBuilder help = new StringBuilder("Usage:");
3300 help.append("display vpn-config [-vid/--vpnid <id>]");
3301 return help.toString();
3304 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3305 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3309 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3310 return neutronEvpnManager.createEVPN(input);
3314 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3315 return neutronEvpnManager.getEVPN(input);
3319 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3320 return neutronEvpnManager.deleteEVPN(input);
3323 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3324 Uuid extNetId = extNet.getUuid();
3325 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3326 .child(Networks.class, new NetworksKey(extNetId)).build();
3329 Optional<Networks> optionalExtNets =
3330 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3332 if (!optionalExtNets.isPresent()) {
3333 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3334 extNetId.getValue());
3337 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3338 builder.setVpnid(vpnId);
3339 Networks networks = builder.build();
3340 // Add Networks object to the ExternalNetworks list
3341 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3342 extNetId.getValue());
3343 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3346 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3347 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3348 extNetId.getValue(), ex);
3353 private boolean removeExternalNetworkFromVpn(Network extNet) {
3354 Uuid extNetId = extNet.getUuid();
3355 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3356 .child(Networks.class, new NetworksKey(extNetId)).build();
3358 Optional<Networks> optionalNets =
3359 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3361 NetworksBuilder builder = null;
3362 if (optionalNets.isPresent()) {
3363 builder = new NetworksBuilder(optionalNets.get());
3365 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3366 extNetId.getValue());
3369 builder.setVpnid(null);
3370 Networks networks = builder.build();
3371 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3372 extNetId.getValue());
3373 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3375 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3376 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3377 extNetId.getValue(), ex);
3382 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3383 Optional<String> existingVpnName = Optional.of(primaryRd);
3384 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3386 vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3387 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3388 } catch (ExecutionException | InterruptedException e) {
3389 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3391 /*Read failed. We don't know if a VPN exists or not.
3392 * Return primaryRd to halt caller execution, to be safe.*/
3393 return existingVpnName;
3395 if (vpnInstanceOpDataOptional.isPresent()) {
3396 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3398 existingVpnName = Optional.empty();
3400 return existingVpnName;
3403 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3404 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3407 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3408 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3411 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3412 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3415 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3416 String message = tuple.getMessage();
3417 logger.accept(message);
3421 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3422 @NonNull Subnetmap subnetMap) {
3423 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3424 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3425 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3426 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3427 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3428 subnetMap.getId().getValue(), internetVpnId.getValue());
3432 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3433 @NonNull Subnetmap subnetMap) {
3434 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3435 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3438 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3439 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3440 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3441 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3442 internetVpnId.getValue(), routerId.getValue());
3443 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3449 private AcquireResult tryInterfaceLock(final String infName) {
3450 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3454 private AcquireResult tryVpnLock(final Uuid vpnId) {
3455 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3458 private static ReentrantLock lockForUuid(Uuid uuid) {
3459 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3460 return JvmGlobalLocks.getLockForString(uuid.getValue());
3463 private static void logTryLockFailure(Object objectId) {
3464 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());