2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.JdkFutureAdapters;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture;
22 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.Map.Entry;
33 import java.util.Objects;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.locks.ReentrantLock;
40 import java.util.function.Consumer;
41 import javax.annotation.PreDestroy;
42 import javax.inject.Inject;
43 import javax.inject.Singleton;
44 import org.eclipse.jdt.annotation.NonNull;
45 import org.eclipse.jdt.annotation.Nullable;
46 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
50 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
51 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
52 import org.opendaylight.genius.infra.Datastore.Configuration;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
55 import org.opendaylight.genius.infra.TypedWriteTransaction;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.genius.utils.JvmGlobalLocks;
58 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
59 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
60 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
61 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
62 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
63 import org.opendaylight.netvirt.elanmanager.api.IElanService;
64 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
65 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
66 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
67 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
68 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
69 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
70 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
178 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
179 import org.opendaylight.yangtools.yang.common.RpcError;
180 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
181 import org.opendaylight.yangtools.yang.common.RpcResult;
182 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
183 import org.slf4j.Logger;
184 import org.slf4j.LoggerFactory;
185 import org.slf4j.helpers.FormattingTuple;
186 import org.slf4j.helpers.MessageFormatter;
189 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
191 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
192 private static final long LOCK_WAIT_TIME = 10L;
194 private final DataBroker dataBroker;
195 private final ManagedNewTransactionRunner txRunner;
196 private final VpnRpcService vpnRpcService;
197 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
198 private final IElanService elanService;
199 private final NeutronvpnConfig neutronvpnConfig;
200 private final NeutronEvpnManager neutronEvpnManager;
201 private final NeutronEvpnUtils neutronEvpnUtils;
202 private final JobCoordinator jobCoordinator;
203 private final NeutronvpnUtils neutronvpnUtils;
204 private final IVpnManager vpnManager;
205 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
206 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
207 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
208 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
211 public NeutronvpnManager(
212 final DataBroker dataBroker,
213 final VpnRpcService vpnRpcSrv, final IElanService elanService,
214 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
215 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
216 final JobCoordinator jobCoordinator,
217 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
218 this.dataBroker = dataBroker;
219 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
220 vpnRpcService = vpnRpcSrv;
221 this.elanService = elanService;
222 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
223 this.neutronvpnConfig = neutronvpnConfig;
224 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
225 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
226 this.jobCoordinator = jobCoordinator;
227 this.neutronvpnUtils = neutronvpnUtils;
228 this.vpnManager = vpnManager;
235 public void close() {
236 LOG.info("{} close", getClass().getSimpleName());
239 private void configureFeatures() throws TransactionCommitFailedException {
240 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
241 Neutron.class).child(Features.class).child(
242 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
243 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
245 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
246 } catch (OptimisticLockFailedException e) {
247 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
249 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
250 Neutron.class).child(Features.class).child(
251 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
252 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
254 SingleTransactionDataBroker.syncWrite(
255 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
256 } catch (OptimisticLockFailedException e) {
257 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
261 public String getOpenDaylightVniRangesConfig() {
262 return neutronvpnConfig.getOpendaylightVniRanges();
265 // TODO Clean up the exception handling
266 @SuppressWarnings("checkstyle:IllegalCatch")
267 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
268 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
269 boolean isExternalNw) {
271 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
272 final ReentrantLock lock = lockForUuid(subnetId);
275 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
276 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
277 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
278 if (sn.isPresent()) {
279 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
280 subnetId.getValue());
283 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
284 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
285 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
286 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
287 subnetId.getValue());
288 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
289 subnetMapIdentifier, subnetmapBuilder.build());
293 } catch (TransactionCommitFailedException | ReadFailedException e) {
294 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
296 // check if there are ports to update for already created Subnetmap node
297 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
298 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
299 if (entry.getValue().getValue().equals(subnetId.getValue())) {
300 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
301 unprocessedPortsMap.remove(entry.getKey());
307 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
308 @Nullable Uuid internetvpnId) {
309 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
310 .child(Subnetmap.class, new SubnetmapKey(subnetId))
312 final ReentrantLock lock = lockForUuid(subnetId);
315 Optional<Subnetmap> sn =
316 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
317 if (!sn.isPresent()) {
318 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
321 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
322 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
323 if (routerId != null) {
324 builder.setRouterId(routerId);
327 builder.setVpnId(vpnId);
329 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
330 builder.setInternetVpnId(internetvpnId);
332 Subnetmap subnetmap = builder.build();
333 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
334 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
336 } catch (ReadFailedException | TransactionCommitFailedException e) {
337 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
344 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
345 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
346 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
347 InstanceIdentifier<Subnetmap> id =
348 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
349 final ReentrantLock lock = lockForUuid(subnetId);
352 Optional<Subnetmap> sn =
353 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
354 if (!sn.isPresent()) {
355 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
356 subnetId.getValue());
359 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
360 subnetId.getValue());
361 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
362 builder.setRouterId(routerId);
363 builder.setRouterInterfacePortId(routerInterfacePortId);
364 builder.setRouterIntfMacAddress(routerIntfMacAddress);
365 builder.setRouterInterfaceFixedIp(fixedIp);
367 builder.setVpnId(vpnId);
369 Subnetmap subnetmap = builder.build();
370 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
371 subnetId.getValue());
372 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
373 } catch (ReadFailedException | TransactionCommitFailedException e) {
374 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
375 subnetId.getValue(), e);
381 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
382 @Nullable Uuid directPortId) {
383 Subnetmap subnetmap = null;
384 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
385 new SubnetmapKey(subnetId)).build();
386 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
387 final ReentrantLock lock = lockForUuid(subnetId);
390 Optional<Subnetmap> sn =
391 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
393 if (sn.isPresent()) {
394 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
395 if (null != portId) {
396 List<Uuid> existingPortList = builder.getPortList();
397 List<Uuid> portList = new ArrayList<>();
398 if (null != existingPortList) {
399 portList.addAll(existingPortList);
401 portList.add(portId);
402 builder.setPortList(portList);
403 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
404 subnetId.getValue(), portId.getValue());
406 if (null != directPortId) {
407 List<Uuid> existingDirectPortList = builder.getDirectPortList();
408 List<Uuid> directPortList = new ArrayList<>();
409 if (null != existingDirectPortList) {
410 directPortList.addAll(existingDirectPortList);
412 directPortList.add(directPortId);
413 builder.setDirectPortList(directPortList);
414 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
415 directPortId.getValue());
417 subnetmap = builder.build();
418 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
421 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
422 + "cache ", subnetId.getValue(), portId.getValue());
423 unprocessedPortsMap.put(portId, subnetId);
425 } catch (ReadFailedException | TransactionCommitFailedException e) {
426 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
433 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
434 Uuid vpnId, @Nullable Uuid portId) {
435 Subnetmap subnetmap = null;
436 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
437 .child(Subnetmap.class, new SubnetmapKey(subnetId))
439 final ReentrantLock lock = lockForUuid(subnetId);
442 Optional<Subnetmap> sn =
443 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
445 if (sn.isPresent()) {
446 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
447 if (routerId != null) {
448 builder.setRouterId(null);
450 if (networkId != null) {
451 builder.setNetworkId(null);
454 builder.setVpnId(null);
456 builder.setInternetVpnId(null);
457 if (portId != null && builder.getPortList() != null) {
458 List<Uuid> portList = new ArrayList<>(builder.getPortList());
459 portList.remove(portId);
460 builder.setPortList(portList);
463 subnetmap = builder.build();
464 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
465 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
468 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
470 } catch (ReadFailedException | TransactionCommitFailedException e) {
471 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
479 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
480 @Nullable Uuid directPortId) {
481 Subnetmap subnetmap = null;
482 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
483 new SubnetmapKey(subnetId)).build();
484 final ReentrantLock lock = lockForUuid(subnetId);
487 Optional<Subnetmap> sn =
488 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
490 if (sn.isPresent()) {
491 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
492 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
493 List<Uuid> portList = new ArrayList<>(builder.getPortList());
494 portList.remove(portId);
495 builder.setPortList(portList);
496 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
497 subnetId.getValue());
499 if (null != directPortId && null != builder.getDirectPortList()
500 && !builder.getDirectPortList().isEmpty()) {
501 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
502 directPortList.remove(directPortId);
503 builder.setDirectPortList(directPortList);
504 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
505 .getValue(), subnetId.getValue());
507 subnetmap = builder.build();
508 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
511 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
513 } catch (ReadFailedException | TransactionCommitFailedException e) {
514 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
515 subnetId.getValue(), e);
522 // TODO Clean up the exception handling
523 @SuppressWarnings("checkstyle:IllegalCatch")
524 protected void deleteSubnetMapNode(Uuid subnetId) {
525 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
526 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
527 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
528 final ReentrantLock lock = lockForUuid(subnetId);
531 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
532 } catch (TransactionCommitFailedException e) {
533 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
539 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
540 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
541 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
543 Optional<VpnInstance> vpnInstanceConfig =
544 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
546 if (!vpnInstanceConfig.isPresent()) {
547 LOG.debug("updateVpnInstanceWithRDs: "
548 + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
551 VpnInstance vpnInstance = vpnInstanceConfig.get();
552 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
553 updateVpnInstanceBuilder.setRouteDistinguisher(rds);
554 LOG.debug("updateVpnInstanceWithRDs: "
555 + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
556 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
557 updateVpnInstanceBuilder.build());
558 } catch (ReadFailedException | TransactionCommitFailedException ex) {
559 LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
560 + "the list of RDs: {}", vpnInstanceId, rds, ex);
564 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
565 boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
566 String vpnName = vpnId.getValue();
567 VpnInstanceBuilder builder = null;
568 List<VpnTarget> vpnTargetList = new ArrayList<>();
569 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
570 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
571 Optional<VpnInstance> optionalVpn;
573 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
575 } catch (ReadFailedException e) {
576 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
580 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
581 if (optionalVpn.isPresent()) {
582 builder = new VpnInstanceBuilder(optionalVpn.get());
583 LOG.debug("updating existing vpninstance node");
585 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
586 .setL2vpn(isL2Vpn).setL3vni(l3vni);
588 if (irt != null && !irt.isEmpty()) {
589 if (ert != null && !ert.isEmpty()) {
590 List<String> commonRT = new ArrayList<>(irt);
591 commonRT.retainAll(ert);
593 for (String common : commonRT) {
596 VpnTarget vpnTarget =
597 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
598 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
599 vpnTargetList.add(vpnTarget);
602 for (String importRT : irt) {
603 VpnTarget vpnTarget =
604 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
605 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
606 vpnTargetList.add(vpnTarget);
610 if (ert != null && !ert.isEmpty()) {
611 for (String exportRT : ert) {
612 VpnTarget vpnTarget =
613 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
614 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
615 vpnTargetList.add(vpnTarget);
619 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
620 if (rd != null && !rd.isEmpty()) {
621 builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets);
624 builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
625 VpnInstance newVpn = builder.build();
626 try (AcquireResult lock = tryVpnLock(vpnId)) {
627 if (!lock.wasAcquired()) {
628 // FIXME: why do we even bother with locking if we do not honor it?!
629 logTryLockFailure(vpnId);
632 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
634 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
636 } catch (TransactionCommitFailedException e) {
637 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
642 private void deleteVpnMapsNode(Uuid vpnId) {
643 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
644 .child(VpnMap.class, new VpnMapKey(vpnId))
646 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
647 try (AcquireResult lock = tryVpnLock(vpnId)) {
648 if (!lock.wasAcquired()) {
649 // FIXME: why do we even bother with locking if we do not honor it?!
650 logTryLockFailure(vpnId);
654 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
656 } catch (TransactionCommitFailedException e) {
657 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
662 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
663 @Nullable List<Uuid> networks) {
664 VpnMapBuilder builder;
665 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
666 .child(VpnMap.class, new VpnMapKey(vpnId))
669 Optional<VpnMap> optionalVpnMap =
670 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
672 if (optionalVpnMap.isPresent()) {
673 builder = new VpnMapBuilder(optionalVpnMap.get());
675 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
679 builder.setName(name);
681 if (tenantId != null) {
682 builder.setTenantId(tenantId);
684 if (router != null) {
685 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
686 List<RouterIds> rtrIds = builder.getRouterIds() != null
687 ? new ArrayList<>(builder.getRouterIds()) : null;
688 if (rtrIds == null) {
689 rtrIds = Collections.singletonList(vpnRouterId);
691 rtrIds.add(vpnRouterId);
693 builder.setRouterIds(rtrIds);
695 if (networks != null) {
696 List<Uuid> nwList = builder.getNetworkIds() != null
697 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
698 nwList.addAll(networks);
699 builder.setNetworkIds(nwList);
702 try (AcquireResult lock = tryVpnLock(vpnId)) {
703 if (!lock.wasAcquired()) {
704 // FIXME: why do we even bother with locking if we do not honor it?!
705 logTryLockFailure(vpnId);
708 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
709 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
711 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
713 } catch (ReadFailedException | TransactionCommitFailedException e) {
714 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
718 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
719 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
720 .child(VpnMap.class, new VpnMapKey(vpnId))
722 Optional<VpnMap> optionalVpnMap;
725 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
727 } catch (ReadFailedException e) {
728 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
731 if (optionalVpnMap.isPresent()) {
732 VpnMap vpnMap = optionalVpnMap.get();
733 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
734 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds());
735 if (rtrIds == null) {
736 rtrIds = new ArrayList<>();
738 if (routerId != null) {
739 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
740 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
741 vpnMapBuilder.setRouterIds(rtrIds);
743 try (AcquireResult lock = tryVpnLock(vpnId)) {
744 if (!lock.wasAcquired()) {
745 // FIXME: why do we even bother with locking if we do not honor it?!
746 logTryLockFailure(vpnId);
749 LOG.debug("removing vpnMaps node: {} ", vpnId);
751 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
753 } catch (TransactionCommitFailedException e) {
754 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
758 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
759 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
760 vpnMapBuilder.setRouterIds(rtrIds);
761 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
764 if (networkIds != null) {
765 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
766 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
767 vpnNw.removeAll(networkIds);
768 if (vpnNw.isEmpty()) {
769 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
770 vpnMapBuilder.setNetworkIds(null);
772 vpnMapBuilder.setNetworkIds(vpnNw);
776 try (AcquireResult lock = tryVpnLock(vpnId)) {
777 if (!lock.wasAcquired()) {
778 // FIXME: why do we even bother with locking if we do not honor it?!
779 logTryLockFailure(vpnId);
782 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
784 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
785 vpnMapIdentifier, vpnMapBuilder.build());
786 } catch (TransactionCommitFailedException e) {
787 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
791 LOG.error("VPN : {} not found", vpnId.getValue());
793 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
796 private void deleteVpnInstance(Uuid vpnId) {
797 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
798 .child(VpnInstance.class,
799 new VpnInstanceKey(vpnId.getValue()))
802 try (AcquireResult lock = tryVpnLock(vpnId)) {
803 if (!lock.wasAcquired()) {
804 // FIXME: why do we even bother with locking if we do not honor it?!
805 logTryLockFailure(vpnId);
808 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
810 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
811 } catch (TransactionCommitFailedException e) {
812 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
817 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
818 TypedWriteTransaction<Configuration> wrtConfigTxn,
819 @Nullable VpnInterface vpnIface) {
820 List<Adjacency> adjList = new ArrayList<>();
821 if (vpnIface != null) {
822 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
824 String infName = port.getUuid().getValue();
825 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
826 for (FixedIps ip : port.nonnullFixedIps()) {
827 String ipValue = ip.getIpAddress().stringValue();
828 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
829 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
830 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
831 snTemp.getSubnetIp(), false)) {
834 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
836 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
837 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
838 //Create Neutron port adjacency if VPN presence is existing for subnet
839 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
840 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
841 .setSubnetId(ip.getSubnetId()).build();
842 if (!adjList.contains(vmAdj)) {
846 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
847 if (snTemp != null && snTemp.getInternetVpnId() != null) {
848 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
849 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
851 if (routerId != null) {
852 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
853 if (rtr != null && rtr.getRoutes() != null) {
854 List<Routes> routeList = rtr.getRoutes();
855 // create extraroute Adjacence for each ipValue,
856 // because router can have IPv4 and IPv6 subnet ports, or can have
857 // more that one IPv4 subnet port or more than one IPv6 subnet port
858 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
859 if (!erAdjList.isEmpty()) {
860 adjList.addAll(erAdjList);
865 return new AdjacenciesBuilder().setAdjacency(adjList).build();
868 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
869 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
870 boolean isRouterInterface = false;
871 if (port.getDeviceOwner() != null) {
872 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
874 String infName = port.getUuid().getValue();
875 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
876 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
877 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
878 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
879 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
882 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
883 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
884 String infName = port.getUuid().getValue();
885 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
886 Optional<VpnInterface> optionalVpnInterface = null;
887 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
888 vpnId, internetVpnId, infName);
890 optionalVpnInterface = SingleTransactionDataBroker
891 .syncReadOptional(dataBroker, LogicalDatastoreType
892 .CONFIGURATION, vpnIfIdentifier);
893 } catch (ReadFailedException e) {
894 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
897 if (!optionalVpnInterface.isPresent()) {
900 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
901 sn != null ? sn.getSubnetIp() : "null");
902 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
903 List<Adjacency> updatedAdjsList = new ArrayList<>();
904 boolean isIpFromAnotherSubnet = false;
905 for (Adjacency adj : vpnAdjsList) {
906 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
907 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
908 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
909 isIpFromAnotherSubnet = true;
911 updatedAdjsList.add(adj);
914 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
915 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
918 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
919 String.valueOf(adjString), wrtConfigTxn);
921 if (internetVpnId != null) {
922 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
923 String.valueOf(adjString), wrtConfigTxn);
926 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
927 && sn.getRouterId() != null) {
928 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
929 if (rtr != null && rtr.getRoutes() != null) {
930 List<Routes> extraRoutesToRemove = new ArrayList<>();
931 for (Routes rt: rtr.getRoutes()) {
932 if (rt.getNexthop().toString().equals(adjString)) {
933 extraRoutesToRemove.add(rt);
937 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
938 extraRoutesToRemove, vpnId);
939 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
941 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
946 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
948 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
950 if (!isIpFromAnotherSubnet) {
951 // no more subnetworks for neutron port
952 if (sn != null && sn.getRouterId() != null) {
953 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
955 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
961 // TODO Clean up the exception handling
962 @SuppressWarnings("checkstyle:IllegalCatch")
963 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
964 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
965 if (wrtConfigTxn == null) {
966 ListenableFutures.addErrorLogging(
967 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
968 tx -> deleteVpnInterface(infName, vpnId, tx)),
969 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
973 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
974 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
975 Optional<VpnInterface> optionalVpnInterface;
977 optionalVpnInterface =
978 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
980 } catch (ReadFailedException ex) {
981 LOG.error("Error during deletion of vpninterface {}", infName, ex);
984 if (!optionalVpnInterface.isPresent()) {
985 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
989 VpnInterface vpnInterface = optionalVpnInterface.get();
990 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
992 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
993 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
994 if (!vpnList.isEmpty()) {
995 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
996 + "List not empty", infName);
999 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1000 .setVpnInstanceNames(vpnList);
1001 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1005 LOG.debug("Deleting vpn interface {}", infName);
1006 wrtConfigTxn.delete(vpnIfIdentifier);
1009 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1010 TypedWriteTransaction<Configuration> writeConfigTxn,
1012 if (vpnId == null || port == null) {
1015 String infName = port.getUuid().getValue();
1016 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1018 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1019 .syncReadOptional(dataBroker, LogicalDatastoreType
1020 .CONFIGURATION, vpnIfIdentifier);
1021 if (optionalVpnInterface.isPresent()) {
1022 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1024 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1025 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1027 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1028 .setVpnInstanceNames(listVpn);
1029 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1030 LOG.debug("Updating vpn interface {}", infName);
1031 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1032 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1033 while (adjacencyIter.hasNext()) {
1034 Adjacency adjacency = adjacencyIter.next();
1035 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1038 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1039 InstanceIdentifier<LearntVpnVipToPort> id =
1040 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1041 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1042 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1043 LogicalDatastoreType.OPERATIONAL, id);
1044 if (optionalVpnVipToPort.isPresent()) {
1045 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1047 if (listVpn == null || listVpn.isEmpty()) {
1048 adjacencyIter.remove();
1050 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1051 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1052 mipToQuery, infName, vpnId.getValue());
1055 for (FixedIps ip : port.nonnullFixedIps()) {
1056 String ipValue = ip.getIpAddress().stringValue();
1058 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1061 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1062 ipValue, writeConfigTxn);
1064 if (listVpn == null || listVpn.isEmpty()) {
1065 if (sm != null && sm.getRouterId() != null) {
1066 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1068 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1070 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1073 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1075 } catch (ReadFailedException ex) {
1076 LOG.error("Update of vpninterface {} failed", infName, ex);
1080 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1082 TypedWriteTransaction<Configuration> writeConfigTxn,
1083 boolean isInternetVpn) {
1084 if (vpnId == null || port == null) {
1087 String infName = port.getUuid().getValue();
1088 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1090 try (AcquireResult lock = tryInterfaceLock(infName)) {
1091 if (!lock.wasAcquired()) {
1092 // FIXME: why do we even bother with locking if we do not honor it?!
1093 logTryLockFailure(infName);
1097 Optional<VpnInterface> optionalVpnInterface =
1098 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1100 if (optionalVpnInterface.isPresent()) {
1101 VpnInstanceNames vpnInstance = VpnHelper
1102 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1103 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1104 .get().getVpnInstanceNames());
1105 if (oldVpnId != null
1106 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1107 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1109 if (vpnId.getValue() != null
1110 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1111 listVpn.add(vpnInstance);
1113 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1114 .setVpnInstanceNames(listVpn);
1115 LOG.debug("Updating vpn interface {}", infName);
1116 if (!isBeingAssociated) {
1117 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1118 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1119 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1120 while (adjacencyIter.hasNext()) {
1121 Adjacency adjacency = adjacencyIter.next();
1122 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1123 InstanceIdentifier<LearntVpnVipToPort> id =
1124 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1125 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1126 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1127 LogicalDatastoreType.OPERATIONAL, id);
1128 if (optionalVpnVipToPort.isPresent()
1129 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1130 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1131 + "from VPN {}", infName, vpnId, oldVpnId);
1132 adjacencyIter.remove();
1133 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1135 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1136 mipToQuery, infName, vpnId.getValue());
1138 InstanceIdentifier<VpnPortipToPort> build =
1139 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1140 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1141 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1142 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1143 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1144 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1145 mipToQuery, infName, vpnId.getValue());
1148 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1149 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1151 for (FixedIps ip : port.nonnullFixedIps()) {
1152 String ipValue = ip.getIpAddress().stringValue();
1153 if (oldVpnId != null) {
1154 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1155 ipValue, writeConfigTxn);
1157 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1158 && isInternetVpn == true) {
1162 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1163 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1165 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1167 LOG.error("VPN Interface {} not found", infName);
1169 } catch (ReadFailedException ex) {
1170 LOG.error("Updation of vpninterface {} failed", infName, ex);
1175 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1176 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1178 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1180 // Update VPN Instance node
1181 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
1183 // Update local vpn-subnet DS
1184 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1186 if (routerId != null) {
1187 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1188 if (existingVpn != null) {
1189 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1190 // if before reboot, router was already associated to VPN, should not proceed associating router to
1191 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1192 // preserved upon reboot.
1193 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1194 // RouterInterfacesMap via #createVPNInterface call.
1195 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1196 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1199 associateRouterToInternalVpn(vpnId, routerId);
1204 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1205 * specified Neutron Networks and Routers.
1207 * @param vpnId Uuid of the VPN tp be created
1208 * @param name Representative name of the new VPN
1209 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1210 * @param rdList Route-distinguisher for the VPN
1211 * @param irtList A list of Import Route Targets
1212 * @param ertList A list of Export Route Targets
1213 * @param routerIdsList ist of neutron router Id to associate with created VPN
1214 * @param networkList UUID of the neutron network the VPN may be associated to
1215 * @param isL2Vpn True if VPN Instance is of type L2, false if L3
1216 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1217 * @throws Exception if association of L3VPN failed
1219 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1220 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1221 boolean isL2Vpn, long l3vni) throws Exception {
1223 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1225 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1226 for (Uuid routerId : routerIdsList) {
1227 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1228 ipVersChoices = ipVersChoices.addVersion(vers);
1231 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
1233 // Please note that router and networks will be filled into VPNMaps
1234 // by subsequent calls here to associateRouterToVpn and
1235 // associateNetworksToVpn
1236 updateVpnMaps(vpnId, name, null, tenantId, null);
1237 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1238 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1241 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1242 for (Uuid routerId : routerIdsList) {
1243 associateRouterToVpn(vpnId, routerId);
1246 if (networkList != null) {
1247 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1248 if (!failStrings.isEmpty()) {
1249 LOG.error("VPN {} association to networks failed for networks: {}. ",
1250 vpnId.getValue(), failStrings);
1251 throw new Exception(failStrings.toString());
1257 * It handles the invocations to the createVPN RPC method.
1260 // TODO Clean up the exception handling
1261 @SuppressWarnings("checkstyle:IllegalCatch")
1262 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1264 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1265 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1266 List<RpcError> errorList = new ArrayList<>();
1267 int failurecount = 0;
1268 int warningcount = 0;
1270 List<L3vpn> vpns = input.getL3vpn();
1272 vpns = Collections.emptyList();
1274 for (L3vpn vpn : vpns) {
1275 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1276 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1277 formatAndLog(LOG::warn,
1278 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1279 vpn.getId().getValue())));
1283 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1284 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1285 formatAndLog(LOG::warn,
1286 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1287 vpn.getId().getValue())));
1292 if (vpn.getL3vni() != null) {
1293 l3vni = vpn.getL3vni().toJava();
1296 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1297 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1298 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1299 formatAndLog(LOG::warn,
1300 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1301 + "is already configured",
1302 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1306 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1307 if (operationalVpn.isPresent()) {
1308 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1309 formatAndLog(LOG::error,
1310 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1311 + "is still available. Please retry creation of a new vpn with the same RD"
1312 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1313 vpn.getRouteDistinguisher().get(0))));
1317 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1318 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1319 routerIdsList = vpn.getRouterIds();
1320 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1321 routerId : routerIdsList) {
1322 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1323 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1324 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1325 + "{}", vpn.getId(), routerId.getRouterId())));
1329 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1330 if (vpnId != null) {
1331 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1332 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1333 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1334 vpnId.getValue())));
1340 if (vpn.getNetworkIds() != null) {
1341 int initialWarningCount = warningcount;
1342 for (Uuid nw : vpn.getNetworkIds()) {
1343 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1344 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1345 if (network == null) {
1346 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1347 formatAndLog(LOG::warn,
1348 "Creation of L3VPN failed for VPN {} due to network not found {}",
1349 vpn.getId().getValue(), nw.getValue())));
1351 } else if (vpnId != null) {
1352 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1353 formatAndLog(LOG::warn,
1354 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1355 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1356 vpnId.getValue())));
1360 if (warningcount != initialWarningCount) {
1364 List<Uuid> rtrIdsList = new ArrayList<>();
1365 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1366 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1367 rtrId : vpn.getRouterIds()) {
1368 rtrIdsList.add(rtrId.getRouterId());
1372 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1373 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1374 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1375 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1377 List<String> rdList = vpn.getRouteDistinguisher() != null
1378 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1379 List<String> importRdList = vpn.getImportRT() != null
1380 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1381 List<String> exportRdList = vpn.getExportRT() != null
1382 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1384 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1385 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
1386 } catch (Exception ex) {
1387 LOG.error("VPN Creation exception :", ex);
1388 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1389 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1394 // if at least one succeeds; result is success
1395 // if none succeeds; result is failure
1396 if (failurecount + warningcount == vpns.size()) {
1397 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1399 List<String> errorResponseList = new ArrayList<>();
1400 if (!errorList.isEmpty()) {
1401 for (RpcError rpcError : errorList) {
1402 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1403 + ", ErrorMessage: " + rpcError.getMessage());
1406 errorResponseList.add("Operation successful with no errors");
1408 opBuilder.setResponse(errorResponseList);
1409 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1415 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1418 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1420 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1421 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1422 Uuid inputVpnId = input.getId();
1423 List<VpnInstance> vpns = new ArrayList<>();
1424 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1427 if (inputVpnId == null) {
1429 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1431 Optional<VpnInstances> optionalVpns =
1432 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1434 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1435 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1436 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1437 // from getL3VPN output
1438 if (vpn.getRouteDistinguisher() != null) {
1444 opBuilder.setL3vpnInstances(l3vpnList);
1445 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1449 String name = inputVpnId.getValue();
1450 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1451 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1452 // read VpnInstance Info
1453 Optional<VpnInstance> optionalVpn =
1454 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1456 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1458 if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
1459 vpns.add(optionalVpn.get());
1462 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1463 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1467 for (VpnInstance vpnInstance : vpns) {
1468 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1469 // create VpnMaps id
1470 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1471 List<String> rd = Collections.EMPTY_LIST;
1472 if (vpnInstance.getRouteDistinguisher() != null) {
1473 rd = vpnInstance.getRouteDistinguisher();
1475 List<String> ertList = new ArrayList<>();
1476 List<String> irtList = new ArrayList<>();
1478 if (vpnInstance.getVpnTargets() != null) {
1479 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1480 if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
1481 vpnTargetList = vpnInstance.getVpnTargets().getVpnTarget();
1483 if (!vpnTargetList.isEmpty()) {
1484 for (VpnTarget vpnTarget : vpnTargetList) {
1485 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1486 ertList.add(vpnTarget.getVrfRTValue());
1488 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1489 irtList.add(vpnTarget.getVrfRTValue());
1491 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1492 ertList.add(vpnTarget.getVrfRTValue());
1493 irtList.add(vpnTarget.getVrfRTValue());
1499 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1501 if (vpnInstance.getL3vni() != null) {
1502 l3vpn.setL3vni(vpnInstance.getL3vni());
1504 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1505 .class, new VpnMapKey(vpnId)).build();
1506 Optional<VpnMap> optionalVpnMap =
1507 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1509 if (optionalVpnMap.isPresent()) {
1510 VpnMap vpnMap = optionalVpnMap.get();
1511 List<Uuid> rtrIds = new ArrayList<>();
1512 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1513 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1514 rtrIds.add(rtrId.getRouterId());
1517 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1518 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1519 .setName(vpnMap.getName());
1522 l3vpnList.add(l3vpn.build());
1525 opBuilder.setL3vpnInstances(l3vpnList);
1526 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1528 } catch (ReadFailedException ex) {
1529 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1530 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1536 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1539 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1541 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1542 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1543 List<RpcError> errorList = new ArrayList<>();
1545 int failurecount = 0;
1546 int warningcount = 0;
1547 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1548 for (Uuid vpn : vpns) {
1550 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1551 InstanceIdentifier<VpnInstance> vpnIdentifier =
1552 InstanceIdentifier.builder(VpnInstances.class)
1553 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1554 Optional<VpnInstance> optionalVpn =
1555 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1557 if (optionalVpn.isPresent()) {
1560 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1561 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1564 } catch (ReadFailedException ex) {
1565 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1566 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1571 // if at least one succeeds; result is success
1572 // if none succeeds; result is failure
1573 if (failurecount + warningcount == vpns.size()) {
1574 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1576 List<String> errorResponseList = new ArrayList<>();
1577 if (!errorList.isEmpty()) {
1578 for (RpcError rpcError : errorList) {
1579 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1580 + ", ErrorMessage: " + rpcError.getMessage());
1583 errorResponseList.add("Operation successful with no errors");
1585 opBuilder.setResponse(errorResponseList);
1586 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1591 public void createVpnInstanceForSubnet(Uuid subnetId) {
1592 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1593 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1596 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1597 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1598 removeVpn(subnetId);
1601 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1602 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1603 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1604 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1606 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1607 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1610 if (vpnId != null) {
1611 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1612 if (vpnMap == null) {
1613 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1614 + " cannot add subnet {} to VPN", vpnId.getValue(),
1618 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1619 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1620 if (isVpnOfTypeL2(vpnInstance)) {
1621 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1622 NeutronEvpnUtils.Operation.ADD);
1625 if (internetVpnId != null) {
1626 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1627 if (vpnMap == null) {
1628 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1629 + "subnet {} to VPN", internetVpnId.getValue(),
1634 final Uuid internetId = internetVpnId;
1635 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1636 List<Uuid> portList = sn.getPortList();
1637 if (portList != null) {
1638 for (final Uuid portId : portList) {
1639 String vpnInfName = portId.getValue();
1640 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1641 Port port = neutronvpnUtils.getNeutronPort(portId);
1643 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1644 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1647 final Boolean isRouterInterface = port.getDeviceOwner()
1648 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1649 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1650 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1652 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1654 if (vpnIface == null) {
1655 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1656 Set<Uuid> listVpn = new HashSet<>();
1657 if (vpnId != null) {
1660 if (internetId != null) {
1661 listVpn.add(internetId);
1663 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1664 isRouterInterface, wrtConfigTxn);
1665 if (sn.getRouterId() != null) {
1666 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1669 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1670 if (vpnId != null) {
1671 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1673 if (internetId != null) {
1674 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1678 ListenableFutures.addErrorLogging(future, LOG,
1679 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1680 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1681 return Collections.singletonList(future);
1687 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1688 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1689 "removeSubnetFromVpn: at least one VPN must be not null");
1690 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1691 vpnId, internetVpnId);
1692 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1694 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1697 VpnMap vpnMap = null;
1698 VpnInstance vpnInstance = null;
1699 if (vpnId != null) {
1700 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1701 if (vpnMap == null) {
1702 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1703 vpnId.getValue(), subnet.getValue());
1706 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1708 if (internetVpnId == null) {
1709 internetVpnId = sn.getInternetVpnId();
1711 if (internetVpnId != null) {
1712 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1713 if (vpnMap == null) {
1714 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1715 + " from Internet VPN",
1716 internetVpnId.getValue(), subnet.getValue());
1720 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1721 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1722 NeutronEvpnUtils.Operation.DELETE);
1724 boolean subnetVpnAssociation = false;
1725 if (vpnId != null && sn.getVpnId() != null
1726 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1727 subnetVpnAssociation = true;
1728 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1729 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1730 subnetVpnAssociation = true;
1732 if (subnetVpnAssociation == false) {
1733 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1734 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1737 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1738 List<Uuid> portList = sn.getPortList();
1739 final Uuid internetId = internetVpnId;
1740 if (portList != null) {
1741 for (final Uuid portId : portList) {
1742 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1743 final Port port = neutronvpnUtils.getNeutronPort(portId);
1744 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1745 List<ListenableFuture<Void>> futures = new ArrayList<>();
1746 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1747 CONFIGURATION, tx -> {
1749 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1751 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1752 + " port is absent in Neutron config DS", portId.getValue(),
1756 ListenableFutures.addErrorLogging(future, LOG,
1757 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1758 + " belonging to subnet {} and vpnId {}",
1759 portId.getValue(), subnet.getValue(), vpnId.getValue());
1760 futures.add(future);
1765 //update subnet-vpn association
1766 removeFromSubnetNode(subnet, null, null, vpnId, null);
1769 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1770 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1771 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1773 Uuid internalVpnId = sm.getVpnId();
1774 if (internalVpnId == null) {
1775 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1776 sm.getId().getValue());
1779 if (isBeingAssociated) {
1780 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1782 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1785 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1786 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1787 if (isBeingAssociated) {
1788 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1789 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1791 removeInternetVpnFromVpnInterface(vpn,
1792 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1797 // Check for ports on this subnet and update association of
1798 // corresponding vpn-interfaces to internet vpn
1799 List<Uuid> portList = sm.getPortList();
1800 if (portList != null) {
1801 for (Uuid port : portList) {
1802 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1803 port.getValue(), isBeingAssociated);
1804 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1805 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1807 if (isBeingAssociated) {
1808 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1809 true, false, tx, true);
1811 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1819 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1820 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1821 oldVpnId.getValue(), newVpnId.getValue());
1822 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1823 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1824 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1825 Uuid vpnExtUuid = netIsExternal ? null
1826 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1827 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1829 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1832 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1833 * associated with internet BGP-VPN.
1835 if (vpnExtUuid != null) {
1836 /* Update V6 Internet default route match with new VPN metadata.
1837 * isBeingAssociated = true means oldVpnId is same as routerId
1838 * isBeingAssociated = false means newVpnId is same as routerId
1840 if (isBeingAssociated) {
1841 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1843 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1846 //Update Router Interface first synchronously.
1847 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1848 ListenableFuture<Void> future =
1849 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1850 tx -> updateVpnInterface(newVpnId, oldVpnId,
1851 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1852 isBeingAssociated, true, tx, false));
1853 Futures.addCallback(future, new FutureCallback<Void>() {
1855 public void onSuccess(Void result) {
1856 // Check for ports on this subnet and update association of
1857 // corresponding vpn-interfaces to external vpn
1858 List<Uuid> portList = sn.getPortList();
1859 if (portList != null) {
1860 for (Uuid port : portList) {
1861 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1862 port.getValue(), isBeingAssociated);
1863 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1864 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1865 tx -> updateVpnInterface(newVpnId, oldVpnId,
1866 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1873 public void onFailure(Throwable throwable) {
1875 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1877 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1879 }, MoreExecutors.directExecutor());
1884 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1885 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1886 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1889 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1890 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1891 final ReentrantLock lock = lockForUuid(routerId);
1894 Optional<RouterInterfaces> optRouterInterfaces =
1895 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1896 routerInterfacesId);
1897 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1898 .setInterfaceId(interfaceName).build();
1899 if (optRouterInterfaces.isPresent()) {
1900 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1901 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1903 // TODO Shouldn't we be doing something with builder and interfaces?
1904 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1905 // List<Interfaces> interfaces = new ArrayList<>();
1906 // interfaces.add(routerInterface);
1908 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1909 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1911 } catch (ReadFailedException | TransactionCommitFailedException e) {
1912 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1918 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1919 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1920 final ReentrantLock lock = lockForUuid(routerId);
1923 Optional<RouterInterfaces> optRouterInterfaces =
1924 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1925 routerInterfacesId);
1926 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1927 .setInterfaceId(interfaceName).build();
1928 if (optRouterInterfaces.isPresent()) {
1929 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1930 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
1931 if (interfaces != null && interfaces.remove(routerInterface)) {
1932 if (interfaces.isEmpty()) {
1933 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1934 routerInterfacesId);
1936 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1937 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1941 } catch (ReadFailedException | TransactionCommitFailedException e) {
1942 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1949 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1950 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1951 * route will be ignored.
1953 * @param vpnName the VPN identifier
1954 * @param interVpnLinkRoutes The list of static routes
1955 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1957 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1958 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1959 for (Routes route : interVpnLinkRoutes) {
1960 String nexthop = route.getNexthop().stringValue();
1961 String destination = route.getDestination().stringValue();
1962 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1963 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1964 AddStaticRouteInput rpcInput =
1965 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1966 .setVpnInstanceName(vpnName.getValue())
1968 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1969 RpcResult<AddStaticRouteOutput> rpcResult;
1971 rpcResult = labelOuputFtr.get();
1972 if (rpcResult.isSuccessful()) {
1973 LOG.debug("Label generated for destination {} is: {}",
1974 destination, rpcResult.getResult().getLabel());
1976 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1977 destination, nexthop, rpcResult.getErrors());
1979 } catch (InterruptedException | ExecutionException e) {
1980 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1981 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1984 // Any other case is a fault.
1985 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1986 route.getDestination().stringValue(), nexthop);
1993 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1994 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1996 * @param vpnName the VPN identifier
1997 * @param interVpnLinkRoutes The list of static routes
1998 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2000 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2001 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2002 for (Routes route : interVpnLinkRoutes) {
2003 String nexthop = route.getNexthop().stringValue();
2004 String destination = route.getDestination().stringValue();
2005 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2006 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2007 RemoveStaticRouteInput rpcInput =
2008 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2009 .setVpnInstanceName(vpnName.getValue())
2012 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2013 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2015 // Any other case is a fault.
2016 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2017 route.getDestination().stringValue(), nexthop);
2024 * Returns true if the specified nexthop is the other endpoint in an
2025 * InterVpnLink, regarding one of the VPN's point of view.
2027 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2028 InterVpnLink interVpnLink) {
2030 interVpnLink != null
2031 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2032 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2033 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2034 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2038 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2039 List<Adjacency> adjList = new ArrayList<>();
2040 Map<String, List<String>> adjMap = new HashMap<>();
2041 for (Routes route : routeList) {
2042 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2043 LOG.error("Incorrect input received for extra route. {}", route);
2045 String nextHop = route.getNexthop().stringValue();
2046 String destination = route.getDestination().stringValue();
2047 if (!nextHop.equals(fixedIp)) {
2048 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2051 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2053 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2054 if (!hops.contains(nextHop)) {
2060 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2061 final String destination = entry.getKey();
2062 final List<String> ipList = entry.getValue();
2063 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2064 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2065 .withKey(new AdjacencyKey(destination)).build();
2071 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2072 checkAlarmExtraRoutes(vpnId, routeList);
2074 for (Routes route : routeList) {
2075 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2076 LOG.error("Incorrect input received for extra route. {}", route);
2078 String nextHop = route.getNexthop().stringValue();
2079 String destination = route.getDestination().stringValue();
2080 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2082 if (infName != null) {
2083 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2084 destination, vpnId.getValue(), nextHop, infName);
2085 boolean isLockAcquired = false;
2087 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2088 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2089 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2090 .child(Adjacency.class, new AdjacencyKey(destination));
2091 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2092 LogicalDatastoreType.CONFIGURATION, path);
2093 if (existingAdjacency.isPresent()
2094 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2095 LOG.error("The route with destination {} nextHop {} is already present as"
2096 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2097 destination, nextHop, infName);
2100 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2101 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2102 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2104 try (AcquireResult lock = tryInterfaceLock(infName)) {
2105 if (!lock.wasAcquired()) {
2106 // FIXME: why do we even bother with locking if we do not honor it?!
2107 logTryLockFailure(infName);
2110 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2113 } catch (TransactionCommitFailedException e) {
2114 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2115 destination, nextHop, e);
2116 } catch (ReadFailedException e) {
2117 LOG.error("Exception on reading data-store ", e);
2120 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2121 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2128 * This method setup or down an alarm about extra route fault.
2129 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2130 * available RDs, then an alarm and an error is generated.<br>
2131 * <b>Be careful</b> the routeList could be changed.
2133 * @param vpnId the vpnId of vpn to control.
2134 * @param routeList the list of router to check, it could be modified.
2136 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2137 if (!neutronvpnAlarm.isAlarmEnabled()) {
2138 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2141 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2142 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2143 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2147 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2148 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2149 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2153 for (Routes route : routeList) {
2154 // count the number of nexthops for each same route.getDestingation().getValue()
2155 String destination = route.getDestination().stringValue();
2156 String nextHop = route.getNexthop().stringValue();
2157 List<String> nextHopList = new ArrayList<>();
2158 nextHopList.add(nextHop);
2160 for (Routes routeTmp : routeList) {
2161 String routeDest = routeTmp.getDestination().stringValue();
2162 if (!destination.equals(routeDest)) {
2165 String routeNextH = routeTmp.getNexthop().stringValue();
2166 if (nextHop.equals(routeNextH)) {
2170 nextHopList.add(routeTmp.getNexthop().stringValue());
2172 final List<String> rdList = new ArrayList<>();
2173 if (vpnInstance != null
2174 && vpnInstance.getRouteDistinguisher() != null) {
2175 vpnInstance.getRouteDistinguisher().forEach(rd -> {
2181 // 1. VPN Instance Name
2182 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2185 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2186 Uuid routerUuid = routerUuidList.get(0);
2187 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2188 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2190 // 3. List of RDs associated with the VPN
2191 detailsAlarm.append(" List of RDs associated with the VPN: ");
2192 for (String s : rdList) {
2193 detailsAlarm.append(s);
2194 detailsAlarm.append(", ");
2197 // 4. Prefix in question
2198 detailsAlarm.append(" for prefix: ");
2199 detailsAlarm.append(route.getDestination().stringValue());
2201 // 5. List of NHs for the prefix
2202 detailsAlarm.append(" for nextHops: ");
2203 for (String s : nextHopList) {
2204 detailsAlarm.append(s);
2205 detailsAlarm.append(", ");
2208 if (rdList.size() < nbNextHops) {
2209 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2211 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2216 // TODO Clean up the exception handling
2217 @SuppressWarnings("checkstyle:IllegalCatch")
2218 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2219 for (Routes route : routeList) {
2220 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2221 String nextHop = route.getNexthop().stringValue();
2222 String destination = route.getDestination().stringValue();
2223 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2225 if (infName == null) {
2226 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2227 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2228 // Proceed to remove the next extra-route
2231 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2232 destination, vpnId.getValue(), nextHop, infName);
2234 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2235 InstanceIdentifier.builder(VpnInterfaces.class)
2236 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2237 .augmentation(Adjacencies.class)
2238 .child(Adjacency.class, new AdjacencyKey(destination))
2242 // Looking for existing prefix in MDSAL database
2243 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2244 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2245 boolean updateNextHops = false;
2246 List<String> nextHopList = new ArrayList<>();
2247 if (adjacency.isPresent()) {
2248 List<String> nhListRead = adjacency.get().getNextHopIpList();
2249 if (nhListRead.size() > 1) { // ECMP case
2250 for (String nextHopRead : nhListRead) {
2251 if (nextHopRead.equals(nextHop)) {
2252 updateNextHops = true;
2254 nextHopList.add(nextHopRead);
2260 try (AcquireResult lock = tryInterfaceLock(infName)) {
2261 if (!lock.wasAcquired()) {
2262 // FIXME: why do we even bother with locking if we do not honor it?!
2263 logTryLockFailure(infName);
2266 if (updateNextHops) {
2267 // An update must be done, not including the current next hop
2268 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2269 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2270 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2271 .setNextHopIpList(nextHopList)
2272 .withKey(new AdjacencyKey(destination))
2274 Adjacencies erAdjs =
2275 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2276 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2277 .addAugmentation(Adjacencies.class, erAdjs).build();
2278 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2279 vpnIfIdentifier, vpnIf);
2281 // Remove the whole route
2282 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2283 adjacencyIdentifier);
2284 LOG.trace("extra route {} deleted successfully", route);
2287 } catch (TransactionCommitFailedException | ReadFailedException e) {
2288 LOG.error("exception in deleting extra route with destination {} for interface {}",
2289 destination, infName, e);
2292 LOG.error("Incorrect input received for extra route: {}", route);
2297 public void removeVpn(Uuid vpnId) {
2299 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2300 if (vpnMap != null) {
2301 List<RouterIds> routerIdsList = vpnMap.getRouterIds();
2302 List<Uuid> routerUuidList = new ArrayList<>();
2303 // dissociate router
2304 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2305 for (RouterIds router : routerIdsList) {
2306 Uuid routerId = router.getRouterId();
2307 routerUuidList.add(routerId);
2308 dissociateRouterFromVpn(vpnId, routerId);
2311 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2312 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2315 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2317 // remove entire vpnMaps node
2318 deleteVpnMapsNode(vpnId);
2320 // remove vpn-instance
2321 deleteVpnInstance(vpnId);
2322 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2325 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2326 return vpnInstance != null && vpnInstance.isL2vpn();
2329 // TODO Clean up the exception handling
2330 @SuppressWarnings("checkstyle:IllegalCatch")
2331 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2332 updateVpnMaps(vpnId, null, routerId, null, null);
2333 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2334 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2335 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2336 for (Subnetmap sn : subMapList) {
2337 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2338 if (!ipVersion.isIpVersionChosen(ipVers)) {
2339 ipVersion = ipVersion.addVersion(ipVers);
2342 if (ipVersion != IpVersionChoice.UNDEFINED) {
2343 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2345 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2347 for (Subnetmap sn : subMapList) {
2348 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2352 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2353 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2354 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2355 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2356 for (Uuid subnet : routerSubnets) {
2357 IpVersionChoice version = NeutronvpnUtils
2358 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2359 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2360 addSubnetToVpn(vpnId, subnet, null);
2362 addSubnetToVpn(vpnId, subnet, internetVpnId);
2367 // TODO Clean up the exception handling
2368 @SuppressWarnings("checkstyle:IllegalCatch")
2369 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2371 clearFromVpnMaps(vpnId, routerId, null);
2372 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2373 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2374 for (Subnetmap sn : subMapList) {
2375 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2376 if (ipVersion.isIpVersionChosen(ipVers)) {
2377 ipVersion = ipVersion.addVersion(ipVers);
2379 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2380 routerId.getValue());
2381 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2383 if (ipVersion != IpVersionChoice.UNDEFINED) {
2384 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2386 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2392 * Parses and associates networks list with given VPN.
2394 * @param vpnId Uuid of given VPN.
2395 * @param networkList List list of network Ids (Uuid), which will be associated.
2396 * @return list of formatted strings with detailed error messages.
2399 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2400 List<String> failedNwList = new ArrayList<>();
2401 HashSet<Uuid> passedNwList = new HashSet<>();
2402 boolean isExternalNetwork = false;
2403 if (networkList.isEmpty()) {
2404 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2405 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2407 return failedNwList;
2409 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2410 if (vpnInstance == null) {
2411 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2412 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2413 + "in ConfigDS", vpnId.getValue()));
2414 return failedNwList;
2417 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2418 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2420 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2421 + "associated with", vpnId.getValue()));
2422 return failedNwList;
2424 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2425 for (Uuid nw : networkList) {
2426 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2427 if (network == null) {
2428 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2429 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2433 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2434 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2435 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2436 nw.getValue(), vpnId.getValue());
2437 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2438 nw.getValue(), vpnId.getValue()));
2441 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2442 if (networkVpnId != null) {
2443 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2444 nw.getValue(), networkVpnId.getValue());
2445 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2446 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2449 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2450 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2451 nw.getValue(), vpnId.getValue());
2452 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2453 nw.getValue(), vpnId.getValue()));
2456 if (NeutronvpnUtils.getIsExternal(network)) {
2457 isExternalNetwork = true;
2459 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2460 if (subnetmapList == null || subnetmapList.isEmpty()) {
2461 passedNwList.add(nw);
2464 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2467 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2468 for (Subnetmap subnetmap : subnetmapList) {
2469 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2470 if (!ipVersion.isIpVersionChosen(ipVers)) {
2471 ipVersion = ipVersion.addVersion(ipVers);
2474 if (ipVersion != IpVersionChoice.UNDEFINED) {
2475 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2476 + " for VPN {} ", ipVersion, vpnId);
2477 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2479 for (Subnetmap subnetmap : subnetmapList) {
2480 Uuid subnetId = subnetmap.getId();
2481 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2482 if (subnetVpnId != null) {
2483 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2484 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2485 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2486 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2489 if (!NeutronvpnUtils.getIsExternal(network)) {
2490 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2492 addSubnetToVpn(vpnId, subnetId, null);
2493 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2495 passedNwList.add(nw);
2498 passedNwList.add(nw);
2500 } catch (ReadFailedException e) {
2501 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2503 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2506 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2507 if (!isExternalNetwork) {
2508 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2510 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2511 return failedNwList;
2514 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2515 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2518 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2519 if (vpnOpDataEntry == null) {
2520 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2523 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2524 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2525 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2527 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2528 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2529 updateVpnMaps(vpnId, null, null, null, extNwList);
2530 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2531 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2532 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2534 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2537 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2538 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2541 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2542 updateVpnInternetForSubnet(sm, vpnId, true);
2544 if (!ipVersion.isIpVersionChosen(ipVers)) {
2545 ipVersion = ipVersion.addVersion(ipVers);
2548 if (ipVersion != IpVersionChoice.UNDEFINED) {
2549 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2550 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2551 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2557 * Parses and disassociates networks list from given VPN.
2559 * @param vpnId Uuid of given VPN.
2560 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2561 * @return list of formatted strings with detailed error messages.
2564 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2565 List<String> failedNwList = new ArrayList<>();
2566 HashSet<Uuid> passedNwList = new HashSet<>();
2567 if (networkList.isEmpty()) {
2568 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2569 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2571 return failedNwList;
2573 for (Uuid nw : networkList) {
2574 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2575 if (networkSubnets == null) {
2576 passedNwList.add(nw);
2579 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2580 if (network == null) {
2581 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2582 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2586 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2587 if (networkVpnId == null) {
2588 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2589 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2593 if (!vpnId.equals(networkVpnId)) {
2594 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2595 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2596 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2597 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2601 if (NeutronvpnUtils.getIsExternal(network)) {
2602 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2603 passedNwList.add(nw);
2605 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2606 nw.getValue(), vpnId.getValue());
2607 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2612 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2613 for (Uuid subnet : networkSubnets) {
2614 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2615 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2616 if (!ipVersion.isIpVersionChosen(ipVers)) {
2617 ipVersion = ipVersion.addVersion(ipVers);
2619 if (!NeutronvpnUtils.getIsExternal(network)) {
2620 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2622 removeSubnetFromVpn(vpnId, subnet, null);
2623 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2624 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2626 passedNwList.add(nw);
2629 if (ipVersion != IpVersionChoice.UNDEFINED) {
2630 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2631 + " for VPN {}", ipVersion, vpnId);
2632 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2635 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2636 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2637 passedNwList, vpnId.getValue());
2638 return failedNwList;
2641 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2642 if (!removeExternalNetworkFromVpn(extNet)) {
2645 // check, if there is another Provider Networks associated with given VPN
2646 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2647 if (vpnNets != null) {
2648 //Remove currently disassociated network from the list
2649 vpnNets.remove(extNet.getUuid());
2650 for (Uuid netId : vpnNets) {
2651 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2652 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2653 + "{}", vpnId.getValue(), netId.getValue());
2658 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2659 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2660 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2661 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2662 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2663 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2664 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2666 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2669 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2670 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2673 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2674 updateVpnInternetForSubnet(sm, vpnId, false);
2676 if (!ipVersion.isIpVersionChosen(ipVers)) {
2677 ipVersion = ipVersion.addVersion(ipVers);
2680 if (ipVersion != IpVersionChoice.UNDEFINED) {
2681 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2682 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2684 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2690 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2693 // TODO Clean up the exception handling
2694 @SuppressWarnings("checkstyle:IllegalCatch")
2695 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2697 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2698 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2699 StringBuilder returnMsg = new StringBuilder();
2700 Uuid vpnId = input.getVpnId();
2703 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2704 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2705 input.getNetworkId());
2706 List<Uuid> netIds = input.getNetworkId();
2707 if (netIds != null && !netIds.isEmpty()) {
2708 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2709 if (!failed.isEmpty()) {
2710 returnMsg.append(failed);
2714 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2716 if (returnMsg.length() != 0) {
2717 opBuilder.setResponse(
2718 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2719 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2720 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2722 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2724 } catch (Exception ex) {
2725 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2726 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2727 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2728 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2730 LOG.debug("associateNetworks returns..");
2735 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2738 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2740 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2741 LOG.debug("associateRouter {}", input);
2742 StringBuilder returnMsg = new StringBuilder();
2743 Uuid vpnId = input.getVpnId();
2744 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2745 routerIds = input.getRouterIds();
2746 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2747 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2748 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2749 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2750 .RouterIds routerId : routerIds) {
2751 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2752 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2753 if (vpnMap != null) {
2755 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2756 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2757 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2758 .append(routerId.getRouterId());
2759 } else if (extVpnId != null) {
2760 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2761 + "another VPN ").append(extVpnId.getValue());
2763 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2764 routerId.getRouterId());
2765 associateRouterToVpn(vpnId, routerId.getRouterId());
2768 returnMsg.append("router not found : ").append(routerId.getRouterId());
2771 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2773 if (returnMsg.length() != 0) {
2774 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2775 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2776 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2778 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2781 LOG.debug("associateRouter returns..");
2786 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2789 // TODO Clean up the exception handling
2790 @SuppressWarnings("checkstyle:IllegalCatch")
2791 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2792 GetFixedIPsForNeutronPortInput input) {
2793 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2794 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2795 Uuid portId = input.getPortId();
2796 StringBuilder returnMsg = new StringBuilder();
2798 List<String> fixedIPList = new ArrayList<>();
2799 Port port = neutronvpnUtils.getNeutronPort(portId);
2801 for (FixedIps ip : port.nonnullFixedIps()) {
2802 fixedIPList.add(ip.getIpAddress().stringValue());
2805 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2807 if (returnMsg.length() != 0) {
2808 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2810 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2811 returnMsg)).build());
2813 opBuilder.setFixedIPs(fixedIPList);
2814 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2816 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2818 } catch (Exception ex) {
2819 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2820 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2821 portId.getValue(), ex.getMessage(), ex)).build());
2827 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2830 // TODO Clean up the exception handling
2831 @SuppressWarnings("checkstyle:IllegalCatch")
2832 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2834 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2835 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2837 LOG.debug("dissociateNetworks {}", input);
2838 StringBuilder returnMsg = new StringBuilder();
2839 Uuid vpnId = input.getVpnId();
2842 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2843 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2844 input.getNetworkId());
2845 List<Uuid> netIds = input.getNetworkId();
2846 if (netIds != null && !netIds.isEmpty()) {
2847 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2848 if (!failed.isEmpty()) {
2849 returnMsg.append(failed);
2853 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2855 if (returnMsg.length() != 0) {
2856 opBuilder.setResponse(
2857 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2858 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2860 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2862 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2864 } catch (Exception ex) {
2865 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2866 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2867 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2869 LOG.debug("dissociateNetworks returns..");
2874 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2877 // TODO Clean up the exception handling
2878 @SuppressWarnings("checkstyle:IllegalCatch")
2879 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2881 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2883 LOG.debug("dissociateRouter {}", input);
2884 StringBuilder returnMsg = new StringBuilder();
2885 Uuid vpnId = input.getVpnId();
2886 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2887 .RouterIds> routerIdList = input.getRouterIds();
2888 String routerIdsString = "";
2889 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2890 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2891 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2892 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2893 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2894 .RouterIds routerId : routerIdList) {
2896 if (routerId != null) {
2897 routerIdsString += routerId.getRouterId() + ", ";
2898 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2900 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2901 if (routerVpnId == null) {
2902 returnMsg.append("input router ").append(routerId.getRouterId())
2903 .append(" not associated to any vpn yet");
2904 } else if (vpnId.equals(routerVpnId)) {
2905 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2907 returnMsg.append("input router ").append(routerId.getRouterId())
2908 .append(" associated to vpn ")
2909 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2912 returnMsg.append("router not found : ").append(routerId.getRouterId());
2915 if (returnMsg.length() != 0) {
2916 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2917 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2918 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2919 returnMsg)).build());
2921 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2923 } catch (Exception ex) {
2924 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2925 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2926 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2930 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2933 LOG.debug("dissociateRouter returns..");
2937 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2938 // check if the router is associated to some VPN
2939 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2940 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2941 if (vpnId != null) {
2942 // remove existing external vpn interfaces
2943 for (Uuid subnetId : routerSubnetIds) {
2944 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2946 clearFromVpnMaps(vpnId, routerId, null);
2948 // remove existing internal vpn interfaces
2949 for (Uuid subnetId : routerSubnetIds) {
2950 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2953 // delete entire vpnMaps node for internal VPN
2954 deleteVpnMapsNode(routerId);
2956 // delete vpn-instance for internal VPN
2957 deleteVpnInstance(routerId);
2960 protected Subnet getNeutronSubnet(Uuid subnetId) {
2961 return neutronvpnUtils.getNeutronSubnet(subnetId);
2965 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2966 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2968 return sn.getGatewayIp();
2974 protected Network getNeutronNetwork(Uuid networkId) {
2975 return neutronvpnUtils.getNeutronNetwork(networkId);
2978 protected Port getNeutronPort(String name) {
2979 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2982 protected Port getNeutronPort(Uuid portId) {
2983 return neutronvpnUtils.getNeutronPort(portId);
2986 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2987 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2990 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2991 return neutronvpnUtils.getNetworksForVpn(vpnId);
2995 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2997 * @return a List of String to be printed on screen
2998 * @throws ReadFailedException if there was a problem reading from the data store
3000 public List<String> showNeutronPortsCLI() throws ReadFailedException {
3001 List<String> result = new ArrayList<>();
3002 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3004 result.add("-------------------------------------------------------------------------------------------");
3005 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3007 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3008 if (ports.isPresent() && ports.get().getPort() != null) {
3009 for (Port port : ports.get().nonnullPort()) {
3010 List<FixedIps> fixedIPs = port.getFixedIps();
3011 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3012 List<String> ipList = new ArrayList<>();
3013 for (FixedIps fixedIp : fixedIPs) {
3014 IpAddress ipAddress = fixedIp.getIpAddress();
3015 if (ipAddress.getIpv4Address() != null) {
3016 ipList.add(ipAddress.getIpv4Address().getValue());
3018 ipList.add(ipAddress.getIpv6Address().getValue());
3021 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3022 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3023 ipList.toString()));
3025 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3026 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3035 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3037 * @param vpnuuid Uuid of the VPN whose config must be shown
3038 * @return formatted output list
3039 * @throws InterruptedException if there was a thread related problem getting the data to display
3040 * @throws ExecutionException if there was any other problem getting the data to display
3042 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3043 List<String> result = new ArrayList<>();
3044 if (vpnuuid == null) {
3046 result.add("Displaying VPN config for all VPNs");
3047 result.add("To display VPN config for a particular VPN, use the following syntax");
3048 result.add(getshowVpnConfigCLIHelp());
3050 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3051 if (rpcResult.isSuccessful()) {
3053 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3055 result.add(String.format(" %-80s ", "Import-RTs"));
3057 result.add(String.format(" %-80s ", "Export-RTs"));
3059 result.add(String.format(" %-76s ", "Subnet IDs"));
3061 result.add("------------------------------------------------------------------------------------");
3063 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3064 rpcResult.getResult().nonnullL3vpnInstances()) {
3065 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3067 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3068 vpn.getRouteDistinguisher()));
3070 result.add(String.format(" %-80s ", vpn.getImportRT()));
3072 result.add(String.format(" %-80s ", vpn.getExportRT()));
3075 Uuid vpnid = vpn.getId();
3076 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3077 if (!subnetList.isEmpty()) {
3078 for (Uuid subnetuuid : subnetList) {
3079 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3082 result.add(String.format(" %-76s ", "\" \""));
3085 result.add("----------------------------------------");
3089 String errortag = rpcResult.getErrors().iterator().next().getTag();
3090 if (Objects.equals(errortag, "")) {
3092 result.add("No VPN has been configured yet");
3093 } else if (Objects.equals(errortag, "invalid-value")) {
3095 result.add("VPN " + vpnuuid.getValue() + " is not present");
3097 result.add("error getting VPN info : " + rpcResult.getErrors());
3098 result.add(getshowVpnConfigCLIHelp());
3104 protected void createExternalVpnInterfaces(Uuid extNetId) {
3105 if (extNetId == null) {
3106 LOG.error("createExternalVpnInterfaces: external network is null");
3110 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3111 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3112 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3116 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3117 for (String elanInterface : extElanInterfaces) {
3118 createExternalVpnInterface(extNetId, elanInterface, tx);
3120 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3123 // TODO Clean up the exception handling
3124 @SuppressWarnings("checkstyle:IllegalCatch")
3125 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3126 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3127 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3128 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3131 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3132 for (String elanInterface : extElanInterfaces) {
3133 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3134 .buildVpnInterfaceIdentifier(elanInterface);
3135 LOG.info("Removing vpn interface {}", elanInterface);
3136 tx.delete(vpnIfIdentifier);
3138 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3141 private void createExternalVpnInterface(Uuid vpnId, String infName,
3142 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3143 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3144 false /* not a router iface */, wrtConfigTxn);
3147 // TODO Clean up the exception handling
3148 @SuppressWarnings("checkstyle:IllegalCatch")
3149 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3150 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3151 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3152 if (vpnIdList.isEmpty() || infName == null) {
3153 LOG.error("vpnid is empty or interface({}) is null", infName);
3156 if (wrtConfigTxn == null) {
3157 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3158 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3159 "Error writing VPN interface");
3162 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3163 for (Uuid vpnId: vpnIdList) {
3164 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3165 AssociatedSubnetType.V4AndV6Subnets);
3166 vpnIdListStruct.add(vpnInstance);
3169 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3170 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3172 .setVpnInstanceNames(vpnIdListStruct)
3173 .setRouterInterface(isRouterInterface);
3174 LOG.info("Network Id is {}", networkUuid);
3175 if (networkUuid != null) {
3176 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3177 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3178 NetworkAttributes.NetworkType networkType = providerType != null
3179 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3180 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3181 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3182 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3185 if (adjacencies != null) {
3186 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3188 VpnInterface vpnIf = vpnb.build();
3190 LOG.info("Creating vpn interface {}", vpnIf);
3191 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3192 } catch (Exception ex) {
3193 LOG.error("Creation of vpninterface {} failed", infName, ex);
3197 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3198 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3199 if (vpnId == null || infName == null) {
3200 LOG.error("vpn id or interface is null");
3203 if (wrtConfigTxn == null) {
3204 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3205 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3206 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3207 }), LOG, "Error updating VPN interface with adjacencies");
3211 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3213 try (AcquireResult lock = tryInterfaceLock(infName)) {
3214 if (!lock.wasAcquired()) {
3215 // FIXME: why do we even bother with locking if we do not honor it?!
3216 logTryLockFailure(infName);
3220 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3221 .syncReadOptional(dataBroker, LogicalDatastoreType
3222 .CONFIGURATION, vpnIfIdentifier);
3223 if (optionalVpnInterface.isPresent()) {
3224 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3225 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3227 if (adjacencies == null) {
3230 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3231 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3232 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3233 optionalVpnInterface.get().getVpnInstanceNames());
3234 if (listVpnInstances.isEmpty()
3235 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3236 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3237 AssociatedSubnetType.V4AndV6Subnets);
3238 listVpnInstances.add(vpnInstance);
3239 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3242 VpnInstanceNames vpnInstance = VpnHelper
3243 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3244 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3245 listVpnInstances.add(vpnInstance);
3246 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3248 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3249 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3251 } catch (IllegalStateException | ReadFailedException ex) {
3252 // FIXME: why are we catching IllegalStateException here?
3253 LOG.error("Update of vpninterface {} failed", infName, ex);
3258 private String getshowVpnConfigCLIHelp() {
3259 StringBuilder help = new StringBuilder("Usage:");
3260 help.append("display vpn-config [-vid/--vpnid <id>]");
3261 return help.toString();
3264 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3265 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3269 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3270 return neutronEvpnManager.createEVPN(input);
3274 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3275 return neutronEvpnManager.getEVPN(input);
3279 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3280 return neutronEvpnManager.deleteEVPN(input);
3283 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3284 Uuid extNetId = extNet.getUuid();
3285 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3286 .child(Networks.class, new NetworksKey(extNetId)).build();
3289 Optional<Networks> optionalExtNets =
3290 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3292 if (!optionalExtNets.isPresent()) {
3293 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3294 extNetId.getValue());
3297 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3298 builder.setVpnid(vpnId);
3299 Networks networks = builder.build();
3300 // Add Networks object to the ExternalNetworks list
3301 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3302 extNetId.getValue());
3303 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3306 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3307 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3308 extNetId.getValue(), ex);
3313 private boolean removeExternalNetworkFromVpn(Network extNet) {
3314 Uuid extNetId = extNet.getUuid();
3315 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3316 .child(Networks.class, new NetworksKey(extNetId)).build();
3318 Optional<Networks> optionalNets =
3319 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3321 NetworksBuilder builder = null;
3322 if (optionalNets.isPresent()) {
3323 builder = new NetworksBuilder(optionalNets.get());
3325 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3326 extNetId.getValue());
3329 builder.setVpnid(null);
3330 Networks networks = builder.build();
3331 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3332 extNetId.getValue());
3333 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3335 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3336 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3337 extNetId.getValue(), ex);
3342 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3343 Optional<String> existingVpnName = Optional.of(primaryRd);
3344 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3346 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3347 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3348 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3349 } catch (ReadFailedException e) {
3350 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3352 /*Read failed. We don't know if a VPN exists or not.
3353 * Return primaryRd to halt caller execution, to be safe.*/
3354 return existingVpnName;
3356 if (vpnInstanceOpDataOptional.isPresent()) {
3357 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3359 existingVpnName = Optional.absent();
3361 return existingVpnName;
3364 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3365 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3368 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3369 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3372 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3373 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3376 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3377 String message = tuple.getMessage();
3378 logger.accept(message);
3382 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3383 @NonNull Subnetmap subnetMap) {
3384 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3385 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3386 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3387 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3388 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3389 subnetMap.getId().getValue(), internetVpnId.getValue());
3393 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3394 @NonNull Subnetmap subnetMap) {
3395 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3396 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3399 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3400 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3401 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3402 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3403 internetVpnId.getValue(), routerId.getValue());
3404 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3410 private AcquireResult tryInterfaceLock(final String infName) {
3411 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3415 private AcquireResult tryVpnLock(final Uuid vpnId) {
3416 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3419 private static ReentrantLock lockForUuid(Uuid uuid) {
3420 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3421 return JvmGlobalLocks.getLockForString(uuid.getValue());
3424 private static void logTryLockFailure(Object objectId) {
3425 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());