2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
14 import com.google.common.base.Preconditions;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.JdkFutureAdapters;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
33 import java.util.Optional;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.locks.ReentrantLock;
40 import java.util.function.Consumer;
41 import javax.annotation.PreDestroy;
42 import javax.inject.Inject;
43 import javax.inject.Singleton;
44 import org.eclipse.jdt.annotation.NonNull;
45 import org.eclipse.jdt.annotation.Nullable;
46 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
47 import org.opendaylight.genius.infra.Datastore.Configuration;
48 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
49 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
50 import org.opendaylight.genius.infra.TypedWriteTransaction;
51 import org.opendaylight.genius.mdsalutil.NwConstants;
52 import org.opendaylight.genius.utils.JvmGlobalLocks;
53 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
54 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
55 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
56 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
57 import org.opendaylight.mdsal.binding.api.DataBroker;
58 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
59 import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
60 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
61 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
62 import org.opendaylight.netvirt.elanmanager.api.IElanService;
63 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
64 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
65 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
66 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
67 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
68 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
69 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNamesKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsKey;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
181 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
182 import org.opendaylight.yangtools.yang.common.RpcError;
183 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
184 import org.opendaylight.yangtools.yang.common.RpcResult;
185 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
186 import org.slf4j.Logger;
187 import org.slf4j.LoggerFactory;
188 import org.slf4j.helpers.FormattingTuple;
189 import org.slf4j.helpers.MessageFormatter;
192 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
194 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
195 private static final long LOCK_WAIT_TIME = 10L;
197 private final DataBroker dataBroker;
198 private final ManagedNewTransactionRunner txRunner;
199 private final VpnRpcService vpnRpcService;
200 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
201 private final IElanService elanService;
202 private final NeutronvpnConfig neutronvpnConfig;
203 private final NeutronEvpnManager neutronEvpnManager;
204 private final NeutronEvpnUtils neutronEvpnUtils;
205 private final JobCoordinator jobCoordinator;
206 private final NeutronvpnUtils neutronvpnUtils;
207 private final IVpnManager vpnManager;
208 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
209 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
210 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
211 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
214 public NeutronvpnManager(
215 final DataBroker dataBroker,
216 final VpnRpcService vpnRpcSrv, final IElanService elanService,
217 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
218 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
219 final JobCoordinator jobCoordinator,
220 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
221 this.dataBroker = dataBroker;
222 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
223 vpnRpcService = vpnRpcSrv;
224 this.elanService = elanService;
225 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
226 this.neutronvpnConfig = neutronvpnConfig;
227 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
228 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
229 this.jobCoordinator = jobCoordinator;
230 this.neutronvpnUtils = neutronvpnUtils;
231 this.vpnManager = vpnManager;
238 public void close() {
239 LOG.info("{} close", getClass().getSimpleName());
242 private void configureFeatures() throws TransactionCommitFailedException {
243 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
244 Neutron.class).child(Features.class).child(
245 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
246 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
248 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
249 } catch (OptimisticLockFailedException e) {
250 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
252 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
253 Neutron.class).child(Features.class).child(
254 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
255 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
257 SingleTransactionDataBroker.syncWrite(
258 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
259 } catch (OptimisticLockFailedException e) {
260 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
264 public String getOpenDaylightVniRangesConfig() {
265 return neutronvpnConfig.getOpendaylightVniRanges();
268 // TODO Clean up the exception handling
269 @SuppressWarnings("checkstyle:IllegalCatch")
270 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
271 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
272 boolean isExternalNw) {
274 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
275 final ReentrantLock lock = lockForUuid(subnetId);
278 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
279 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
280 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
281 if (sn.isPresent()) {
282 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
283 subnetId.getValue());
286 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
287 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
288 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
289 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
290 subnetId.getValue());
291 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
292 subnetMapIdentifier, subnetmapBuilder.build());
296 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
297 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
299 // check if there are ports to update for already created Subnetmap node
300 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
301 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
302 if (entry.getValue().getValue().equals(subnetId.getValue())) {
303 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
304 unprocessedPortsMap.remove(entry.getKey());
310 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
311 @Nullable Uuid internetvpnId) {
312 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
313 .child(Subnetmap.class, new SubnetmapKey(subnetId))
315 final ReentrantLock lock = lockForUuid(subnetId);
318 Optional<Subnetmap> sn =
319 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
320 if (!sn.isPresent()) {
321 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
324 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
325 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
326 if (routerId != null) {
327 builder.setRouterId(routerId);
330 builder.setVpnId(vpnId);
332 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
333 builder.setInternetVpnId(internetvpnId);
335 Subnetmap subnetmap = builder.build();
336 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
337 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
339 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
340 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
347 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
348 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
349 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
350 InstanceIdentifier<Subnetmap> id =
351 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
352 final ReentrantLock lock = lockForUuid(subnetId);
355 Optional<Subnetmap> sn =
356 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
357 if (!sn.isPresent()) {
358 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
359 subnetId.getValue());
362 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
363 subnetId.getValue());
364 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
365 builder.setRouterId(routerId);
366 builder.setRouterInterfacePortId(routerInterfacePortId);
367 builder.setRouterIntfMacAddress(routerIntfMacAddress);
368 builder.setRouterInterfaceFixedIp(fixedIp);
370 builder.setVpnId(vpnId);
372 Subnetmap subnetmap = builder.build();
373 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
374 subnetId.getValue());
375 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
376 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
377 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
378 subnetId.getValue(), e);
384 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
385 @Nullable Uuid directPortId) {
386 Subnetmap subnetmap = null;
387 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
388 new SubnetmapKey(subnetId)).build();
389 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
390 final ReentrantLock lock = lockForUuid(subnetId);
393 Optional<Subnetmap> sn =
394 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
396 if (sn.isPresent()) {
397 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
398 if (null != portId) {
399 List<Uuid> existingPortList = builder.getPortList();
400 List<Uuid> portList = new ArrayList<>();
401 if (null != existingPortList) {
402 portList.addAll(existingPortList);
404 portList.add(portId);
405 builder.setPortList(portList);
406 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
407 subnetId.getValue(), portId.getValue());
409 if (null != directPortId) {
410 List<Uuid> existingDirectPortList = builder.getDirectPortList();
411 List<Uuid> directPortList = new ArrayList<>();
412 if (null != existingDirectPortList) {
413 directPortList.addAll(existingDirectPortList);
415 directPortList.add(directPortId);
416 builder.setDirectPortList(directPortList);
417 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
418 directPortId.getValue());
420 subnetmap = builder.build();
421 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
424 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
425 + "cache ", subnetId.getValue(), portId.getValue());
426 unprocessedPortsMap.put(portId, subnetId);
428 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
429 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
436 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
437 Uuid vpnId, @Nullable Uuid portId) {
438 Subnetmap subnetmap = null;
439 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
440 .child(Subnetmap.class, new SubnetmapKey(subnetId))
442 final ReentrantLock lock = lockForUuid(subnetId);
445 Optional<Subnetmap> sn =
446 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
448 if (sn.isPresent()) {
449 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
450 if (routerId != null) {
451 builder.setRouterId(null);
453 if (networkId != null) {
454 builder.setNetworkId(null);
457 builder.setVpnId(null);
459 builder.setInternetVpnId(null);
460 if (portId != null && builder.getPortList() != null) {
461 List<Uuid> portList = new ArrayList<>(builder.getPortList());
462 portList.remove(portId);
463 builder.setPortList(portList);
466 subnetmap = builder.build();
467 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
468 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
471 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
473 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
474 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
482 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
483 @Nullable Uuid directPortId) {
484 Subnetmap subnetmap = null;
485 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
486 new SubnetmapKey(subnetId)).build();
487 final ReentrantLock lock = lockForUuid(subnetId);
490 Optional<Subnetmap> sn =
491 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
493 if (sn.isPresent()) {
494 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
495 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
496 List<Uuid> portList = new ArrayList<>(builder.getPortList());
497 portList.remove(portId);
498 builder.setPortList(portList);
499 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
500 subnetId.getValue());
502 if (null != directPortId && null != builder.getDirectPortList()
503 && !builder.getDirectPortList().isEmpty()) {
504 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
505 directPortList.remove(directPortId);
506 builder.setDirectPortList(directPortList);
507 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
508 .getValue(), subnetId.getValue());
510 subnetmap = builder.build();
511 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
514 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
516 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
517 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
518 subnetId.getValue(), e);
525 // TODO Clean up the exception handling
526 @SuppressWarnings("checkstyle:IllegalCatch")
527 protected void deleteSubnetMapNode(Uuid subnetId) {
528 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
529 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
530 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
531 final ReentrantLock lock = lockForUuid(subnetId);
534 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
535 } catch (TransactionCommitFailedException e) {
536 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
542 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
543 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
544 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
546 Optional<VpnInstance> vpnInstanceConfig =
547 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
549 if (!vpnInstanceConfig.isPresent()) {
550 LOG.debug("updateVpnInstanceWithRDs: "
551 + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
554 VpnInstance vpnInstance = vpnInstanceConfig.get();
555 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
556 updateVpnInstanceBuilder.setRouteDistinguisher(rds);
557 LOG.debug("updateVpnInstanceWithRDs: "
558 + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
559 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
560 updateVpnInstanceBuilder.build());
561 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
562 LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
563 + "the list of RDs: {}", vpnInstanceId, rds, ex);
567 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
568 boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
569 String vpnName = vpnId.getValue();
570 VpnInstanceBuilder builder = null;
571 List<VpnTarget> vpnTargetList = new ArrayList<>();
572 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
573 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
574 Optional<VpnInstance> optionalVpn;
576 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
578 } catch (ExecutionException | InterruptedException e) {
579 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
583 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
584 if (optionalVpn.isPresent()) {
585 builder = new VpnInstanceBuilder(optionalVpn.get());
586 LOG.debug("updating existing vpninstance node");
588 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
589 .setL2vpn(isL2Vpn).setL3vni(l3vni);
591 if (irt != null && !irt.isEmpty()) {
592 if (ert != null && !ert.isEmpty()) {
593 List<String> commonRT = new ArrayList<>(irt);
594 commonRT.retainAll(ert);
596 for (String common : commonRT) {
599 VpnTarget vpnTarget =
600 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
601 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
602 vpnTargetList.add(vpnTarget);
605 for (String importRT : irt) {
606 VpnTarget vpnTarget =
607 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
608 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
609 vpnTargetList.add(vpnTarget);
613 if (ert != null && !ert.isEmpty()) {
614 for (String exportRT : ert) {
615 VpnTarget vpnTarget =
616 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
617 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
618 vpnTargetList.add(vpnTarget);
622 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
623 if (rd != null && !rd.isEmpty()) {
624 builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets);
627 builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
628 VpnInstance newVpn = builder.build();
629 try (AcquireResult lock = tryVpnLock(vpnId)) {
630 if (!lock.wasAcquired()) {
631 // FIXME: why do we even bother with locking if we do not honor it?!
632 logTryLockFailure(vpnId);
635 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
637 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
639 } catch (TransactionCommitFailedException e) {
640 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
645 private void deleteVpnMapsNode(Uuid vpnId) {
646 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
647 .child(VpnMap.class, new VpnMapKey(vpnId))
649 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
650 try (AcquireResult lock = tryVpnLock(vpnId)) {
651 if (!lock.wasAcquired()) {
652 // FIXME: why do we even bother with locking if we do not honor it?!
653 logTryLockFailure(vpnId);
657 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
659 } catch (TransactionCommitFailedException e) {
660 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
665 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
666 @Nullable List<Uuid> networks) {
667 VpnMapBuilder builder;
668 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
669 .child(VpnMap.class, new VpnMapKey(vpnId))
672 Optional<VpnMap> optionalVpnMap =
673 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
675 if (optionalVpnMap.isPresent()) {
676 builder = new VpnMapBuilder(optionalVpnMap.get());
678 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
682 builder.setName(name);
684 if (tenantId != null) {
685 builder.setTenantId(tenantId);
687 if (router != null) {
688 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
689 List<RouterIds> rtrIds = builder.getRouterIds().values() != null
690 ? new ArrayList<>(builder.getRouterIds().values()) : null;
691 if (rtrIds == null) {
692 rtrIds = Collections.singletonList(vpnRouterId);
694 rtrIds.add(vpnRouterId);
696 builder.setRouterIds(rtrIds);
698 if (networks != null) {
699 List<Uuid> nwList = builder.getNetworkIds() != null
700 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
701 nwList.addAll(networks);
702 builder.setNetworkIds(nwList);
705 try (AcquireResult lock = tryVpnLock(vpnId)) {
706 if (!lock.wasAcquired()) {
707 // FIXME: why do we even bother with locking if we do not honor it?!
708 logTryLockFailure(vpnId);
711 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
712 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
714 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
716 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
717 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
721 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
722 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
723 .child(VpnMap.class, new VpnMapKey(vpnId))
725 Optional<VpnMap> optionalVpnMap;
728 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
730 } catch (ExecutionException | InterruptedException e) {
731 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
734 if (optionalVpnMap.isPresent()) {
735 VpnMap vpnMap = optionalVpnMap.get();
736 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
737 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds().values());
738 if (rtrIds == null) {
739 rtrIds = new ArrayList<>();
741 if (routerId != null) {
742 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
743 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
744 vpnMapBuilder.setRouterIds(rtrIds);
746 try (AcquireResult lock = tryVpnLock(vpnId)) {
747 if (!lock.wasAcquired()) {
748 // FIXME: why do we even bother with locking if we do not honor it?!
749 logTryLockFailure(vpnId);
752 LOG.debug("removing vpnMaps node: {} ", vpnId);
754 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
756 } catch (TransactionCommitFailedException e) {
757 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
761 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
762 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
763 vpnMapBuilder.setRouterIds(rtrIds);
764 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
767 if (networkIds != null) {
768 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
769 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
770 vpnNw.removeAll(networkIds);
771 if (vpnNw.isEmpty()) {
772 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
773 vpnMapBuilder.setNetworkIds(null);
775 vpnMapBuilder.setNetworkIds(vpnNw);
779 try (AcquireResult lock = tryVpnLock(vpnId)) {
780 if (!lock.wasAcquired()) {
781 // FIXME: why do we even bother with locking if we do not honor it?!
782 logTryLockFailure(vpnId);
785 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
787 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
788 vpnMapIdentifier, vpnMapBuilder.build());
789 } catch (TransactionCommitFailedException e) {
790 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
794 LOG.error("VPN : {} not found", vpnId.getValue());
796 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
799 private void deleteVpnInstance(Uuid vpnId) {
800 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
801 .child(VpnInstance.class,
802 new VpnInstanceKey(vpnId.getValue()))
805 try (AcquireResult lock = tryVpnLock(vpnId)) {
806 if (!lock.wasAcquired()) {
807 // FIXME: why do we even bother with locking if we do not honor it?!
808 logTryLockFailure(vpnId);
811 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
813 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
814 } catch (TransactionCommitFailedException e) {
815 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
820 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
821 TypedWriteTransaction<Configuration> wrtConfigTxn,
822 @Nullable VpnInterface vpnIface) {
823 List<Adjacency> adjList = new ArrayList<>();
824 if (vpnIface != null) {
825 adjList = new ArrayList<Adjacency>(vpnIface.augmentation(Adjacencies.class).getAdjacency().values());
827 String infName = port.getUuid().getValue();
828 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
829 for (FixedIps ip : port.nonnullFixedIps().values()) {
830 String ipValue = ip.getIpAddress().stringValue();
831 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
832 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
833 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
834 snTemp.getSubnetIp(), false)) {
837 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
839 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
840 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
841 //Create Neutron port adjacency if VPN presence is existing for subnet
842 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
843 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
844 .setSubnetId(ip.getSubnetId()).build();
845 if (!adjList.contains(vmAdj)) {
849 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
850 if (snTemp != null && snTemp.getInternetVpnId() != null) {
851 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
852 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
854 if (routerId != null) {
855 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
856 if (rtr != null && rtr.getRoutes() != null) {
857 List<Routes> routeList = new ArrayList<Routes>(rtr.getRoutes().values());
858 // create extraroute Adjacence for each ipValue,
859 // because router can have IPv4 and IPv6 subnet ports, or can have
860 // more that one IPv4 subnet port or more than one IPv6 subnet port
861 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
862 if (!erAdjList.isEmpty()) {
863 adjList.addAll(erAdjList);
868 return new AdjacenciesBuilder().setAdjacency(adjList).build();
871 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
872 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
873 boolean isRouterInterface = false;
874 if (port.getDeviceOwner() != null) {
875 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
877 String infName = port.getUuid().getValue();
878 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
879 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
880 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
881 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
882 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
885 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
886 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
887 String infName = port.getUuid().getValue();
888 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
889 Optional<VpnInterface> optionalVpnInterface = null;
890 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
891 vpnId, internetVpnId, infName);
893 optionalVpnInterface = SingleTransactionDataBroker
894 .syncReadOptional(dataBroker, LogicalDatastoreType
895 .CONFIGURATION, vpnIfIdentifier);
896 } catch (ExecutionException | InterruptedException e) {
897 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
900 if (!optionalVpnInterface.isPresent()) {
903 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
904 sn != null ? sn.getSubnetIp() : "null");
905 Map<AdjacencyKey, Adjacency> keyAdjacencyMap
906 = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
907 List<Adjacency> updatedAdjsList = new ArrayList<>();
908 boolean isIpFromAnotherSubnet = false;
909 for (Adjacency adj : keyAdjacencyMap.values()) {
910 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
911 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
912 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
913 isIpFromAnotherSubnet = true;
915 updatedAdjsList.add(adj);
918 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
919 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
922 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
923 String.valueOf(adjString), wrtConfigTxn);
925 if (internetVpnId != null) {
926 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
927 String.valueOf(adjString), wrtConfigTxn);
930 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
931 && sn.getRouterId() != null) {
932 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
933 if (rtr != null && rtr.getRoutes() != null) {
934 List<Routes> extraRoutesToRemove = new ArrayList<>();
935 for (Routes rt: rtr.getRoutes().values()) {
936 if (rt.getNexthop().toString().equals(adjString)) {
937 extraRoutesToRemove.add(rt);
941 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
942 extraRoutesToRemove, vpnId);
943 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
945 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
950 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
952 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
954 if (!isIpFromAnotherSubnet) {
955 // no more subnetworks for neutron port
956 if (sn != null && sn.getRouterId() != null) {
957 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
959 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
965 // TODO Clean up the exception handling
966 @SuppressWarnings("checkstyle:IllegalCatch")
967 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
968 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
969 if (wrtConfigTxn == null) {
970 ListenableFutures.addErrorLogging(
971 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
972 tx -> deleteVpnInterface(infName, vpnId, tx)),
973 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
977 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
978 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
979 Optional<VpnInterface> optionalVpnInterface;
981 optionalVpnInterface =
982 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
984 } catch (ExecutionException | InterruptedException ex) {
985 LOG.error("Error during deletion of vpninterface {}", infName, ex);
988 if (!optionalVpnInterface.isPresent()) {
989 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
993 VpnInterface vpnInterface = optionalVpnInterface.get();
994 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap = vpnInterface.getVpnInstanceNames();
995 if (keyVpnInstanceNamesMap != null
996 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId,
997 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
998 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId,
999 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
1000 if (!keyVpnInstanceNamesMap.isEmpty()) {
1001 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1002 + "List not empty", infName);
1005 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1006 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1007 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1011 LOG.debug("Deleting vpn interface {}", infName);
1012 wrtConfigTxn.delete(vpnIfIdentifier);
1015 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1016 TypedWriteTransaction<Configuration> writeConfigTxn,
1018 if (vpnId == null || port == null) {
1021 String infName = port.getUuid().getValue();
1022 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1024 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1025 .syncReadOptional(dataBroker, LogicalDatastoreType
1026 .CONFIGURATION, vpnIfIdentifier);
1027 if (optionalVpnInterface.isPresent()) {
1028 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap
1029 = optionalVpnInterface.get().getVpnInstanceNames();
1030 if (keyVpnInstanceNamesMap != null
1031 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),
1032 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
1033 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(),
1034 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
1036 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1037 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1038 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1039 LOG.debug("Updating vpn interface {}", infName);
1040 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency() : new HashMap<>();
1041 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1042 while (adjacencyIter.hasNext()) {
1043 Adjacency adjacency = adjacencyIter.next();
1044 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1047 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1048 InstanceIdentifier<LearntVpnVipToPort> id =
1049 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1050 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1051 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1052 LogicalDatastoreType.OPERATIONAL, id);
1053 if (optionalVpnVipToPort.isPresent()) {
1054 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1056 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1057 adjacencyIter.remove();
1059 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1060 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1061 mipToQuery, infName, vpnId.getValue());
1064 for (FixedIps ip : port.nonnullFixedIps().values()) {
1065 String ipValue = ip.getIpAddress().stringValue();
1067 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1070 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1071 ipValue, writeConfigTxn);
1073 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1074 if (sm != null && sm.getRouterId() != null) {
1075 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1077 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1079 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1082 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1084 } catch (ExecutionException | InterruptedException ex) {
1085 LOG.error("Update of vpninterface {} failed", infName, ex);
1089 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1091 TypedWriteTransaction<Configuration> writeConfigTxn,
1092 boolean isInternetVpn) {
1093 if (vpnId == null || port == null) {
1096 String infName = port.getUuid().getValue();
1097 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1099 try (AcquireResult lock = tryInterfaceLock(infName)) {
1100 if (!lock.wasAcquired()) {
1101 // FIXME: why do we even bother with locking if we do not honor it?!
1102 logTryLockFailure(infName);
1106 Optional<VpnInterface> optionalVpnInterface =
1107 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1109 if (optionalVpnInterface.isPresent()) {
1110 VpnInstanceNames vpnInstance = VpnHelper
1111 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1112 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface.get()
1113 .getVpnInstanceNames().values());
1114 if (oldVpnId != null
1115 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1116 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1118 if (vpnId.getValue() != null
1119 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1120 listVpn.add(vpnInstance);
1122 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1123 .setVpnInstanceNames(listVpn);
1124 LOG.debug("Updating vpn interface {}", infName);
1125 if (!isBeingAssociated) {
1126 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1127 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency()
1128 : new HashMap<AdjacencyKey, Adjacency>();
1129 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1130 while (adjacencyIter.hasNext()) {
1131 Adjacency adjacency = adjacencyIter.next();
1132 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1133 InstanceIdentifier<LearntVpnVipToPort> id =
1134 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1135 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1136 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1137 LogicalDatastoreType.OPERATIONAL, id);
1138 if (optionalVpnVipToPort.isPresent()
1139 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1140 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1141 + "from VPN {}", infName, vpnId, oldVpnId);
1142 adjacencyIter.remove();
1143 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1145 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1146 mipToQuery, infName, vpnId.getValue());
1148 InstanceIdentifier<VpnPortipToPort> build =
1149 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1150 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1151 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1152 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1153 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1154 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1155 mipToQuery, infName, vpnId.getValue());
1158 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(keyAdjacencyMap).build();
1159 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1161 for (FixedIps ip : port.nonnullFixedIps().values()) {
1162 String ipValue = ip.getIpAddress().stringValue();
1163 if (oldVpnId != null) {
1164 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1165 ipValue, writeConfigTxn);
1167 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1168 && isInternetVpn == true) {
1172 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1173 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1175 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1177 LOG.error("VPN Interface {} not found", infName);
1179 } catch (ExecutionException | InterruptedException ex) {
1180 LOG.error("Updation of vpninterface {} failed", infName, ex);
1185 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1186 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1188 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1190 // Update VPN Instance node
1191 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
1193 // Update local vpn-subnet DS
1194 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1196 if (routerId != null) {
1197 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1198 if (existingVpn != null) {
1199 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1200 // if before reboot, router was already associated to VPN, should not proceed associating router to
1201 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1202 // preserved upon reboot.
1203 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1204 // RouterInterfacesMap via #createVPNInterface call.
1205 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1206 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1209 associateRouterToInternalVpn(vpnId, routerId);
1214 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1215 * specified Neutron Networks and Routers.
1217 * @param vpnId Uuid of the VPN tp be created
1218 * @param name Representative name of the new VPN
1219 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1220 * @param rdList Route-distinguisher for the VPN
1221 * @param irtList A list of Import Route Targets
1222 * @param ertList A list of Export Route Targets
1223 * @param routerIdsList ist of neutron router Id to associate with created VPN
1224 * @param networkList UUID of the neutron network the VPN may be associated to
1225 * @param isL2Vpn True if VPN Instance is of type L2, false if L3
1226 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1227 * @throws Exception if association of L3VPN failed
1229 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1230 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1231 boolean isL2Vpn, long l3vni) throws Exception {
1233 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1235 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1236 for (Uuid routerId : routerIdsList) {
1237 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1238 ipVersChoices = ipVersChoices.addVersion(vers);
1241 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
1243 // Please note that router and networks will be filled into VPNMaps
1244 // by subsequent calls here to associateRouterToVpn and
1245 // associateNetworksToVpn
1246 updateVpnMaps(vpnId, name, null, tenantId, null);
1247 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1248 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1251 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1252 for (Uuid routerId : routerIdsList) {
1253 associateRouterToVpn(vpnId, routerId);
1256 if (networkList != null) {
1257 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1258 if (!failStrings.isEmpty()) {
1259 LOG.error("VPN {} association to networks failed for networks: {}. ",
1260 vpnId.getValue(), failStrings);
1261 throw new Exception(failStrings.toString());
1267 * It handles the invocations to the createVPN RPC method.
1270 // TODO Clean up the exception handling
1271 @SuppressWarnings("checkstyle:IllegalCatch")
1272 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1274 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1275 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1276 List<RpcError> errorList = new ArrayList<>();
1277 int failurecount = 0;
1278 int warningcount = 0;
1280 List<L3vpn> vpns = input.getL3vpn();
1282 vpns = Collections.emptyList();
1284 for (L3vpn vpn : vpns) {
1285 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1286 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1287 formatAndLog(LOG::warn,
1288 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1289 vpn.getId().getValue())));
1293 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1294 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1295 formatAndLog(LOG::warn,
1296 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1297 vpn.getId().getValue())));
1302 if (vpn.getL3vni() != null) {
1303 l3vni = vpn.getL3vni().toJava();
1306 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1307 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1308 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1309 formatAndLog(LOG::warn,
1310 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1311 + "is already configured",
1312 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1316 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1317 if (operationalVpn.isPresent()) {
1318 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1319 formatAndLog(LOG::error,
1320 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1321 + "is still available. Please retry creation of a new vpn with the same RD"
1322 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1323 vpn.getRouteDistinguisher().get(0))));
1327 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1328 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
1329 .neutronvpn.rev150602.vpn.instance.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight
1330 .netvirt.neutronvpn.rev150602.vpn.instance.RouterIds> keyRouterIdsMap = vpn.getRouterIds();
1331 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1332 routerId : keyRouterIdsMap.values()) {
1333 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1334 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1335 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1336 + "{}", vpn.getId(), routerId.getRouterId())));
1340 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1341 if (vpnId != null) {
1342 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1343 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1344 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1345 vpnId.getValue())));
1351 if (vpn.getNetworkIds() != null) {
1352 int initialWarningCount = warningcount;
1353 for (Uuid nw : vpn.getNetworkIds()) {
1354 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1355 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1356 if (network == null) {
1357 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1358 formatAndLog(LOG::warn,
1359 "Creation of L3VPN failed for VPN {} due to network not found {}",
1360 vpn.getId().getValue(), nw.getValue())));
1362 } else if (vpnId != null) {
1363 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1364 formatAndLog(LOG::warn,
1365 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1366 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1367 vpnId.getValue())));
1371 if (warningcount != initialWarningCount) {
1375 List<Uuid> rtrIdsList = new ArrayList<>();
1376 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1377 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1378 rtrId : vpn.getRouterIds().values()) {
1379 rtrIdsList.add(rtrId.getRouterId());
1383 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1384 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1385 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1386 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1388 List<String> rdList = vpn.getRouteDistinguisher() != null
1389 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1390 List<String> importRdList = vpn.getImportRT() != null
1391 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1392 List<String> exportRdList = vpn.getExportRT() != null
1393 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1395 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1396 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
1397 } catch (Exception ex) {
1398 LOG.error("VPN Creation exception :", ex);
1399 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1400 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1405 // if at least one succeeds; result is success
1406 // if none succeeds; result is failure
1407 if (failurecount + warningcount == vpns.size()) {
1408 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1410 List<String> errorResponseList = new ArrayList<>();
1411 if (!errorList.isEmpty()) {
1412 for (RpcError rpcError : errorList) {
1413 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1414 + ", ErrorMessage: " + rpcError.getMessage());
1417 errorResponseList.add("Operation successful with no errors");
1419 opBuilder.setResponse(errorResponseList);
1420 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1426 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1429 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1431 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1432 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1433 Uuid inputVpnId = input.getId();
1434 List<VpnInstance> vpns = new ArrayList<>();
1435 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1438 if (inputVpnId == null) {
1440 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1442 Optional<VpnInstances> optionalVpns =
1443 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1445 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1446 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance().values()) {
1447 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1448 // from getL3VPN output
1449 if (vpn.getRouteDistinguisher() != null) {
1455 opBuilder.setL3vpnInstances(l3vpnList);
1456 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1460 String name = inputVpnId.getValue();
1461 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1462 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1463 // read VpnInstance Info
1464 Optional<VpnInstance> optionalVpn =
1465 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1467 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1469 if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
1470 vpns.add(optionalVpn.get());
1473 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1474 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1478 for (VpnInstance vpnInstance : vpns) {
1479 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1480 // create VpnMaps id
1481 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1482 List<String> rd = Collections.EMPTY_LIST;
1483 if (vpnInstance.getRouteDistinguisher() != null) {
1484 rd = vpnInstance.getRouteDistinguisher();
1486 List<String> ertList = new ArrayList<>();
1487 List<String> irtList = new ArrayList<>();
1489 if (vpnInstance.getVpnTargets() != null) {
1490 Map<VpnTargetKey, VpnTarget> keyVpnTargetMap = Collections.EMPTY_MAP;
1491 if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
1492 keyVpnTargetMap = vpnInstance.getVpnTargets().getVpnTarget();
1494 if (!keyVpnTargetMap.isEmpty()) {
1495 for (VpnTarget vpnTarget : keyVpnTargetMap.values()) {
1496 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1497 ertList.add(vpnTarget.getVrfRTValue());
1499 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1500 irtList.add(vpnTarget.getVrfRTValue());
1502 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1503 ertList.add(vpnTarget.getVrfRTValue());
1504 irtList.add(vpnTarget.getVrfRTValue());
1510 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1512 if (vpnInstance.getL3vni() != null) {
1513 l3vpn.setL3vni(vpnInstance.getL3vni());
1515 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1516 .class, new VpnMapKey(vpnId)).build();
1517 Optional<VpnMap> optionalVpnMap =
1518 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1520 if (optionalVpnMap.isPresent()) {
1521 VpnMap vpnMap = optionalVpnMap.get();
1522 List<Uuid> rtrIds = new ArrayList<>();
1523 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1524 for (RouterIds rtrId : vpnMap.getRouterIds().values()) {
1525 rtrIds.add(rtrId.getRouterId());
1528 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1529 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1530 .setName(vpnMap.getName());
1533 l3vpnList.add(l3vpn.build());
1536 opBuilder.setL3vpnInstances(l3vpnList);
1537 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1539 } catch (ExecutionException | InterruptedException ex) {
1540 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1541 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1547 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1550 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1552 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1553 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1554 List<RpcError> errorList = new ArrayList<>();
1556 int failurecount = 0;
1557 int warningcount = 0;
1558 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1559 for (Uuid vpn : vpns) {
1561 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1562 InstanceIdentifier<VpnInstance> vpnIdentifier =
1563 InstanceIdentifier.builder(VpnInstances.class)
1564 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1565 Optional<VpnInstance> optionalVpn =
1566 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1568 if (optionalVpn.isPresent()) {
1571 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1572 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1575 } catch (ExecutionException | InterruptedException ex) {
1576 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1577 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1582 // if at least one succeeds; result is success
1583 // if none succeeds; result is failure
1584 if (failurecount + warningcount == vpns.size()) {
1585 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1587 List<String> errorResponseList = new ArrayList<>();
1588 if (!errorList.isEmpty()) {
1589 for (RpcError rpcError : errorList) {
1590 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1591 + ", ErrorMessage: " + rpcError.getMessage());
1594 errorResponseList.add("Operation successful with no errors");
1596 opBuilder.setResponse(errorResponseList);
1597 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1602 public void createVpnInstanceForSubnet(Uuid subnetId) {
1603 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1604 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1607 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1608 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1609 removeVpn(subnetId);
1612 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1613 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1614 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1615 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1617 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1618 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1621 if (vpnId != null) {
1622 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1623 if (vpnMap == null) {
1624 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1625 + " cannot add subnet {} to VPN", vpnId.getValue(),
1629 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1630 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1631 if (isVpnOfTypeL2(vpnInstance)) {
1632 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1633 NeutronEvpnUtils.Operation.ADD);
1636 if (internetVpnId != null) {
1637 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1638 if (vpnMap == null) {
1639 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1640 + "subnet {} to VPN", internetVpnId.getValue(),
1645 final Uuid internetId = internetVpnId;
1646 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1647 List<Uuid> portList = sn.getPortList();
1648 if (portList != null) {
1649 for (final Uuid portId : portList) {
1650 String vpnInfName = portId.getValue();
1651 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1652 Port port = neutronvpnUtils.getNeutronPort(portId);
1654 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1655 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1658 final Boolean isRouterInterface = port.getDeviceOwner()
1659 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1660 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1661 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1663 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1665 if (vpnIface == null) {
1666 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1667 Set<Uuid> listVpn = new HashSet<>();
1668 if (vpnId != null) {
1671 if (internetId != null) {
1672 listVpn.add(internetId);
1674 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1675 isRouterInterface, wrtConfigTxn);
1676 if (sn.getRouterId() != null) {
1677 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1680 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1681 if (vpnId != null) {
1682 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1684 if (internetId != null) {
1685 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1689 ListenableFutures.addErrorLogging(future, LOG,
1690 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1691 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1692 return Collections.singletonList(future);
1698 protected void removeSubnetFromVpn(final Uuid vpnId, Subnetmap subnetmap, @Nullable Uuid internetVpnId) {
1699 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1700 "removeSubnetFromVpn: at least one VPN must be not null");
1701 Uuid subnetId = subnetmap.getId();
1702 LOG.debug("Removing subnet {} from vpn {}/{}", subnetId.getValue(),
1703 vpnId, internetVpnId);
1704 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnetId.getValue());
1705 VpnMap vpnMap = null;
1706 VpnInstance vpnInstance = null;
1707 if (vpnId != null) {
1708 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1709 if (vpnMap == null) {
1710 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1711 vpnId.getValue(), subnetId.getValue());
1714 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1716 if (internetVpnId == null) {
1717 internetVpnId = subnetmap.getInternetVpnId();
1719 if (internetVpnId != null) {
1720 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1721 if (vpnMap == null) {
1722 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1723 + " from Internet VPN",
1724 internetVpnId.getValue(), subnetId.getValue());
1728 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1729 neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(),
1730 NeutronEvpnUtils.Operation.DELETE);
1732 boolean subnetVpnAssociation = false;
1733 if (vpnId != null && subnetmap.getVpnId() != null
1734 && subnetmap.getVpnId().getValue().equals(vpnId.getValue())) {
1735 subnetVpnAssociation = true;
1736 } else if (internetVpnId != null && subnetmap.getInternetVpnId() != null
1737 && subnetmap.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1738 subnetVpnAssociation = true;
1740 if (subnetVpnAssociation == false) {
1741 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1742 vpnId, internetVpnId, subnetmap.getVpnId(), subnetmap.getInternetVpnId());
1745 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1746 List<Uuid> portList = subnetmap.getPortList();
1747 final Uuid internetId = internetVpnId;
1748 if (portList != null) {
1749 for (final Uuid portId : portList) {
1750 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", subnetmap.getSubnetIp(), portId.getValue());
1751 final Port port = neutronvpnUtils.getNeutronPort(portId);
1752 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1753 List<ListenableFuture<Void>> futures = new ArrayList<>();
1754 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1755 CONFIGURATION, tx -> {
1757 withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx);
1759 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1760 + " port is absent in Neutron config DS", portId.getValue(),
1761 subnetId.getValue());
1764 ListenableFutures.addErrorLogging(future, LOG,
1765 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1766 + " belonging to subnet {} and vpnId {}",
1767 portId.getValue(), subnetId.getValue(), vpnId.getValue());
1768 futures.add(future);
1773 //update subnet-vpn association
1774 removeFromSubnetNode(subnetId, null, null, vpnId, null);
1777 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1778 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1779 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1781 Uuid internalVpnId = sm.getVpnId();
1782 if (internalVpnId == null) {
1783 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1784 sm.getId().getValue());
1787 if (isBeingAssociated) {
1788 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1790 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1793 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1794 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1795 if (isBeingAssociated) {
1796 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1797 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1799 removeInternetVpnFromVpnInterface(vpn,
1800 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1805 // Check for ports on this subnet and update association of
1806 // corresponding vpn-interfaces to internet vpn
1807 List<Uuid> portList = sm.getPortList();
1808 if (portList != null) {
1809 for (Uuid port : portList) {
1810 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1811 port.getValue(), isBeingAssociated);
1812 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1813 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1815 if (isBeingAssociated) {
1816 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1817 true, false, tx, true);
1819 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1827 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1828 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1829 oldVpnId.getValue(), newVpnId.getValue());
1830 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1831 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1832 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1833 Uuid vpnExtUuid = netIsExternal ? null
1834 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1835 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1837 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1840 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1841 * associated with internet BGP-VPN.
1843 if (vpnExtUuid != null) {
1844 /* Update V6 Internet default route match with new VPN metadata.
1845 * isBeingAssociated = true means oldVpnId is same as routerId
1846 * isBeingAssociated = false means newVpnId is same as routerId
1848 if (isBeingAssociated) {
1849 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1851 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1854 //Update Router Interface first synchronously.
1855 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1856 ListenableFuture<Void> future =
1857 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1858 tx -> updateVpnInterface(newVpnId, oldVpnId,
1859 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1860 isBeingAssociated, true, tx, false));
1861 Futures.addCallback(future, new FutureCallback<Void>() {
1863 public void onSuccess(Void result) {
1864 // Check for ports on this subnet and update association of
1865 // corresponding vpn-interfaces to external vpn
1866 List<Uuid> portList = sn.getPortList();
1867 if (portList != null) {
1868 for (Uuid port : portList) {
1869 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1870 port.getValue(), isBeingAssociated);
1871 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1872 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1873 tx -> updateVpnInterface(newVpnId, oldVpnId,
1874 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1881 public void onFailure(Throwable throwable) {
1883 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1885 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1887 }, MoreExecutors.directExecutor());
1892 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1893 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1894 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1897 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1898 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1899 final ReentrantLock lock = lockForUuid(routerId);
1902 Optional<RouterInterfaces> optRouterInterfaces =
1903 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1904 routerInterfacesId);
1905 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1906 .setInterfaceId(interfaceName).build();
1907 if (optRouterInterfaces.isPresent()) {
1908 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1909 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1911 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1912 List<Interfaces> interfaces = new ArrayList<>();
1913 interfaces.add(routerInterface);
1914 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1915 routerInterfacesId, builder.setInterfaces(interfaces).build());
1917 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1918 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1924 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1925 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1926 final ReentrantLock lock = lockForUuid(routerId);
1929 Optional<RouterInterfaces> optRouterInterfaces =
1930 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1931 routerInterfacesId);
1932 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1933 .setInterfaceId(interfaceName).build();
1934 if (optRouterInterfaces.isPresent()) {
1935 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1936 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces().values());
1937 if (interfaces != null && interfaces.remove(routerInterface)) {
1938 if (interfaces.isEmpty()) {
1939 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1940 routerInterfacesId);
1942 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1943 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1947 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1948 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1955 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1956 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1957 * route will be ignored.
1959 * @param vpnName the VPN identifier
1960 * @param interVpnLinkRoutes The list of static routes
1961 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1963 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1964 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1965 for (Routes route : interVpnLinkRoutes) {
1966 String nexthop = route.getNexthop().stringValue();
1967 String destination = route.getDestination().stringValue();
1968 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1969 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1970 AddStaticRouteInput rpcInput =
1971 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1972 .setVpnInstanceName(vpnName.getValue())
1974 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1975 RpcResult<AddStaticRouteOutput> rpcResult;
1977 rpcResult = labelOuputFtr.get();
1978 if (rpcResult.isSuccessful()) {
1979 LOG.debug("Label generated for destination {} is: {}",
1980 destination, rpcResult.getResult().getLabel());
1982 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1983 destination, nexthop, rpcResult.getErrors());
1985 } catch (InterruptedException | ExecutionException e) {
1986 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1987 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1990 // Any other case is a fault.
1991 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1992 route.getDestination().stringValue(), nexthop);
1999 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2000 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2002 * @param vpnName the VPN identifier
2003 * @param interVpnLinkRoutes The list of static routes
2004 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2006 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2007 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2008 for (Routes route : interVpnLinkRoutes) {
2009 String nexthop = route.getNexthop().stringValue();
2010 String destination = route.getDestination().stringValue();
2011 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2012 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2013 RemoveStaticRouteInput rpcInput =
2014 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2015 .setVpnInstanceName(vpnName.getValue())
2018 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2019 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2021 // Any other case is a fault.
2022 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2023 route.getDestination().stringValue(), nexthop);
2030 * Returns true if the specified nexthop is the other endpoint in an
2031 * InterVpnLink, regarding one of the VPN's point of view.
2033 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2034 InterVpnLink interVpnLink) {
2036 interVpnLink != null
2037 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2038 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2039 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2040 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2044 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2045 List<Adjacency> adjList = new ArrayList<>();
2046 Map<String, List<String>> adjMap = new HashMap<>();
2047 for (Routes route : routeList) {
2048 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2049 LOG.error("Incorrect input received for extra route. {}", route);
2051 String nextHop = route.getNexthop().stringValue();
2052 String destination = route.getDestination().stringValue();
2053 if (!nextHop.equals(fixedIp)) {
2054 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2057 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2059 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2060 if (!hops.contains(nextHop)) {
2066 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2067 final String destination = entry.getKey();
2068 final List<String> ipList = entry.getValue();
2069 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2070 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2071 .withKey(new AdjacencyKey(destination)).build();
2077 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2078 checkAlarmExtraRoutes(vpnId, routeList);
2080 for (Routes route : routeList) {
2081 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2082 LOG.error("Incorrect input received for extra route. {}", route);
2084 String nextHop = route.getNexthop().stringValue();
2085 String destination = route.getDestination().stringValue();
2086 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2088 if (infName != null) {
2089 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2090 destination, vpnId.getValue(), nextHop, infName);
2091 boolean isLockAcquired = false;
2093 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2094 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2095 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2096 .child(Adjacency.class, new AdjacencyKey(destination));
2097 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2098 LogicalDatastoreType.CONFIGURATION, path);
2099 if (existingAdjacency.isPresent()
2100 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2101 LOG.error("The route with destination {} nextHop {} is already present as"
2102 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2103 destination, nextHop, infName);
2106 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2107 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2108 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2110 try (AcquireResult lock = tryInterfaceLock(infName)) {
2111 if (!lock.wasAcquired()) {
2112 // FIXME: why do we even bother with locking if we do not honor it?!
2113 logTryLockFailure(infName);
2116 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2119 } catch (TransactionCommitFailedException e) {
2120 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2121 destination, nextHop, e);
2122 } catch (ExecutionException | InterruptedException e) {
2123 LOG.error("Exception on reading data-store ", e);
2126 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2127 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2134 * This method setup or down an alarm about extra route fault.
2135 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2136 * available RDs, then an alarm and an error is generated.<br>
2137 * <b>Be careful</b> the routeList could be changed.
2139 * @param vpnId the vpnId of vpn to control.
2140 * @param routeList the list of router to check, it could be modified.
2142 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2143 if (!neutronvpnAlarm.isAlarmEnabled()) {
2144 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2147 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2148 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2149 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2153 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2154 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2155 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2159 for (Routes route : routeList) {
2160 // count the number of nexthops for each same route.getDestingation().getValue()
2161 String destination = route.getDestination().stringValue();
2162 String nextHop = route.getNexthop().stringValue();
2163 List<String> nextHopList = new ArrayList<>();
2164 nextHopList.add(nextHop);
2166 for (Routes routeTmp : routeList) {
2167 String routeDest = routeTmp.getDestination().stringValue();
2168 if (!destination.equals(routeDest)) {
2171 String routeNextH = routeTmp.getNexthop().stringValue();
2172 if (nextHop.equals(routeNextH)) {
2176 nextHopList.add(routeTmp.getNexthop().stringValue());
2178 final List<String> rdList = new ArrayList<>();
2179 if (vpnInstance != null
2180 && vpnInstance.getRouteDistinguisher() != null) {
2181 vpnInstance.getRouteDistinguisher().forEach(rd -> {
2187 // 1. VPN Instance Name
2188 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2191 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2192 Uuid routerUuid = routerUuidList.get(0);
2193 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2194 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2196 // 3. List of RDs associated with the VPN
2197 detailsAlarm.append(" List of RDs associated with the VPN: ");
2198 for (String s : rdList) {
2199 detailsAlarm.append(s);
2200 detailsAlarm.append(", ");
2203 // 4. Prefix in question
2204 detailsAlarm.append(" for prefix: ");
2205 detailsAlarm.append(route.getDestination().stringValue());
2207 // 5. List of NHs for the prefix
2208 detailsAlarm.append(" for nextHops: ");
2209 for (String s : nextHopList) {
2210 detailsAlarm.append(s);
2211 detailsAlarm.append(", ");
2214 if (rdList.size() < nbNextHops) {
2215 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2217 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2222 // TODO Clean up the exception handling
2223 @SuppressWarnings("checkstyle:IllegalCatch")
2224 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2225 for (Routes route : routeList) {
2226 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2227 String nextHop = route.getNexthop().stringValue();
2228 String destination = route.getDestination().stringValue();
2229 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2231 if (infName == null) {
2232 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2233 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2234 // Proceed to remove the next extra-route
2237 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2238 destination, vpnId.getValue(), nextHop, infName);
2240 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2241 InstanceIdentifier.builder(VpnInterfaces.class)
2242 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2243 .augmentation(Adjacencies.class)
2244 .child(Adjacency.class, new AdjacencyKey(destination))
2248 // Looking for existing prefix in MDSAL database
2249 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2250 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2251 boolean updateNextHops = false;
2252 List<String> nextHopList = new ArrayList<>();
2253 if (adjacency.isPresent()) {
2254 List<String> nhListRead = adjacency.get().getNextHopIpList();
2255 if (nhListRead.size() > 1) { // ECMP case
2256 for (String nextHopRead : nhListRead) {
2257 if (nextHopRead.equals(nextHop)) {
2258 updateNextHops = true;
2260 nextHopList.add(nextHopRead);
2266 try (AcquireResult lock = tryInterfaceLock(infName)) {
2267 if (!lock.wasAcquired()) {
2268 // FIXME: why do we even bother with locking if we do not honor it?!
2269 logTryLockFailure(infName);
2272 if (updateNextHops) {
2273 // An update must be done, not including the current next hop
2274 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2275 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2276 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2277 .setNextHopIpList(nextHopList)
2278 .withKey(new AdjacencyKey(destination))
2280 Adjacencies erAdjs =
2281 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2282 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2283 .addAugmentation(Adjacencies.class, erAdjs).build();
2284 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2285 vpnIfIdentifier, vpnIf);
2287 // Remove the whole route
2288 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2289 adjacencyIdentifier);
2290 LOG.trace("extra route {} deleted successfully", route);
2293 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
2294 LOG.error("exception in deleting extra route with destination {} for interface {}",
2295 destination, infName, e);
2298 LOG.error("Incorrect input received for extra route: {}", route);
2303 public void removeVpn(Uuid vpnId) {
2305 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2306 if (vpnMap != null) {
2307 Map<RouterIdsKey, RouterIds> keyRouterIdsMap = vpnMap.getRouterIds();
2308 List<Uuid> routerUuidList = new ArrayList<>();
2309 // dissociate router
2310 if (keyRouterIdsMap != null && !keyRouterIdsMap.isEmpty()) {
2311 for (RouterIds router : keyRouterIdsMap.values()) {
2312 Uuid routerId = router.getRouterId();
2313 routerUuidList.add(routerId);
2314 dissociateRouterFromVpn(vpnId, routerId);
2317 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2318 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2321 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2323 // remove entire vpnMaps node
2324 deleteVpnMapsNode(vpnId);
2326 // remove vpn-instance
2327 deleteVpnInstance(vpnId);
2328 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2331 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2332 return vpnInstance != null && vpnInstance.isL2vpn();
2335 // TODO Clean up the exception handling
2336 @SuppressWarnings("checkstyle:IllegalCatch")
2337 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2338 updateVpnMaps(vpnId, null, routerId, null, null);
2339 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2340 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2341 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2342 for (Subnetmap sn : subMapList) {
2343 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2344 if (!ipVersion.isIpVersionChosen(ipVers)) {
2345 ipVersion = ipVersion.addVersion(ipVers);
2348 if (ipVersion != IpVersionChoice.UNDEFINED) {
2349 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2351 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2353 for (Subnetmap sn : subMapList) {
2354 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2358 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2359 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2360 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2361 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2362 for (Uuid subnet : routerSubnets) {
2363 IpVersionChoice version = NeutronvpnUtils
2364 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2365 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2366 addSubnetToVpn(vpnId, subnet, null);
2368 addSubnetToVpn(vpnId, subnet, internetVpnId);
2373 // TODO Clean up the exception handling
2374 @SuppressWarnings("checkstyle:IllegalCatch")
2375 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2377 clearFromVpnMaps(vpnId, routerId, null);
2378 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2379 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2380 for (Subnetmap sn : subMapList) {
2381 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2382 if (ipVersion.isIpVersionChosen(ipVers)) {
2383 ipVersion = ipVersion.addVersion(ipVers);
2385 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2386 routerId.getValue());
2387 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2389 if (ipVersion != IpVersionChoice.UNDEFINED) {
2390 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2392 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2398 * Parses and associates networks list with given VPN.
2400 * @param vpnId Uuid of given VPN.
2401 * @param networkList List list of network Ids (Uuid), which will be associated.
2402 * @return list of formatted strings with detailed error messages.
2405 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2406 List<String> failedNwList = new ArrayList<>();
2407 HashSet<Uuid> passedNwList = new HashSet<>();
2408 boolean isExternalNetwork = false;
2409 if (networkList.isEmpty()) {
2410 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2411 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2413 return failedNwList;
2415 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2416 if (vpnInstance == null) {
2417 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2418 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2419 + "in ConfigDS", vpnId.getValue()));
2420 return failedNwList;
2423 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2424 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2426 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2427 + "associated with", vpnId.getValue()));
2428 return failedNwList;
2430 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2431 for (Uuid nw : networkList) {
2432 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2433 if (network == null) {
2434 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2435 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2439 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2440 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2441 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2442 nw.getValue(), vpnId.getValue());
2443 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2444 nw.getValue(), vpnId.getValue()));
2447 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2448 if (networkVpnId != null) {
2449 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2450 nw.getValue(), networkVpnId.getValue());
2451 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2452 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2455 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2456 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2457 nw.getValue(), vpnId.getValue());
2458 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2459 nw.getValue(), vpnId.getValue()));
2462 if (NeutronvpnUtils.getIsExternal(network)) {
2463 isExternalNetwork = true;
2465 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2466 if (subnetmapList == null || subnetmapList.isEmpty()) {
2467 passedNwList.add(nw);
2470 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2473 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2474 for (Subnetmap subnetmap : subnetmapList) {
2475 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2476 if (!ipVersion.isIpVersionChosen(ipVers)) {
2477 ipVersion = ipVersion.addVersion(ipVers);
2480 if (ipVersion != IpVersionChoice.UNDEFINED) {
2481 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2482 + " for VPN {} ", ipVersion, vpnId);
2483 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2485 for (Subnetmap subnetmap : subnetmapList) {
2486 Uuid subnetId = subnetmap.getId();
2487 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2488 if (subnetVpnId != null) {
2489 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2490 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2491 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2492 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2495 if (!NeutronvpnUtils.getIsExternal(network)) {
2496 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2498 addSubnetToVpn(vpnId, subnetId, null);
2499 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2501 passedNwList.add(nw);
2504 passedNwList.add(nw);
2506 } catch (ExecutionException | InterruptedException e) {
2507 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2509 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2512 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2513 if (!isExternalNetwork) {
2514 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2516 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2517 return failedNwList;
2520 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2521 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2524 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2525 if (vpnOpDataEntry == null) {
2526 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2529 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2530 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2531 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2533 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2534 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2535 updateVpnMaps(vpnId, null, null, null, extNwList);
2536 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2537 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2538 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2540 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2543 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2544 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2547 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2548 updateVpnInternetForSubnet(sm, vpnId, true);
2550 if (!ipVersion.isIpVersionChosen(ipVers)) {
2551 ipVersion = ipVersion.addVersion(ipVers);
2554 if (ipVersion != IpVersionChoice.UNDEFINED) {
2555 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2556 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2557 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2563 * Parses and disassociates networks list from given VPN.
2565 * @param vpnId Uuid of given VPN.
2566 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2567 * @return list of formatted strings with detailed error messages.
2570 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2571 List<String> failedNwList = new ArrayList<>();
2572 HashSet<Uuid> passedNwList = new HashSet<>();
2573 if (networkList.isEmpty()) {
2574 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2575 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2577 return failedNwList;
2579 for (Uuid nw : networkList) {
2580 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2581 if (networkSubnets == null) {
2582 passedNwList.add(nw);
2585 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2586 if (network == null) {
2587 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2588 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2592 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2593 if (networkVpnId == null) {
2594 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2595 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2599 if (!vpnId.equals(networkVpnId)) {
2600 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2601 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2602 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2603 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2607 if (NeutronvpnUtils.getIsExternal(network)) {
2608 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2609 passedNwList.add(nw);
2611 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2612 nw.getValue(), vpnId.getValue());
2613 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2618 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2619 for (Uuid subnet : networkSubnets) {
2620 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2621 if (subnetmap == null) {
2622 failedNwList.add(String.format("subnetmap %s not found for network %s",
2623 subnet.getValue(), nw.getValue()));
2624 LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when "
2625 + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(),
2629 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2630 if (!ipVersion.isIpVersionChosen(ipVers)) {
2631 ipVersion = ipVersion.addVersion(ipVers);
2633 if (!NeutronvpnUtils.getIsExternal(network)) {
2634 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2636 removeSubnetFromVpn(vpnId, subnetmap, null);
2637 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2638 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2640 passedNwList.add(nw);
2643 if (ipVersion != IpVersionChoice.UNDEFINED) {
2644 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2645 + " for VPN {}", ipVersion, vpnId);
2646 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2649 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2650 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2651 passedNwList, vpnId.getValue());
2652 return failedNwList;
2655 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2656 if (!removeExternalNetworkFromVpn(extNet)) {
2659 // check, if there is another Provider Networks associated with given VPN
2660 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2661 if (vpnNets != null) {
2662 //Remove currently disassociated network from the list
2663 vpnNets.remove(extNet.getUuid());
2664 for (Uuid netId : vpnNets) {
2665 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2666 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2667 + "{}", vpnId.getValue(), netId.getValue());
2672 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2673 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2674 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2675 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2676 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2677 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2678 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2680 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2683 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2684 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2687 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2688 updateVpnInternetForSubnet(sm, vpnId, false);
2690 if (!ipVersion.isIpVersionChosen(ipVers)) {
2691 ipVersion = ipVersion.addVersion(ipVers);
2694 if (ipVersion != IpVersionChoice.UNDEFINED) {
2695 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2696 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2698 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2704 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2707 // TODO Clean up the exception handling
2708 @SuppressWarnings("checkstyle:IllegalCatch")
2709 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2711 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2712 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2713 StringBuilder returnMsg = new StringBuilder();
2714 Uuid vpnId = input.getVpnId();
2717 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2718 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2719 input.getNetworkId());
2720 List<Uuid> netIds = input.getNetworkId();
2721 if (netIds != null && !netIds.isEmpty()) {
2722 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2723 if (!failed.isEmpty()) {
2724 returnMsg.append(failed);
2728 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2730 if (returnMsg.length() != 0) {
2731 opBuilder.setResponse(
2732 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2733 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2734 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2736 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2738 } catch (Exception ex) {
2739 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2740 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2741 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2742 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2744 LOG.debug("associateNetworks returns..");
2749 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2752 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2754 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2755 LOG.debug("associateRouter {}", input);
2756 StringBuilder returnMsg = new StringBuilder();
2757 Uuid vpnId = input.getVpnId();
2758 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter
2759 .input.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2760 .associaterouter.input.RouterIds> keyRouterIdsMap = input.getRouterIds();
2761 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "associateRouter: RouterIds list is empty!");
2762 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2763 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2764 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2765 .RouterIds routerId : keyRouterIdsMap.values()) {
2766 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2767 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2768 if (vpnMap != null) {
2770 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2771 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2772 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2773 .append(routerId.getRouterId());
2774 } else if (extVpnId != null) {
2775 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2776 + "another VPN ").append(extVpnId.getValue());
2778 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2779 routerId.getRouterId());
2780 associateRouterToVpn(vpnId, routerId.getRouterId());
2783 returnMsg.append("router not found : ").append(routerId.getRouterId());
2786 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2788 if (returnMsg.length() != 0) {
2789 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2790 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2791 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2793 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2796 LOG.debug("associateRouter returns..");
2801 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2804 // TODO Clean up the exception handling
2805 @SuppressWarnings("checkstyle:IllegalCatch")
2806 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2807 GetFixedIPsForNeutronPortInput input) {
2808 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2809 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2810 Uuid portId = input.getPortId();
2811 StringBuilder returnMsg = new StringBuilder();
2813 List<String> fixedIPList = new ArrayList<>();
2814 Port port = neutronvpnUtils.getNeutronPort(portId);
2816 for (FixedIps ip : port.nonnullFixedIps().values()) {
2817 fixedIPList.add(ip.getIpAddress().stringValue());
2820 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2822 if (returnMsg.length() != 0) {
2823 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2825 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2826 returnMsg)).build());
2828 opBuilder.setFixedIPs(fixedIPList);
2829 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2831 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2833 } catch (Exception ex) {
2834 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2835 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2836 portId.getValue(), ex.getMessage(), ex)).build());
2842 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2845 // TODO Clean up the exception handling
2846 @SuppressWarnings("checkstyle:IllegalCatch")
2847 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2849 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2850 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2852 LOG.debug("dissociateNetworks {}", input);
2853 StringBuilder returnMsg = new StringBuilder();
2854 Uuid vpnId = input.getVpnId();
2857 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2858 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2859 input.getNetworkId());
2860 List<Uuid> netIds = input.getNetworkId();
2861 if (netIds != null && !netIds.isEmpty()) {
2862 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2863 if (!failed.isEmpty()) {
2864 returnMsg.append(failed);
2868 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2870 if (returnMsg.length() != 0) {
2871 opBuilder.setResponse(
2872 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2873 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2875 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2877 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2879 } catch (Exception ex) {
2880 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2881 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2882 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2884 LOG.debug("dissociateNetworks returns..");
2889 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2892 // TODO Clean up the exception handling
2893 @SuppressWarnings("checkstyle:IllegalCatch")
2894 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2896 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2898 LOG.debug("dissociateRouter {}", input);
2899 StringBuilder returnMsg = new StringBuilder();
2900 Uuid vpnId = input.getVpnId();
2901 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2902 .RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2903 .dissociaterouter.input.RouterIds> keyRouterIdsMap = input.getRouterIds();
2904 String routerIdsString = "";
2905 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2906 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2907 Preconditions.checkNotNull(keyRouterIdsMap, "dissociateRouter: keyRouterIdsMap not found!");
2908 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2909 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2910 .RouterIds routerId : keyRouterIdsMap.values()) {
2912 if (routerId != null) {
2913 routerIdsString += routerId.getRouterId() + ", ";
2914 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2916 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2917 if (routerVpnId == null) {
2918 returnMsg.append("input router ").append(routerId.getRouterId())
2919 .append(" not associated to any vpn yet");
2920 } else if (vpnId.equals(routerVpnId)) {
2921 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2923 returnMsg.append("input router ").append(routerId.getRouterId())
2924 .append(" associated to vpn ")
2925 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2928 returnMsg.append("router not found : ").append(routerId.getRouterId());
2931 if (returnMsg.length() != 0) {
2932 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2933 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2934 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2935 returnMsg)).build());
2937 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2939 } catch (Exception ex) {
2940 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2941 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2942 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2946 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2949 LOG.debug("dissociateRouter returns..");
2953 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2954 // check if the router is associated to some VPN
2955 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2956 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2957 if (vpnId != null) {
2958 // remove existing external vpn interfaces
2959 for (Uuid subnetId : routerSubnetIds) {
2960 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
2961 if (subnetmap != null) {
2962 removeSubnetFromVpn(vpnId, subnetmap, internetVpnId);
2964 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
2965 subnetId, routerId.getValue());
2968 clearFromVpnMaps(vpnId, routerId, null);
2970 // remove existing internal vpn interfaces
2971 for (Uuid subnetId : routerSubnetIds) {
2972 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
2973 if (subnetmap != null) {
2974 removeSubnetFromVpn(routerId, subnetmap, internetVpnId);
2976 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
2977 subnetId, routerId.getValue());
2981 // delete entire vpnMaps node for internal VPN
2982 deleteVpnMapsNode(routerId);
2984 // delete vpn-instance for internal VPN
2985 deleteVpnInstance(routerId);
2988 protected Subnet getNeutronSubnet(Uuid subnetId) {
2989 return neutronvpnUtils.getNeutronSubnet(subnetId);
2993 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2994 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2996 return sn.getGatewayIp();
3002 protected Network getNeutronNetwork(Uuid networkId) {
3003 return neutronvpnUtils.getNeutronNetwork(networkId);
3006 protected Port getNeutronPort(String name) {
3007 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3010 protected Port getNeutronPort(Uuid portId) {
3011 return neutronvpnUtils.getNeutronPort(portId);
3014 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3015 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3018 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3019 return neutronvpnUtils.getNetworksForVpn(vpnId);
3023 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3025 * @return a List of String to be printed on screen
3026 * @throws ExecutionException or InterruptedException if there was a problem reading from the data store
3028 public List<String> showNeutronPortsCLI() throws ExecutionException, InterruptedException {
3029 List<String> result = new ArrayList<>();
3030 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3032 result.add("-------------------------------------------------------------------------------------------");
3033 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3035 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3036 if (ports.isPresent() && ports.get().getPort() != null) {
3037 for (Port port : ports.get().nonnullPort().values()) {
3038 Map<FixedIpsKey, FixedIps> keyFixedIpsMap = port.getFixedIps();
3039 if (keyFixedIpsMap != null && !keyFixedIpsMap.isEmpty()) {
3040 List<String> ipList = new ArrayList<>();
3041 for (FixedIps fixedIp : keyFixedIpsMap.values()) {
3042 IpAddress ipAddress = fixedIp.getIpAddress();
3043 if (ipAddress.getIpv4Address() != null) {
3044 ipList.add(ipAddress.getIpv4Address().getValue());
3046 ipList.add(ipAddress.getIpv6Address().getValue());
3049 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3050 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3051 ipList.toString()));
3053 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3054 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3063 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3065 * @param vpnuuid Uuid of the VPN whose config must be shown
3066 * @return formatted output list
3067 * @throws InterruptedException if there was a thread related problem getting the data to display
3068 * @throws ExecutionException if there was any other problem getting the data to display
3070 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3071 List<String> result = new ArrayList<>();
3072 if (vpnuuid == null) {
3074 result.add("Displaying VPN config for all VPNs");
3075 result.add("To display VPN config for a particular VPN, use the following syntax");
3076 result.add(getshowVpnConfigCLIHelp());
3078 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3079 if (rpcResult.isSuccessful()) {
3081 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3083 result.add(String.format(" %-80s ", "Import-RTs"));
3085 result.add(String.format(" %-80s ", "Export-RTs"));
3087 result.add(String.format(" %-76s ", "Subnet IDs"));
3089 result.add("------------------------------------------------------------------------------------");
3091 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3092 rpcResult.getResult().nonnullL3vpnInstances()) {
3093 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3095 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3096 vpn.getRouteDistinguisher()));
3098 result.add(String.format(" %-80s ", vpn.getImportRT()));
3100 result.add(String.format(" %-80s ", vpn.getExportRT()));
3103 Uuid vpnid = vpn.getId();
3104 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3105 if (!subnetList.isEmpty()) {
3106 for (Uuid subnetuuid : subnetList) {
3107 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3110 result.add(String.format(" %-76s ", "\" \""));
3113 result.add("----------------------------------------");
3117 String errortag = rpcResult.getErrors().iterator().next().getTag();
3118 if (Objects.equals(errortag, "")) {
3120 result.add("No VPN has been configured yet");
3121 } else if (Objects.equals(errortag, "invalid-value")) {
3123 result.add("VPN " + vpnuuid.getValue() + " is not present");
3125 result.add("error getting VPN info : " + rpcResult.getErrors());
3126 result.add(getshowVpnConfigCLIHelp());
3132 protected void createExternalVpnInterfaces(Uuid extNetId) {
3133 if (extNetId == null) {
3134 LOG.error("createExternalVpnInterfaces: external network is null");
3138 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3139 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3140 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3144 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3145 for (String elanInterface : extElanInterfaces) {
3146 createExternalVpnInterface(extNetId, elanInterface, tx);
3148 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3151 // TODO Clean up the exception handling
3152 @SuppressWarnings("checkstyle:IllegalCatch")
3153 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3154 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3155 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3156 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3159 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3160 for (String elanInterface : extElanInterfaces) {
3161 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3162 .buildVpnInterfaceIdentifier(elanInterface);
3163 LOG.info("Removing vpn interface {}", elanInterface);
3164 tx.delete(vpnIfIdentifier);
3166 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3169 private void createExternalVpnInterface(Uuid vpnId, String infName,
3170 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3171 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3172 false /* not a router iface */, wrtConfigTxn);
3175 // TODO Clean up the exception handling
3176 @SuppressWarnings("checkstyle:IllegalCatch")
3177 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3178 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3179 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3180 if (vpnIdList.isEmpty() || infName == null) {
3181 LOG.error("vpnid is empty or interface({}) is null", infName);
3184 if (wrtConfigTxn == null) {
3185 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3186 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3187 "Error writing VPN interface");
3190 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3191 for (Uuid vpnId: vpnIdList) {
3192 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3193 AssociatedSubnetType.V4AndV6Subnets);
3194 vpnIdListStruct.add(vpnInstance);
3197 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3198 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3200 .setVpnInstanceNames(vpnIdListStruct)
3201 .setRouterInterface(isRouterInterface);
3202 LOG.info("Network Id is {}", networkUuid);
3203 if (networkUuid != null) {
3204 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3205 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3206 NetworkAttributes.NetworkType networkType = providerType != null
3207 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3208 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3209 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3210 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3213 if (adjacencies != null) {
3214 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3216 VpnInterface vpnIf = vpnb.build();
3218 LOG.info("Creating vpn interface {}", vpnIf);
3219 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3220 } catch (Exception ex) {
3221 LOG.error("Creation of vpninterface {} failed", infName, ex);
3225 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3226 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3227 if (vpnId == null || infName == null) {
3228 LOG.error("vpn id or interface is null");
3231 if (wrtConfigTxn == null) {
3232 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3233 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3234 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3235 }), LOG, "Error updating VPN interface with adjacencies");
3239 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3241 try (AcquireResult lock = tryInterfaceLock(infName)) {
3242 if (!lock.wasAcquired()) {
3243 // FIXME: why do we even bother with locking if we do not honor it?!
3244 logTryLockFailure(infName);
3248 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3249 .syncReadOptional(dataBroker, LogicalDatastoreType
3250 .CONFIGURATION, vpnIfIdentifier);
3251 if (optionalVpnInterface.isPresent()) {
3252 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3253 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3255 if (adjacencies == null) {
3258 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3259 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3260 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3261 optionalVpnInterface.get().getVpnInstanceNames().values());
3262 if (listVpnInstances.isEmpty()
3263 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3264 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3265 AssociatedSubnetType.V4AndV6Subnets);
3266 listVpnInstances.add(vpnInstance);
3267 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3270 VpnInstanceNames vpnInstance = VpnHelper
3271 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3272 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3273 listVpnInstances.add(vpnInstance);
3274 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3276 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3277 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3279 } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
3280 // FIXME: why are we catching IllegalStateException here?
3281 LOG.error("Update of vpninterface {} failed", infName, ex);
3286 private String getshowVpnConfigCLIHelp() {
3287 StringBuilder help = new StringBuilder("Usage:");
3288 help.append("display vpn-config [-vid/--vpnid <id>]");
3289 return help.toString();
3292 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3293 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3297 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3298 return neutronEvpnManager.createEVPN(input);
3302 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3303 return neutronEvpnManager.getEVPN(input);
3307 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3308 return neutronEvpnManager.deleteEVPN(input);
3311 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3312 Uuid extNetId = extNet.getUuid();
3313 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3314 .child(Networks.class, new NetworksKey(extNetId)).build();
3317 Optional<Networks> optionalExtNets =
3318 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3320 if (!optionalExtNets.isPresent()) {
3321 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3322 extNetId.getValue());
3325 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3326 builder.setVpnid(vpnId);
3327 Networks networks = builder.build();
3328 // Add Networks object to the ExternalNetworks list
3329 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3330 extNetId.getValue());
3331 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3334 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3335 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3336 extNetId.getValue(), ex);
3341 private boolean removeExternalNetworkFromVpn(Network extNet) {
3342 Uuid extNetId = extNet.getUuid();
3343 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3344 .child(Networks.class, new NetworksKey(extNetId)).build();
3346 Optional<Networks> optionalNets =
3347 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3349 NetworksBuilder builder = null;
3350 if (optionalNets.isPresent()) {
3351 builder = new NetworksBuilder(optionalNets.get());
3353 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3354 extNetId.getValue());
3357 builder.setVpnid(null);
3358 Networks networks = builder.build();
3359 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3360 extNetId.getValue());
3361 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3363 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3364 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3365 extNetId.getValue(), ex);
3370 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3371 Optional<String> existingVpnName = Optional.of(primaryRd);
3372 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3374 vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3375 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3376 } catch (ExecutionException | InterruptedException e) {
3377 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3379 /*Read failed. We don't know if a VPN exists or not.
3380 * Return primaryRd to halt caller execution, to be safe.*/
3381 return existingVpnName;
3383 if (vpnInstanceOpDataOptional.isPresent()) {
3384 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3386 existingVpnName = Optional.empty();
3388 return existingVpnName;
3391 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3392 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3395 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3396 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3399 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3400 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3403 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3404 String message = tuple.getMessage();
3405 logger.accept(message);
3409 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3410 @NonNull Subnetmap subnetMap) {
3411 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3412 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3413 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3414 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3415 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3416 subnetMap.getId().getValue(), internetVpnId.getValue());
3420 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3421 @NonNull Subnetmap subnetMap) {
3422 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3423 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3426 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3427 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3428 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3429 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3430 internetVpnId.getValue(), routerId.getValue());
3431 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3437 private AcquireResult tryInterfaceLock(final String infName) {
3438 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3442 private AcquireResult tryVpnLock(final Uuid vpnId) {
3443 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3446 private static ReentrantLock lockForUuid(Uuid uuid) {
3447 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3448 return JvmGlobalLocks.getLockForString(uuid.getValue());
3451 private static void logTryLockFailure(Object objectId) {
3452 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());