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.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
86 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
87 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
180 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
181 import org.opendaylight.yangtools.yang.common.RpcError;
182 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
183 import org.opendaylight.yangtools.yang.common.RpcResult;
184 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
185 import org.slf4j.Logger;
186 import org.slf4j.LoggerFactory;
187 import org.slf4j.helpers.FormattingTuple;
188 import org.slf4j.helpers.MessageFormatter;
191 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
193 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
194 private static final long LOCK_WAIT_TIME = 10L;
196 private final DataBroker dataBroker;
197 private final ManagedNewTransactionRunner txRunner;
198 private final VpnRpcService vpnRpcService;
199 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
200 private final IElanService elanService;
201 private final NeutronvpnConfig neutronvpnConfig;
202 private final NeutronEvpnManager neutronEvpnManager;
203 private final NeutronEvpnUtils neutronEvpnUtils;
204 private final JobCoordinator jobCoordinator;
205 private final NeutronvpnUtils neutronvpnUtils;
206 private final IVpnManager vpnManager;
207 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
208 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
209 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
210 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
213 public NeutronvpnManager(
214 final DataBroker dataBroker,
215 final VpnRpcService vpnRpcSrv, final IElanService elanService,
216 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
217 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
218 final JobCoordinator jobCoordinator,
219 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
220 this.dataBroker = dataBroker;
221 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
222 vpnRpcService = vpnRpcSrv;
223 this.elanService = elanService;
224 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
225 this.neutronvpnConfig = neutronvpnConfig;
226 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
227 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
228 this.jobCoordinator = jobCoordinator;
229 this.neutronvpnUtils = neutronvpnUtils;
230 this.vpnManager = vpnManager;
237 public void close() {
238 LOG.info("{} close", getClass().getSimpleName());
241 private void configureFeatures() throws TransactionCommitFailedException {
242 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
243 Neutron.class).child(Features.class).child(
244 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
245 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
247 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
248 } catch (OptimisticLockFailedException e) {
249 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
251 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
252 Neutron.class).child(Features.class).child(
253 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
254 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
256 SingleTransactionDataBroker.syncWrite(
257 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
258 } catch (OptimisticLockFailedException e) {
259 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
263 public String getOpenDaylightVniRangesConfig() {
264 return neutronvpnConfig.getOpendaylightVniRanges();
267 // TODO Clean up the exception handling
268 @SuppressWarnings("checkstyle:IllegalCatch")
269 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
270 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId) {
272 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
273 final ReentrantLock lock = lockForUuid(subnetId);
276 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
277 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
278 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
279 if (sn.isPresent()) {
280 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
281 subnetId.getValue());
284 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
285 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
286 .setNetworkType(networkType).setSegmentationId(segmentationId);
287 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
288 subnetId.getValue());
289 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
290 subnetMapIdentifier, subnetmapBuilder.build());
294 } catch (TransactionCommitFailedException | ReadFailedException e) {
295 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
297 // check if there are ports to update for already created Subnetmap node
298 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
299 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
300 if (entry.getValue().getValue().equals(subnetId.getValue())) {
301 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
302 unprocessedPortsMap.remove(entry.getKey());
308 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
309 @Nullable Uuid internetvpnId) {
310 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
311 .child(Subnetmap.class, new SubnetmapKey(subnetId))
313 final ReentrantLock lock = lockForUuid(subnetId);
316 Optional<Subnetmap> sn =
317 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
318 if (!sn.isPresent()) {
319 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
322 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
323 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
324 if (routerId != null) {
325 builder.setRouterId(routerId);
328 builder.setVpnId(vpnId);
330 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
331 builder.setInternetVpnId(internetvpnId);
333 Subnetmap subnetmap = builder.build();
334 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
335 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
337 } catch (ReadFailedException | TransactionCommitFailedException e) {
338 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
345 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
346 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
347 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
348 InstanceIdentifier<Subnetmap> id =
349 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
350 final ReentrantLock lock = lockForUuid(subnetId);
353 Optional<Subnetmap> sn =
354 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
355 if (!sn.isPresent()) {
356 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
357 subnetId.getValue());
360 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
361 subnetId.getValue());
362 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
363 builder.setRouterId(routerId);
364 builder.setRouterInterfacePortId(routerInterfacePortId);
365 builder.setRouterIntfMacAddress(routerIntfMacAddress);
366 builder.setRouterInterfaceFixedIp(fixedIp);
368 builder.setVpnId(vpnId);
370 Subnetmap subnetmap = builder.build();
371 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
372 subnetId.getValue());
373 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
374 } catch (ReadFailedException | TransactionCommitFailedException e) {
375 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
376 subnetId.getValue(), e);
382 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
383 @Nullable Uuid directPortId) {
384 Subnetmap subnetmap = null;
385 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
386 new SubnetmapKey(subnetId)).build();
387 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
388 final ReentrantLock lock = lockForUuid(subnetId);
391 Optional<Subnetmap> sn =
392 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
394 if (sn.isPresent()) {
395 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
396 if (null != portId) {
397 List<Uuid> portList = builder.getPortList();
398 if (null == portList) {
399 portList = new ArrayList<>();
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> directPortList = builder.getDirectPortList();
408 if (null == directPortList) {
409 directPortList = new ArrayList<>();
411 directPortList.add(directPortId);
412 builder.setDirectPortList(directPortList);
413 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
414 directPortId.getValue());
416 subnetmap = builder.build();
417 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
420 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
421 + "cache ", subnetId.getValue(), portId.getValue());
422 unprocessedPortsMap.put(portId, subnetId);
424 } catch (ReadFailedException | TransactionCommitFailedException e) {
425 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
432 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
433 Uuid vpnId, @Nullable Uuid portId) {
434 Subnetmap subnetmap = null;
435 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
436 .child(Subnetmap.class, new SubnetmapKey(subnetId))
438 final ReentrantLock lock = lockForUuid(subnetId);
441 Optional<Subnetmap> sn =
442 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
444 if (sn.isPresent()) {
445 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
446 if (routerId != null) {
447 builder.setRouterId(null);
449 if (networkId != null) {
450 builder.setNetworkId(null);
453 builder.setVpnId(null);
455 builder.setInternetVpnId(null);
456 if (portId != null && builder.getPortList() != null) {
457 List<Uuid> portList = builder.getPortList();
458 portList.remove(portId);
459 builder.setPortList(portList);
462 subnetmap = builder.build();
463 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
464 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
467 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
469 } catch (ReadFailedException | TransactionCommitFailedException e) {
470 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
478 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
479 @Nullable Uuid directPortId) {
480 Subnetmap subnetmap = null;
481 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
482 new SubnetmapKey(subnetId)).build();
483 final ReentrantLock lock = lockForUuid(subnetId);
486 Optional<Subnetmap> sn =
487 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
489 if (sn.isPresent()) {
490 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
491 if (null != portId && null != builder.getPortList()) {
492 List<Uuid> portList = builder.getPortList();
493 portList.remove(portId);
494 builder.setPortList(portList);
495 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
496 subnetId.getValue());
498 if (null != directPortId && null != builder.getDirectPortList()) {
499 List<Uuid> directPortList = builder.getDirectPortList();
500 directPortList.remove(directPortId);
501 builder.setDirectPortList(directPortList);
502 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
503 .getValue(), subnetId.getValue());
505 subnetmap = builder.build();
506 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
509 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
511 } catch (ReadFailedException | TransactionCommitFailedException e) {
512 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
513 subnetId.getValue(), e);
520 // TODO Clean up the exception handling
521 @SuppressWarnings("checkstyle:IllegalCatch")
522 protected void deleteSubnetMapNode(Uuid subnetId) {
523 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
524 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
525 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
526 final ReentrantLock lock = lockForUuid(subnetId);
529 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
530 } catch (TransactionCommitFailedException e) {
531 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
537 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
538 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
539 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
541 Optional<VpnInstance> vpnInstanceConfig =
542 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
544 if (!vpnInstanceConfig.isPresent()) {
545 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
548 VpnInstance vpnInstance = vpnInstanceConfig.get();
549 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
550 if (vpnInstance.getIpv4Family() != null) {
551 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
552 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
554 if (vpnInstance.getIpv6Family() != null) {
555 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
556 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
558 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
559 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
560 updateVpnInstanceBuilder.build());
561 } catch (ReadFailedException | TransactionCommitFailedException ex) {
562 LOG.warn("Error configuring feature ", ex);
566 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
567 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
568 String vpnName = vpnId.getValue();
569 VpnInstanceBuilder builder = null;
570 List<VpnTarget> vpnTargetList = new ArrayList<>();
571 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
572 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
573 Optional<VpnInstance> optionalVpn;
575 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
577 } catch (ReadFailedException e) {
578 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
582 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
583 if (optionalVpn.isPresent()) {
584 builder = new VpnInstanceBuilder(optionalVpn.get());
585 LOG.debug("updating existing vpninstance node");
587 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
588 .setType(type).setL3vni(l3vni);
590 if (irt != null && !irt.isEmpty()) {
591 if (ert != null && !ert.isEmpty()) {
592 List<String> commonRT = new ArrayList<>(irt);
593 commonRT.retainAll(ert);
595 for (String common : commonRT) {
598 VpnTarget vpnTarget =
599 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
600 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
601 vpnTargetList.add(vpnTarget);
604 for (String importRT : irt) {
605 VpnTarget vpnTarget =
606 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
607 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
608 vpnTargetList.add(vpnTarget);
612 if (ert != null && !ert.isEmpty()) {
613 for (String exportRT : ert) {
614 VpnTarget vpnTarget =
615 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
616 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
617 vpnTargetList.add(vpnTarget);
621 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
622 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
623 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
625 if (rd != null && !rd.isEmpty()) {
626 ipv4vpnBuilder.setRouteDistinguisher(rd);
627 ipv6vpnBuilder.setRouteDistinguisher(rd);
630 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
631 builder.setIpv4Family(ipv4vpnBuilder.build());
633 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
634 builder.setIpv6Family(ipv6vpnBuilder.build());
636 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
637 builder.setIpv4Family(ipv4vpnBuilder.build());
639 VpnInstance newVpn = builder.build();
641 try (AcquireResult lock = tryVpnLock(vpnId)) {
642 if (!lock.wasAcquired()) {
643 // FIXME: why do we even bother with locking if we do not honor it?!
644 logTryLockFailure(vpnId);
647 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
649 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
651 } catch (TransactionCommitFailedException e) {
652 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
657 private void deleteVpnMapsNode(Uuid vpnId) {
658 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
659 .child(VpnMap.class, new VpnMapKey(vpnId))
661 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
662 try (AcquireResult lock = tryVpnLock(vpnId)) {
663 if (!lock.wasAcquired()) {
664 // FIXME: why do we even bother with locking if we do not honor it?!
665 logTryLockFailure(vpnId);
669 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
671 } catch (TransactionCommitFailedException e) {
672 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
677 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
678 @Nullable List<Uuid> networks) {
679 VpnMapBuilder builder;
680 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
681 .child(VpnMap.class, new VpnMapKey(vpnId))
684 Optional<VpnMap> optionalVpnMap =
685 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
687 if (optionalVpnMap.isPresent()) {
688 builder = new VpnMapBuilder(optionalVpnMap.get());
690 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
694 builder.setName(name);
696 if (tenantId != null) {
697 builder.setTenantId(tenantId);
699 if (router != null) {
700 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
701 List<RouterIds> rtrIds = builder.getRouterIds();
702 if (rtrIds == null) {
703 rtrIds = Collections.singletonList(vpnRouterId);
705 rtrIds.add(vpnRouterId);
707 builder.setRouterIds(rtrIds);
709 if (networks != null) {
710 List<Uuid> nwList = builder.getNetworkIds();
711 if (nwList == null) {
712 nwList = new ArrayList<>();
714 nwList.addAll(networks);
715 builder.setNetworkIds(nwList);
718 try (AcquireResult lock = tryVpnLock(vpnId)) {
719 if (!lock.wasAcquired()) {
720 // FIXME: why do we even bother with locking if we do not honor it?!
721 logTryLockFailure(vpnId);
724 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
725 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
727 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
729 } catch (ReadFailedException | TransactionCommitFailedException e) {
730 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
734 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
735 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
736 .child(VpnMap.class, new VpnMapKey(vpnId))
738 Optional<VpnMap> optionalVpnMap;
741 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
743 } catch (ReadFailedException e) {
744 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
747 if (optionalVpnMap.isPresent()) {
748 VpnMap vpnMap = optionalVpnMap.get();
749 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
750 List<RouterIds> rtrIds = vpnMap.getRouterIds();
751 if (rtrIds == null) {
752 rtrIds = new ArrayList<>();
754 if (routerId != null) {
755 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
756 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
757 vpnMapBuilder.setRouterIds(rtrIds);
759 try (AcquireResult lock = tryVpnLock(vpnId)) {
760 if (!lock.wasAcquired()) {
761 // FIXME: why do we even bother with locking if we do not honor it?!
762 logTryLockFailure(vpnId);
765 LOG.debug("removing vpnMaps node: {} ", vpnId);
767 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
769 } catch (TransactionCommitFailedException e) {
770 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
774 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
775 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
776 vpnMapBuilder.setRouterIds(rtrIds);
777 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
780 if (networkIds != null) {
781 List<Uuid> vpnNw = vpnMap.getNetworkIds();
782 vpnNw.removeAll(networkIds);
783 if (vpnNw.isEmpty()) {
784 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
785 vpnMapBuilder.setNetworkIds(null);
787 vpnMapBuilder.setNetworkIds(vpnNw);
791 try (AcquireResult lock = tryVpnLock(vpnId)) {
792 if (!lock.wasAcquired()) {
793 // FIXME: why do we even bother with locking if we do not honor it?!
794 logTryLockFailure(vpnId);
797 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
799 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
800 vpnMapIdentifier, vpnMapBuilder.build());
801 } catch (TransactionCommitFailedException e) {
802 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
806 LOG.error("VPN : {} not found", vpnId.getValue());
808 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
811 private void deleteVpnInstance(Uuid vpnId) {
812 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
813 .child(VpnInstance.class,
814 new VpnInstanceKey(vpnId.getValue()))
817 try (AcquireResult lock = tryVpnLock(vpnId)) {
818 if (!lock.wasAcquired()) {
819 // FIXME: why do we even bother with locking if we do not honor it?!
820 logTryLockFailure(vpnId);
823 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
825 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
826 } catch (TransactionCommitFailedException e) {
827 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
832 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
833 TypedWriteTransaction<Configuration> wrtConfigTxn,
834 @Nullable VpnInterface vpnIface) {
835 List<Adjacency> adjList = new ArrayList<>();
836 if (vpnIface != null) {
837 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
839 String infName = port.getUuid().getValue();
840 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
841 for (FixedIps ip : port.nonnullFixedIps()) {
842 String ipValue = ip.getIpAddress().stringValue();
843 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
844 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
845 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
846 snTemp.getSubnetIp(), false)) {
849 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
851 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
852 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
853 //Create Neutron port adjacency if VPN presence is existing for subnet
854 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
855 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
856 .setSubnetId(ip.getSubnetId()).build();
857 if (!adjList.contains(vmAdj)) {
861 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
862 if (snTemp != null && snTemp.getInternetVpnId() != null) {
863 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
864 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
866 if (routerId != null) {
867 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
868 if (rtr != null && rtr.getRoutes() != null) {
869 List<Routes> routeList = rtr.getRoutes();
870 // create extraroute Adjacence for each ipValue,
871 // because router can have IPv4 and IPv6 subnet ports, or can have
872 // more that one IPv4 subnet port or more than one IPv6 subnet port
873 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
874 if (!erAdjList.isEmpty()) {
875 adjList.addAll(erAdjList);
880 return new AdjacenciesBuilder().setAdjacency(adjList).build();
883 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
884 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
885 boolean isRouterInterface = false;
886 if (port.getDeviceOwner() != null) {
887 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
889 String infName = port.getUuid().getValue();
890 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
891 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
892 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
893 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
894 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
897 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
898 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
899 String infName = port.getUuid().getValue();
900 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
901 Optional<VpnInterface> optionalVpnInterface = null;
902 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
903 vpnId, internetVpnId, infName);
905 optionalVpnInterface = SingleTransactionDataBroker
906 .syncReadOptional(dataBroker, LogicalDatastoreType
907 .CONFIGURATION, vpnIfIdentifier);
908 } catch (ReadFailedException e) {
909 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
912 if (!optionalVpnInterface.isPresent()) {
915 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
916 sn != null ? sn.getSubnetIp() : "null");
917 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
918 List<Adjacency> updatedAdjsList = new ArrayList<>();
919 boolean isIpFromAnotherSubnet = false;
920 for (Adjacency adj : vpnAdjsList) {
921 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
922 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
923 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
924 isIpFromAnotherSubnet = true;
926 updatedAdjsList.add(adj);
929 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
930 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
933 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
934 String.valueOf(adjString), wrtConfigTxn);
936 if (internetVpnId != null) {
937 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
938 String.valueOf(adjString), wrtConfigTxn);
941 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
942 && sn.getRouterId() != null) {
943 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
944 if (rtr != null && rtr.getRoutes() != null) {
945 List<Routes> extraRoutesToRemove = new ArrayList<>();
946 for (Routes rt: rtr.getRoutes()) {
947 if (rt.getNexthop().toString().equals(adjString)) {
948 extraRoutesToRemove.add(rt);
952 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
953 extraRoutesToRemove, vpnId);
954 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
956 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
961 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
963 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
965 if (!isIpFromAnotherSubnet) {
966 // no more subnetworks for neutron port
967 if (sn != null && sn.getRouterId() != null) {
968 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
970 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
976 // TODO Clean up the exception handling
977 @SuppressWarnings("checkstyle:IllegalCatch")
978 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
979 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
980 if (wrtConfigTxn == null) {
981 ListenableFutures.addErrorLogging(
982 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
983 tx -> deleteVpnInterface(infName, vpnId, tx)),
984 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
988 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
989 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
990 Optional<VpnInterface> optionalVpnInterface;
992 optionalVpnInterface =
993 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
995 } catch (ReadFailedException ex) {
996 LOG.error("Error during deletion of vpninterface {}", infName, ex);
999 if (!optionalVpnInterface.isPresent()) {
1000 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
1003 if (vpnId != null) {
1004 VpnInterface vpnInterface = optionalVpnInterface.get();
1005 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
1007 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
1008 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
1009 if (!vpnList.isEmpty()) {
1010 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1011 + "List not empty", infName);
1014 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1015 .setVpnInstanceNames(vpnList);
1016 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1020 LOG.debug("Deleting vpn interface {}", infName);
1021 wrtConfigTxn.delete(vpnIfIdentifier);
1024 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1025 TypedWriteTransaction<Configuration> writeConfigTxn,
1027 if (vpnId == null || port == null) {
1030 String infName = port.getUuid().getValue();
1031 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1033 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1034 .syncReadOptional(dataBroker, LogicalDatastoreType
1035 .CONFIGURATION, vpnIfIdentifier);
1036 if (optionalVpnInterface.isPresent()) {
1037 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1039 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1040 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1042 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1043 .setVpnInstanceNames(listVpn);
1044 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1045 LOG.debug("Updating vpn interface {}", infName);
1046 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1047 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1048 while (adjacencyIter.hasNext()) {
1049 Adjacency adjacency = adjacencyIter.next();
1050 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1053 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1054 InstanceIdentifier<LearntVpnVipToPort> id =
1055 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1056 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1057 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1058 LogicalDatastoreType.OPERATIONAL, id);
1059 if (optionalVpnVipToPort.isPresent()) {
1060 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1062 if (listVpn == null || listVpn.isEmpty()) {
1063 adjacencyIter.remove();
1065 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1066 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1067 mipToQuery, infName, vpnId.getValue());
1070 for (FixedIps ip : port.nonnullFixedIps()) {
1071 String ipValue = ip.getIpAddress().stringValue();
1073 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1076 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1077 ipValue, writeConfigTxn);
1079 if (listVpn == null || listVpn.isEmpty()) {
1080 if (sm != null && sm.getRouterId() != null) {
1081 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1083 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1085 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1088 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1090 } catch (ReadFailedException ex) {
1091 LOG.error("Update of vpninterface {} failed", infName, ex);
1095 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1097 TypedWriteTransaction<Configuration> writeConfigTxn,
1098 boolean isInternetVpn) {
1099 if (vpnId == null || port == null) {
1102 String infName = port.getUuid().getValue();
1103 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1105 try (AcquireResult lock = tryInterfaceLock(infName)) {
1106 if (!lock.wasAcquired()) {
1107 // FIXME: why do we even bother with locking if we do not honor it?!
1108 logTryLockFailure(infName);
1112 Optional<VpnInterface> optionalVpnInterface =
1113 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1115 if (optionalVpnInterface.isPresent()) {
1116 VpnInstanceNames vpnInstance = VpnHelper
1117 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1118 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1119 .get().getVpnInstanceNames());
1120 if (oldVpnId != null
1121 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1122 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1124 if (vpnId.getValue() != null
1125 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1126 listVpn.add(vpnInstance);
1128 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1129 .setVpnInstanceNames(listVpn);
1130 LOG.debug("Updating vpn interface {}", infName);
1131 if (!isBeingAssociated) {
1132 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1133 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1134 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1135 while (adjacencyIter.hasNext()) {
1136 Adjacency adjacency = adjacencyIter.next();
1137 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1138 InstanceIdentifier<LearntVpnVipToPort> id =
1139 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1140 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1141 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1142 LogicalDatastoreType.OPERATIONAL, id);
1143 if (optionalVpnVipToPort.isPresent()
1144 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1145 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1146 + "from VPN {}", infName, vpnId, oldVpnId);
1147 adjacencyIter.remove();
1148 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1150 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1151 mipToQuery, infName, vpnId.getValue());
1153 InstanceIdentifier<VpnPortipToPort> build =
1154 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1155 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1156 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1157 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1158 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1159 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1160 mipToQuery, infName, vpnId.getValue());
1163 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1164 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1166 for (FixedIps ip : port.nonnullFixedIps()) {
1167 String ipValue = ip.getIpAddress().stringValue();
1168 if (oldVpnId != null) {
1169 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1170 ipValue, writeConfigTxn);
1172 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1173 && isInternetVpn == true) {
1177 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1178 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1180 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1182 LOG.error("VPN Interface {} not found", infName);
1184 } catch (ReadFailedException ex) {
1185 LOG.error("Updation of vpninterface {} failed", infName, ex);
1190 public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List<String> rd,
1191 @Nullable List<String> irt, @Nullable List<String> ert, @Nullable Uuid router,
1192 @Nullable List<Uuid> networks) {
1194 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1196 // Update VPN Instance node
1197 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1199 // Update local vpn-subnet DS
1200 updateVpnMaps(vpn, name, router, tenant, networks);
1202 if (router != null) {
1203 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1204 if (existingVpn != null) {
1205 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1206 // if before reboot, router was already associated to VPN, should not proceed associating router to
1207 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1208 // preserved upon reboot.
1209 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1210 // RouterInterfacesMap via #createVPNInterface call.
1211 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1212 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1215 associateRouterToInternalVpn(vpn, router);
1220 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1221 * specified Neutron Networks and Routers.
1223 * @param vpnId Uuid of the VPN tp be created
1224 * @param name Representative name of the new VPN
1225 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1226 * @param rdList Route-distinguisher for the VPN
1227 * @param irtList A list of Import Route Targets
1228 * @param ertList A list of Export Route Targets
1229 * @param routerIdsList ist of neutron router Id to associate with created VPN
1230 * @param networkList UUID of the neutron network the VPN may be associated to
1231 * @param type Type of the VPN Instance
1232 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1233 * @throws Exception if association of L3VPN failed
1235 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1236 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1237 VpnInstance.Type type, long l3vni) throws Exception {
1239 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1241 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1242 for (Uuid routerId : routerIdsList) {
1243 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1244 ipVersChoices = ipVersChoices.addVersion(vers);
1247 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1249 // Please note that router and networks will be filled into VPNMaps
1250 // by subsequent calls here to associateRouterToVpn and
1251 // associateNetworksToVpn
1252 updateVpnMaps(vpnId, name, null, tenantId, null);
1253 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1254 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1257 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1258 for (Uuid routerId : routerIdsList) {
1259 associateRouterToVpn(vpnId, routerId);
1262 if (networkList != null) {
1263 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1264 if (!failStrings.isEmpty()) {
1265 LOG.error("VPN {} association to networks failed for networks: {}. ",
1266 vpnId.getValue(), failStrings.toString());
1267 throw new Exception(failStrings.toString());
1273 * It handles the invocations to the createVPN RPC method.
1276 // TODO Clean up the exception handling
1277 @SuppressWarnings("checkstyle:IllegalCatch")
1278 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1280 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1281 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1282 List<RpcError> errorList = new ArrayList<>();
1283 int failurecount = 0;
1284 int warningcount = 0;
1286 List<L3vpn> vpns = input.getL3vpn();
1288 vpns = Collections.emptyList();
1290 for (L3vpn vpn : vpns) {
1291 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1292 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1293 formatAndLog(LOG::warn,
1294 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1295 vpn.getId().getValue())));
1299 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1300 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1301 formatAndLog(LOG::warn,
1302 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1303 vpn.getId().getValue())));
1307 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1309 if (vpn.getL3vni() != null) {
1310 l3vni = vpn.getL3vni().toJava();
1313 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1314 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1315 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1316 formatAndLog(LOG::warn,
1317 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1318 + "is already configured",
1319 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1323 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1324 if (operationalVpn.isPresent()) {
1325 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1326 formatAndLog(LOG::error,
1327 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1328 + "is still available. Please retry creation of a new vpn with the same RD"
1329 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1330 vpn.getRouteDistinguisher().get(0))));
1334 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1335 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1336 routerIdsList = vpn.getRouterIds();
1337 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1338 routerId : routerIdsList) {
1339 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1340 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1341 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1342 + "{}", vpn.getId(), routerId.getRouterId())));
1346 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1347 if (vpnId != null) {
1348 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1349 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1350 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1351 vpnId.getValue())));
1357 if (vpn.getNetworkIds() != null) {
1358 int initialWarningCount = warningcount;
1359 for (Uuid nw : vpn.getNetworkIds()) {
1360 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1361 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1362 if (network == null) {
1363 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1364 formatAndLog(LOG::warn,
1365 "Creation of L3VPN failed for VPN {} due to network not found {}",
1366 vpn.getId().getValue(), nw.getValue())));
1368 } else if (vpnId != null) {
1369 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1370 formatAndLog(LOG::warn,
1371 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1372 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1373 vpnId.getValue())));
1377 if (warningcount != initialWarningCount) {
1381 List<Uuid> rtrIdsList = new ArrayList<>();
1382 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1383 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1384 rtrId : vpn.getRouterIds()) {
1385 rtrIdsList.add(rtrId.getRouterId());
1389 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1390 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1391 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1392 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1393 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1394 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1395 vpnInstanceType, l3vni);
1396 } catch (Exception ex) {
1397 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1398 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1403 // if at least one succeeds; result is success
1404 // if none succeeds; result is failure
1405 if (failurecount + warningcount == vpns.size()) {
1406 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1408 List<String> errorResponseList = new ArrayList<>();
1409 if (!errorList.isEmpty()) {
1410 for (RpcError rpcError : errorList) {
1411 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1412 + ", ErrorMessage: " + rpcError.getMessage());
1415 errorResponseList.add("Operation successful with no errors");
1417 opBuilder.setResponse(errorResponseList);
1418 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1424 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1427 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1429 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1430 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1431 Uuid inputVpnId = input.getId();
1432 List<VpnInstance> vpns = new ArrayList<>();
1433 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1436 if (inputVpnId == null) {
1438 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1440 Optional<VpnInstances> optionalVpns =
1441 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1443 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1444 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1445 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1446 // from getL3VPN output
1447 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1450 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1456 opBuilder.setL3vpnInstances(l3vpnList);
1457 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1461 String name = inputVpnId.getValue();
1462 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1463 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1464 // read VpnInstance Info
1465 Optional<VpnInstance> optionalVpn =
1466 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1468 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1470 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1471 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1472 vpns.add(optionalVpn.get());
1475 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1476 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1480 for (VpnInstance vpnInstance : vpns) {
1481 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1482 // create VpnMaps id
1483 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1484 List<String> rd = Collections.EMPTY_LIST;
1485 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1486 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1487 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1488 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1490 List<String> ertList = new ArrayList<>();
1491 List<String> irtList = new ArrayList<>();
1493 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1494 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1495 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1496 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1497 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1498 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1499 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1501 if (!vpnTargetList.isEmpty()) {
1502 for (VpnTarget vpnTarget : vpnTargetList) {
1503 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1504 ertList.add(vpnTarget.getVrfRTValue());
1506 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1507 irtList.add(vpnTarget.getVrfRTValue());
1509 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1510 ertList.add(vpnTarget.getVrfRTValue());
1511 irtList.add(vpnTarget.getVrfRTValue());
1517 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1519 if (vpnInstance.getL3vni() != null) {
1520 l3vpn.setL3vni(vpnInstance.getL3vni());
1522 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1523 .class, new VpnMapKey(vpnId)).build();
1524 Optional<VpnMap> optionalVpnMap =
1525 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1527 if (optionalVpnMap.isPresent()) {
1528 VpnMap vpnMap = optionalVpnMap.get();
1529 List<Uuid> rtrIds = new ArrayList<>();
1530 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1531 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1532 rtrIds.add(rtrId.getRouterId());
1535 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1536 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1537 .setName(vpnMap.getName());
1540 l3vpnList.add(l3vpn.build());
1543 opBuilder.setL3vpnInstances(l3vpnList);
1544 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1546 } catch (ReadFailedException ex) {
1547 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1548 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1554 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1557 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1559 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1560 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1561 List<RpcError> errorList = new ArrayList<>();
1563 int failurecount = 0;
1564 int warningcount = 0;
1565 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1566 for (Uuid vpn : vpns) {
1568 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1569 InstanceIdentifier<VpnInstance> vpnIdentifier =
1570 InstanceIdentifier.builder(VpnInstances.class)
1571 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1572 Optional<VpnInstance> optionalVpn =
1573 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1575 if (optionalVpn.isPresent()) {
1578 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1579 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1582 } catch (ReadFailedException ex) {
1583 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1584 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1589 // if at least one succeeds; result is success
1590 // if none succeeds; result is failure
1591 if (failurecount + warningcount == vpns.size()) {
1592 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1594 List<String> errorResponseList = new ArrayList<>();
1595 if (!errorList.isEmpty()) {
1596 for (RpcError rpcError : errorList) {
1597 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1598 + ", ErrorMessage: " + rpcError.getMessage());
1601 errorResponseList.add("Operation successful with no errors");
1603 opBuilder.setResponse(errorResponseList);
1604 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1609 public void createVpnInstanceForSubnet(Uuid subnetId) {
1610 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1611 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1614 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1615 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1616 removeVpn(subnetId);
1619 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1620 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1621 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1622 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1624 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1625 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1628 if (vpnId != null) {
1629 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1630 if (vpnMap == null) {
1631 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1632 + " cannot add subnet {} to VPN", vpnId.getValue(),
1636 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1637 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1638 if (isVpnOfTypeL2(vpnInstance)) {
1639 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1640 NeutronEvpnUtils.Operation.ADD);
1643 if (internetVpnId != null) {
1644 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1645 if (vpnMap == null) {
1646 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1647 + "subnet {} to VPN", internetVpnId.getValue(),
1652 final Uuid internetId = internetVpnId;
1653 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1654 List<Uuid> portList = sn.getPortList();
1655 if (portList != null) {
1656 for (final Uuid portId : portList) {
1657 String vpnInfName = portId.getValue();
1658 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1659 Port port = neutronvpnUtils.getNeutronPort(portId);
1661 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1662 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1665 final Boolean isRouterInterface = port.getDeviceOwner()
1666 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1667 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1668 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1669 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1671 if (vpnIface == null) {
1672 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1673 Set<Uuid> listVpn = new HashSet<>();
1674 if (vpnId != null) {
1677 if (internetId != null) {
1678 listVpn.add(internetId);
1680 writeVpnInterfaceToDs(listVpn,
1681 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1682 if (sn.getRouterId() != null) {
1683 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1686 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1687 if (vpnId != null) {
1688 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1690 if (internetId != null) {
1691 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1700 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1701 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1702 "removeSubnetFromVpn: at least one VPN must be not null");
1703 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1704 vpnId, internetVpnId);
1705 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1707 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1710 VpnMap vpnMap = null;
1711 VpnInstance vpnInstance = null;
1712 if (vpnId != null) {
1713 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1714 if (vpnMap == null) {
1715 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1716 vpnId.getValue(), subnet.getValue());
1719 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1721 if (internetVpnId == null) {
1722 internetVpnId = sn.getInternetVpnId();
1724 if (internetVpnId != null) {
1725 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1726 if (vpnMap == null) {
1727 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1728 + " from Internet VPN",
1729 internetVpnId.getValue(), subnet.getValue());
1733 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1734 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1735 NeutronEvpnUtils.Operation.DELETE);
1737 boolean subnetVpnAssociation = false;
1738 if (vpnId != null && sn.getVpnId() != null
1739 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1740 subnetVpnAssociation = true;
1741 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1742 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1743 subnetVpnAssociation = true;
1745 if (subnetVpnAssociation == false) {
1746 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1747 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1750 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1751 List<Uuid> portList = sn.getPortList();
1752 final Uuid internetId = internetVpnId;
1753 if (portList != null) {
1754 for (final Uuid portId : portList) {
1755 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1756 final Port port = neutronvpnUtils.getNeutronPort(portId);
1757 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1758 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1759 CONFIGURATION, tx -> {
1761 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1764 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1765 + "port is absent in Neutron config DS", portId.getValue(),
1771 //update subnet-vpn association
1772 removeFromSubnetNode(subnet, null, null, vpnId, null);
1775 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1776 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1777 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1779 Uuid internalVpnId = sm.getVpnId();
1780 if (internalVpnId == null) {
1781 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1782 sm.getId().getValue());
1785 if (isBeingAssociated) {
1786 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1788 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1791 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1792 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1793 if (isBeingAssociated) {
1794 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1795 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1797 removeInternetVpnFromVpnInterface(vpn,
1798 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1803 // Check for ports on this subnet and update association of
1804 // corresponding vpn-interfaces to internet vpn
1805 List<Uuid> portList = sm.getPortList();
1806 if (portList != null) {
1807 for (Uuid port : portList) {
1808 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1809 port.getValue(), isBeingAssociated);
1810 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1811 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1813 if (isBeingAssociated) {
1814 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1815 true, false, tx, true);
1817 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1825 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1826 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1827 oldVpnId.getValue(), newVpnId.getValue());
1828 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1829 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1830 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1831 Uuid vpnExtUuid = netIsExternal ? null
1832 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1833 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1835 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1838 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1839 * associated with internet BGP-VPN.
1841 if (vpnExtUuid != null) {
1842 /* Update V6 Internet default route match with new VPN metadata.
1843 * isBeingAssociated = true means oldVpnId is same as routerId
1844 * isBeingAssociated = false means newVpnId is same as routerId
1846 if (isBeingAssociated) {
1847 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1849 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1852 //Update Router Interface first synchronously.
1853 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1854 ListenableFuture<Void> future =
1855 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1856 tx -> updateVpnInterface(newVpnId, oldVpnId,
1857 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1858 isBeingAssociated, true, tx, false));
1859 Futures.addCallback(future, new FutureCallback<Void>() {
1861 public void onSuccess(Void result) {
1862 // Check for ports on this subnet and update association of
1863 // corresponding vpn-interfaces to external vpn
1864 List<Uuid> portList = sn.getPortList();
1865 if (portList != null) {
1866 for (Uuid port : portList) {
1867 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1868 port.getValue(), isBeingAssociated);
1869 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1870 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1871 tx -> updateVpnInterface(newVpnId, oldVpnId,
1872 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1879 public void onFailure(Throwable throwable) {
1881 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1883 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1885 }, MoreExecutors.directExecutor());
1890 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1891 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1892 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1895 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1896 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1897 final ReentrantLock lock = lockForUuid(routerId);
1900 Optional<RouterInterfaces> optRouterInterfaces =
1901 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1902 routerInterfacesId);
1903 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1904 .setInterfaceId(interfaceName).build();
1905 if (optRouterInterfaces.isPresent()) {
1906 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1907 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1909 // TODO Shouldn't we be doing something with builder and interfaces?
1910 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1911 // List<Interfaces> interfaces = new ArrayList<>();
1912 // interfaces.add(routerInterface);
1914 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1915 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1917 } catch (ReadFailedException | TransactionCommitFailedException e) {
1918 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1924 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1925 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1926 final ReentrantLock lock = lockForUuid(routerId);
1929 Optional<RouterInterfaces> optRouterInterfaces =
1930 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1931 routerInterfacesId);
1932 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1933 .setInterfaceId(interfaceName).build();
1934 if (optRouterInterfaces.isPresent()) {
1935 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1936 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1937 if (interfaces != null && interfaces.remove(routerInterface)) {
1938 if (interfaces.isEmpty()) {
1939 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1940 routerInterfacesId);
1942 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1943 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1947 } catch (ReadFailedException | TransactionCommitFailedException e) {
1948 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1955 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1956 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1957 * route will be ignored.
1959 * @param vpnName the VPN identifier
1960 * @param interVpnLinkRoutes The list of static routes
1961 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1963 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1964 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1965 for (Routes route : interVpnLinkRoutes) {
1966 String nexthop = route.getNexthop().stringValue();
1967 String destination = route.getDestination().stringValue();
1968 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1969 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1970 AddStaticRouteInput rpcInput =
1971 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1972 .setVpnInstanceName(vpnName.getValue())
1974 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1975 RpcResult<AddStaticRouteOutput> rpcResult;
1977 rpcResult = labelOuputFtr.get();
1978 if (rpcResult.isSuccessful()) {
1979 LOG.debug("Label generated for destination {} is: {}",
1980 destination, rpcResult.getResult().getLabel());
1982 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1983 destination, nexthop, rpcResult.getErrors());
1985 } catch (InterruptedException | ExecutionException e) {
1986 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1987 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1990 // Any other case is a fault.
1991 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1992 route.getDestination().stringValue(), nexthop);
1999 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2000 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2002 * @param vpnName the VPN identifier
2003 * @param interVpnLinkRoutes The list of static routes
2004 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2006 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2007 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2008 for (Routes route : interVpnLinkRoutes) {
2009 String nexthop = route.getNexthop().stringValue();
2010 String destination = route.getDestination().stringValue();
2011 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2012 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2013 RemoveStaticRouteInput rpcInput =
2014 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2015 .setVpnInstanceName(vpnName.getValue())
2018 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2019 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2021 // Any other case is a fault.
2022 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2023 route.getDestination().stringValue(), nexthop);
2030 * Returns true if the specified nexthop is the other endpoint in an
2031 * InterVpnLink, regarding one of the VPN's point of view.
2033 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2034 InterVpnLink interVpnLink) {
2036 interVpnLink != null
2037 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2038 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2039 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2040 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2044 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2045 List<Adjacency> adjList = new ArrayList<>();
2046 Map<String, List<String>> adjMap = new HashMap<>();
2047 for (Routes route : routeList) {
2048 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2049 LOG.error("Incorrect input received for extra route. {}", route);
2051 String nextHop = route.getNexthop().stringValue();
2052 String destination = route.getDestination().stringValue();
2053 if (!nextHop.equals(fixedIp)) {
2054 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2057 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2059 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2060 if (!hops.contains(nextHop)) {
2066 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2067 final String destination = entry.getKey();
2068 final List<String> ipList = entry.getValue();
2069 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2070 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2071 .withKey(new AdjacencyKey(destination)).build();
2077 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2078 checkAlarmExtraRoutes(vpnId, routeList);
2080 for (Routes route : routeList) {
2081 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2082 LOG.error("Incorrect input received for extra route. {}", route);
2084 String nextHop = route.getNexthop().stringValue();
2085 String destination = route.getDestination().stringValue();
2086 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2088 if (infName != null) {
2089 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2090 destination, vpnId.getValue(), nextHop, infName);
2091 boolean isLockAcquired = false;
2093 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2094 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2095 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2096 .child(Adjacency.class, new AdjacencyKey(destination));
2097 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2098 LogicalDatastoreType.CONFIGURATION, path);
2099 if (existingAdjacency.isPresent()
2100 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2101 LOG.error("The route with destination {} nextHop {} is already present as"
2102 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2103 destination, nextHop, infName);
2106 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2107 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2108 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2110 try (AcquireResult lock = tryInterfaceLock(infName)) {
2111 if (!lock.wasAcquired()) {
2112 // FIXME: why do we even bother with locking if we do not honor it?!
2113 logTryLockFailure(infName);
2116 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2119 } catch (TransactionCommitFailedException e) {
2120 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2121 destination, nextHop, e);
2122 } catch (ReadFailedException e) {
2123 LOG.error("Exception on reading data-store ", e);
2126 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2127 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2134 * This method setup or down an alarm about extra route fault.
2135 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2136 * available RDs, then an alarm and an error is generated.<br>
2137 * <b>Be careful</b> the routeList could be changed.
2139 * @param vpnId the vpnId of vpn to control.
2140 * @param routeList the list of router to check, it could be modified.
2142 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2143 if (!neutronvpnAlarm.isAlarmEnabled()) {
2144 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2147 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2148 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2149 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2153 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2154 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2155 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2159 for (Routes route : routeList) {
2160 // count the number of nexthops for each same route.getDestingation().getValue()
2161 String destination = route.getDestination().stringValue();
2162 String nextHop = route.getNexthop().stringValue();
2163 List<String> nextHopList = new ArrayList<>();
2164 nextHopList.add(nextHop);
2166 for (Routes routeTmp : routeList) {
2167 String routeDest = routeTmp.getDestination().stringValue();
2168 if (!destination.equals(routeDest)) {
2171 String routeNextH = routeTmp.getNexthop().stringValue();
2172 if (nextHop.equals(routeNextH)) {
2176 nextHopList.add(routeTmp.getNexthop().stringValue());
2178 final List<String> rdList = new ArrayList<>();
2179 if (vpnInstance.getIpv4Family() != null
2180 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2181 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2187 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2188 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2189 if (rd != null && !rdList.contains(rd)) {
2194 // 1. VPN Instance Name
2195 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2198 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2199 Uuid routerUuid = routerUuidList.get(0);
2200 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2201 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2203 // 3. List of RDs associated with the VPN
2204 detailsAlarm.append(" List of RDs associated with the VPN: ");
2205 for (String s : rdList) {
2206 detailsAlarm.append(s);
2207 detailsAlarm.append(", ");
2210 // 4. Prefix in question
2211 detailsAlarm.append(" for prefix: ");
2212 detailsAlarm.append(route.getDestination().stringValue());
2214 // 5. List of NHs for the prefix
2215 detailsAlarm.append(" for nextHops: ");
2216 for (String s : nextHopList) {
2217 detailsAlarm.append(s);
2218 detailsAlarm.append(", ");
2221 if (rdList.size() < nbNextHops) {
2222 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2224 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2229 // TODO Clean up the exception handling
2230 @SuppressWarnings("checkstyle:IllegalCatch")
2231 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2232 for (Routes route : routeList) {
2233 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2234 String nextHop = route.getNexthop().stringValue();
2235 String destination = route.getDestination().stringValue();
2236 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2238 if (infName == null) {
2239 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2240 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2241 // Proceed to remove the next extra-route
2244 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2245 destination, vpnId.getValue(), nextHop, infName);
2247 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2248 InstanceIdentifier.builder(VpnInterfaces.class)
2249 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2250 .augmentation(Adjacencies.class)
2251 .child(Adjacency.class, new AdjacencyKey(destination))
2255 // Looking for existing prefix in MDSAL database
2256 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2257 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2258 boolean updateNextHops = false;
2259 List<String> nextHopList = new ArrayList<>();
2260 if (adjacency.isPresent()) {
2261 List<String> nhListRead = adjacency.get().getNextHopIpList();
2262 if (nhListRead.size() > 1) { // ECMP case
2263 for (String nextHopRead : nhListRead) {
2264 if (nextHopRead.equals(nextHop)) {
2265 updateNextHops = true;
2267 nextHopList.add(nextHopRead);
2273 try (AcquireResult lock = tryInterfaceLock(infName)) {
2274 if (!lock.wasAcquired()) {
2275 // FIXME: why do we even bother with locking if we do not honor it?!
2276 logTryLockFailure(infName);
2279 if (updateNextHops) {
2280 // An update must be done, not including the current next hop
2281 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2282 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2283 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2284 .setNextHopIpList(nextHopList)
2285 .withKey(new AdjacencyKey(destination))
2287 Adjacencies erAdjs =
2288 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2289 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2290 .addAugmentation(Adjacencies.class, erAdjs).build();
2291 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2292 vpnIfIdentifier, vpnIf);
2294 // Remove the whole route
2295 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2296 adjacencyIdentifier);
2297 LOG.trace("extra route {} deleted successfully", route);
2300 } catch (TransactionCommitFailedException | ReadFailedException e) {
2301 LOG.error("exception in deleting extra route with destination {} for interface {}",
2302 destination, infName, e);
2305 LOG.error("Incorrect input received for extra route: {}", route);
2310 public void removeVpn(Uuid vpnId) {
2312 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2313 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2314 List<Uuid> routerUuidList = new ArrayList<>();
2315 // dissociate router
2316 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2317 for (RouterIds router : routerIdsList) {
2318 Uuid routerId = router.getRouterId();
2319 routerUuidList.add(routerId);
2320 dissociateRouterFromVpn(vpnId, routerId);
2323 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2324 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2326 // remove entire vpnMaps node
2327 deleteVpnMapsNode(vpnId);
2329 // remove vpn-instance
2330 deleteVpnInstance(vpnId);
2331 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2334 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2335 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2338 // TODO Clean up the exception handling
2339 @SuppressWarnings("checkstyle:IllegalCatch")
2340 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2341 updateVpnMaps(vpnId, null, routerId, null, null);
2342 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2343 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2344 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2345 for (Subnetmap sn : subMapList) {
2346 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2347 if (!ipVersion.isIpVersionChosen(ipVers)) {
2348 ipVersion = ipVersion.addVersion(ipVers);
2351 if (ipVersion != IpVersionChoice.UNDEFINED) {
2352 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2354 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2356 for (Subnetmap sn : subMapList) {
2357 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2361 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2362 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2363 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2364 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2365 for (Uuid subnet : routerSubnets) {
2366 IpVersionChoice version = NeutronvpnUtils
2367 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2368 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2369 addSubnetToVpn(vpnId, subnet, null);
2371 addSubnetToVpn(vpnId, subnet, internetVpnId);
2376 // TODO Clean up the exception handling
2377 @SuppressWarnings("checkstyle:IllegalCatch")
2378 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2380 clearFromVpnMaps(vpnId, routerId, null);
2381 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2382 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2383 for (Subnetmap sn : subMapList) {
2384 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2385 if (ipVersion.isIpVersionChosen(ipVers)) {
2386 ipVersion = ipVersion.addVersion(ipVers);
2388 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2389 routerId.getValue());
2390 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2392 if (ipVersion != IpVersionChoice.UNDEFINED) {
2393 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2395 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2401 * Parses and associates networks list with given VPN.
2403 * @param vpnId Uuid of given VPN.
2404 * @param networkList List list of network Ids (Uuid), which will be associated.
2405 * @return list of formatted strings with detailed error messages.
2408 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2409 List<String> failedNwList = new ArrayList<>();
2410 HashSet<Uuid> passedNwList = new HashSet<>();
2411 boolean isExternalNetwork = false;
2412 if (networkList.isEmpty()) {
2413 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2414 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2416 return failedNwList;
2418 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2419 if (vpnInstance == null) {
2420 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2421 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2422 + "in ConfigDS", vpnId.getValue()));
2423 return failedNwList;
2426 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2427 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2429 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2430 + "associated with", vpnId.getValue()));
2431 return failedNwList;
2433 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2434 for (Uuid nw : networkList) {
2435 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2436 if (network == null) {
2437 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2438 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2442 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2443 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2444 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2445 nw.getValue(), vpnId.getValue());
2446 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2447 nw.getValue(), vpnId.getValue()));
2450 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2451 if (networkVpnId != null) {
2452 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2453 nw.getValue(), networkVpnId.getValue());
2454 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2455 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2458 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2459 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2460 nw.getValue(), vpnId.getValue());
2461 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2462 nw.getValue(), vpnId.getValue()));
2465 if (NeutronvpnUtils.getIsExternal(network)) {
2466 isExternalNetwork = true;
2468 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2469 if (subnetmapList == null || subnetmapList.isEmpty()) {
2470 passedNwList.add(nw);
2473 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2476 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2477 for (Subnetmap subnetmap : subnetmapList) {
2478 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2479 if (!ipVersion.isIpVersionChosen(ipVers)) {
2480 ipVersion = ipVersion.addVersion(ipVers);
2483 if (ipVersion != IpVersionChoice.UNDEFINED) {
2484 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2485 + " for VPN {} ", ipVersion, vpnId);
2486 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2488 for (Subnetmap subnetmap : subnetmapList) {
2489 Uuid subnetId = subnetmap.getId();
2490 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2491 if (subnetVpnId != null) {
2492 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2493 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2494 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2495 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2498 if (!NeutronvpnUtils.getIsExternal(network)) {
2499 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2501 addSubnetToVpn(vpnId, subnetId, null);
2502 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2504 passedNwList.add(nw);
2507 passedNwList.add(nw);
2509 } catch (ReadFailedException e) {
2510 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2512 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2515 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2516 if (!isExternalNetwork) {
2517 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2519 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2520 return failedNwList;
2523 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2524 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2527 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2528 if (vpnOpDataEntry == null) {
2529 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2532 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2533 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2534 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2536 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2537 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2538 updateVpnMaps(vpnId, null, null, null, extNwList);
2539 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2540 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2541 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2543 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2546 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2547 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2550 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2551 updateVpnInternetForSubnet(sm, vpnId, true);
2553 if (!ipVersion.isIpVersionChosen(ipVers)) {
2554 ipVersion = ipVersion.addVersion(ipVers);
2557 if (ipVersion != IpVersionChoice.UNDEFINED) {
2558 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2559 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2560 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2566 * Parses and disassociates networks list from given VPN.
2568 * @param vpnId Uuid of given VPN.
2569 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2570 * @return list of formatted strings with detailed error messages.
2573 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2574 List<String> failedNwList = new ArrayList<>();
2575 HashSet<Uuid> passedNwList = new HashSet<>();
2576 if (networkList.isEmpty()) {
2577 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2578 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2580 return failedNwList;
2582 for (Uuid nw : networkList) {
2583 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2584 if (networkSubnets == null) {
2585 passedNwList.add(nw);
2588 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2589 if (network == null) {
2590 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2591 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2595 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2596 if (networkVpnId == null) {
2597 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2598 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2602 if (!vpnId.equals(networkVpnId)) {
2603 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2604 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2605 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2606 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2610 if (NeutronvpnUtils.getIsExternal(network)) {
2611 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2612 passedNwList.add(nw);
2614 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2615 nw.getValue(), vpnId.getValue());
2616 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2621 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2622 for (Uuid subnet : networkSubnets) {
2623 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2624 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2625 if (!ipVersion.isIpVersionChosen(ipVers)) {
2626 ipVersion = ipVersion.addVersion(ipVers);
2628 if (!NeutronvpnUtils.getIsExternal(network)) {
2629 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2631 removeSubnetFromVpn(vpnId, subnet, null);
2632 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2633 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2635 passedNwList.add(nw);
2638 if (ipVersion != IpVersionChoice.UNDEFINED) {
2639 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2640 + " for VPN {}", ipVersion, vpnId);
2641 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2644 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2645 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2646 passedNwList.toString(), vpnId.getValue());
2647 return failedNwList;
2650 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2651 if (!removeExternalNetworkFromVpn(extNet)) {
2654 // check, if there is another Provider Networks associated with given VPN
2655 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2656 if (vpnNets != null) {
2657 //Remove currently disassociated network from the list
2658 vpnNets.remove(extNet.getUuid());
2659 for (Uuid netId : vpnNets) {
2660 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2661 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2662 + "{}", vpnId.getValue(), netId.getValue());
2667 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2668 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2669 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2670 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2671 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2672 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2673 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2675 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2678 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2679 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2682 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2683 updateVpnInternetForSubnet(sm, vpnId, false);
2685 if (!ipVersion.isIpVersionChosen(ipVers)) {
2686 ipVersion = ipVersion.addVersion(ipVers);
2689 if (ipVersion != IpVersionChoice.UNDEFINED) {
2690 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2691 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2693 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2699 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2702 // TODO Clean up the exception handling
2703 @SuppressWarnings("checkstyle:IllegalCatch")
2704 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2706 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2707 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2708 StringBuilder returnMsg = new StringBuilder();
2709 Uuid vpnId = input.getVpnId();
2712 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2713 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2714 input.getNetworkId().toString());
2715 List<Uuid> netIds = input.getNetworkId();
2716 if (netIds != null && !netIds.isEmpty()) {
2717 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2718 if (!failed.isEmpty()) {
2719 returnMsg.append(failed);
2723 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2725 if (returnMsg.length() != 0) {
2726 opBuilder.setResponse(
2727 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2728 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2729 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2731 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2733 } catch (Exception ex) {
2734 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2735 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2736 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2738 LOG.debug("associateNetworks returns..");
2743 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2746 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2748 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2749 LOG.debug("associateRouter {}", input);
2750 StringBuilder returnMsg = new StringBuilder();
2751 Uuid vpnId = input.getVpnId();
2752 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2753 routerIds = input.getRouterIds();
2754 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2755 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2756 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2757 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2758 .RouterIds routerId : routerIds) {
2759 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2760 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2761 if (vpnMap != null) {
2763 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2764 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2765 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2766 .append(routerId.getRouterId());
2767 } else if (extVpnId != null) {
2768 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2769 + "another VPN ").append(extVpnId.getValue());
2771 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2772 routerId.getRouterId());
2773 associateRouterToVpn(vpnId, routerId.getRouterId());
2776 returnMsg.append("router not found : ").append(routerId.getRouterId());
2779 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2781 if (returnMsg.length() != 0) {
2782 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2783 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2784 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2786 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2789 LOG.debug("associateRouter returns..");
2794 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2797 // TODO Clean up the exception handling
2798 @SuppressWarnings("checkstyle:IllegalCatch")
2799 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2800 GetFixedIPsForNeutronPortInput input) {
2801 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2802 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2803 Uuid portId = input.getPortId();
2804 StringBuilder returnMsg = new StringBuilder();
2806 List<String> fixedIPList = new ArrayList<>();
2807 Port port = neutronvpnUtils.getNeutronPort(portId);
2809 for (FixedIps ip : port.nonnullFixedIps()) {
2810 fixedIPList.add(ip.getIpAddress().stringValue());
2813 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2815 if (returnMsg.length() != 0) {
2816 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2818 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2819 returnMsg)).build());
2821 opBuilder.setFixedIPs(fixedIPList);
2822 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2824 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2826 } catch (Exception ex) {
2827 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2828 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2829 portId.getValue(), ex.getMessage(), ex)).build());
2835 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2838 // TODO Clean up the exception handling
2839 @SuppressWarnings("checkstyle:IllegalCatch")
2840 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2842 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2843 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2845 LOG.debug("dissociateNetworks {}", input);
2846 StringBuilder returnMsg = new StringBuilder();
2847 Uuid vpnId = input.getVpnId();
2850 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2851 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2852 input.getNetworkId().toString());
2853 List<Uuid> netIds = input.getNetworkId();
2854 if (netIds != null && !netIds.isEmpty()) {
2855 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2856 if (!failed.isEmpty()) {
2857 returnMsg.append(failed);
2861 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2863 if (returnMsg.length() != 0) {
2864 opBuilder.setResponse(
2865 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2866 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2868 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2870 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2872 } catch (Exception ex) {
2873 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2874 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2875 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2877 LOG.debug("dissociateNetworks returns..");
2882 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2885 // TODO Clean up the exception handling
2886 @SuppressWarnings("checkstyle:IllegalCatch")
2887 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2889 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2891 LOG.debug("dissociateRouter {}", input);
2892 StringBuilder returnMsg = new StringBuilder();
2893 Uuid vpnId = input.getVpnId();
2894 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2895 .RouterIds> routerIdList = input.getRouterIds();
2896 String routerIdsString = "";
2897 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2898 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2899 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2900 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2901 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2902 .RouterIds routerId : routerIdList) {
2904 if (routerId != null) {
2905 routerIdsString += routerId.getRouterId() + ", ";
2906 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2908 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2909 if (routerVpnId == null) {
2910 returnMsg.append("input router ").append(routerId.getRouterId())
2911 .append(" not associated to any vpn yet");
2912 } else if (vpnId.equals(routerVpnId)) {
2913 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2915 returnMsg.append("input router ").append(routerId.getRouterId())
2916 .append(" associated to vpn ")
2917 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2920 returnMsg.append("router not found : ").append(routerId.getRouterId());
2923 if (returnMsg.length() != 0) {
2924 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2925 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2926 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2927 returnMsg)).build());
2929 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2931 } catch (Exception ex) {
2932 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2933 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2934 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2938 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2941 LOG.debug("dissociateRouter returns..");
2945 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2946 // check if the router is associated to some VPN
2947 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2948 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2949 if (vpnId != null) {
2950 // remove existing external vpn interfaces
2951 for (Uuid subnetId : routerSubnetIds) {
2952 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2954 clearFromVpnMaps(vpnId, routerId, null);
2956 // remove existing internal vpn interfaces
2957 for (Uuid subnetId : routerSubnetIds) {
2958 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2961 // delete entire vpnMaps node for internal VPN
2962 deleteVpnMapsNode(routerId);
2964 // delete vpn-instance for internal VPN
2965 deleteVpnInstance(routerId);
2968 protected Subnet getNeutronSubnet(Uuid subnetId) {
2969 return neutronvpnUtils.getNeutronSubnet(subnetId);
2973 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2974 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2976 return sn.getGatewayIp();
2982 protected Network getNeutronNetwork(Uuid networkId) {
2983 return neutronvpnUtils.getNeutronNetwork(networkId);
2986 protected Port getNeutronPort(String name) {
2987 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2990 protected Port getNeutronPort(Uuid portId) {
2991 return neutronvpnUtils.getNeutronPort(portId);
2994 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2995 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2998 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2999 return neutronvpnUtils.getNetworksForVpn(vpnId);
3003 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3005 * @return a List of String to be printed on screen
3006 * @throws ReadFailedException if there was a problem reading from the data store
3008 public List<String> showNeutronPortsCLI() throws ReadFailedException {
3009 List<String> result = new ArrayList<>();
3010 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3012 result.add("-------------------------------------------------------------------------------------------");
3013 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3015 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3016 if (ports.isPresent() && ports.get().getPort() != null) {
3017 for (Port port : ports.get().nonnullPort()) {
3018 List<FixedIps> fixedIPs = port.getFixedIps();
3019 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3020 List<String> ipList = new ArrayList<>();
3021 for (FixedIps fixedIp : fixedIPs) {
3022 IpAddress ipAddress = fixedIp.getIpAddress();
3023 if (ipAddress.getIpv4Address() != null) {
3024 ipList.add(ipAddress.getIpv4Address().getValue());
3026 ipList.add(ipAddress.getIpv6Address().getValue());
3029 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3030 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3031 ipList.toString()));
3033 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3034 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3043 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3045 * @param vpnuuid Uuid of the VPN whose config must be shown
3046 * @return formatted output list
3047 * @throws InterruptedException if there was a thread related problem getting the data to display
3048 * @throws ExecutionException if there was any other problem getting the data to display
3050 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3051 List<String> result = new ArrayList<>();
3052 if (vpnuuid == null) {
3054 result.add("Displaying VPN config for all VPNs");
3055 result.add("To display VPN config for a particular VPN, use the following syntax");
3056 result.add(getshowVpnConfigCLIHelp());
3058 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3059 if (rpcResult.isSuccessful()) {
3061 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3063 result.add(String.format(" %-80s ", "Import-RTs"));
3065 result.add(String.format(" %-80s ", "Export-RTs"));
3067 result.add(String.format(" %-76s ", "Subnet IDs"));
3069 result.add("------------------------------------------------------------------------------------");
3071 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3072 rpcResult.getResult().nonnullL3vpnInstances()) {
3073 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3075 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3076 vpn.getRouteDistinguisher()));
3078 result.add(String.format(" %-80s ", vpn.getImportRT()));
3080 result.add(String.format(" %-80s ", vpn.getExportRT()));
3083 Uuid vpnid = vpn.getId();
3084 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3085 if (!subnetList.isEmpty()) {
3086 for (Uuid subnetuuid : subnetList) {
3087 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3090 result.add(String.format(" %-76s ", "\" \""));
3093 result.add("----------------------------------------");
3097 String errortag = rpcResult.getErrors().iterator().next().getTag();
3098 if (Objects.equals(errortag, "")) {
3100 result.add("No VPN has been configured yet");
3101 } else if (Objects.equals(errortag, "invalid-value")) {
3103 result.add("VPN " + vpnuuid.getValue() + " is not present");
3105 result.add("error getting VPN info : " + rpcResult.getErrors());
3106 result.add(getshowVpnConfigCLIHelp());
3112 protected void createExternalVpnInterfaces(Uuid extNetId) {
3113 if (extNetId == null) {
3114 LOG.error("createExternalVpnInterfaces: external network is null");
3118 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3119 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3120 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3124 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3125 for (String elanInterface : extElanInterfaces) {
3126 createExternalVpnInterface(extNetId, elanInterface, tx);
3128 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3131 // TODO Clean up the exception handling
3132 @SuppressWarnings("checkstyle:IllegalCatch")
3133 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3134 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3135 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3136 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3139 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3140 for (String elanInterface : extElanInterfaces) {
3141 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3142 .buildVpnInterfaceIdentifier(elanInterface);
3143 LOG.info("Removing vpn interface {}", elanInterface);
3144 tx.delete(vpnIfIdentifier);
3146 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3149 private void createExternalVpnInterface(Uuid vpnId, String infName,
3150 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3151 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3152 false /* not a router iface */, wrtConfigTxn);
3155 // TODO Clean up the exception handling
3156 @SuppressWarnings("checkstyle:IllegalCatch")
3157 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3158 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3159 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3160 if (vpnIdList.isEmpty() || infName == null) {
3161 LOG.error("vpnid is empty or interface({}) is null", infName);
3164 if (wrtConfigTxn == null) {
3165 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3166 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3167 "Error writing VPN interface");
3170 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3171 for (Uuid vpnId: vpnIdList) {
3172 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3173 AssociatedSubnetType.V4AndV6Subnets);
3174 vpnIdListStruct.add(vpnInstance);
3177 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3178 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3180 .setVpnInstanceNames(vpnIdListStruct)
3181 .setRouterInterface(isRouterInterface);
3182 LOG.info("Network Id is {}", networkUuid);
3183 if (networkUuid != null) {
3184 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3185 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3186 NetworkAttributes.NetworkType networkType = providerType != null
3187 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3188 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3189 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3190 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3193 if (adjacencies != null) {
3194 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3196 VpnInterface vpnIf = vpnb.build();
3198 LOG.info("Creating vpn interface {}", vpnIf);
3199 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3200 } catch (Exception ex) {
3201 LOG.error("Creation of vpninterface {} failed", infName, ex);
3205 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3206 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3207 if (vpnId == null || infName == null) {
3208 LOG.error("vpn id or interface is null");
3211 if (wrtConfigTxn == null) {
3212 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3213 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3214 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3215 }), LOG, "Error updating VPN interface with adjacencies");
3219 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3221 try (AcquireResult lock = tryInterfaceLock(infName)) {
3222 if (!lock.wasAcquired()) {
3223 // FIXME: why do we even bother with locking if we do not honor it?!
3224 logTryLockFailure(infName);
3228 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3229 .syncReadOptional(dataBroker, LogicalDatastoreType
3230 .CONFIGURATION, vpnIfIdentifier);
3231 if (optionalVpnInterface.isPresent()) {
3232 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3233 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3235 if (adjacencies == null) {
3238 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3239 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3240 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3241 optionalVpnInterface.get().getVpnInstanceNames());
3242 if (listVpnInstances.isEmpty()
3243 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3244 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3245 AssociatedSubnetType.V4AndV6Subnets);
3246 listVpnInstances.add(vpnInstance);
3247 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3250 VpnInstanceNames vpnInstance = VpnHelper
3251 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3252 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3253 listVpnInstances.add(vpnInstance);
3254 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3256 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3257 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3259 } catch (IllegalStateException | ReadFailedException ex) {
3260 // FIXME: why are we catching IllegalStateException here?
3261 LOG.error("Update of vpninterface {} failed", infName, ex);
3266 private String getshowVpnConfigCLIHelp() {
3267 StringBuilder help = new StringBuilder("Usage:");
3268 help.append("display vpn-config [-vid/--vpnid <id>]");
3269 return help.toString();
3272 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3273 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3277 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3278 return neutronEvpnManager.createEVPN(input);
3282 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3283 return neutronEvpnManager.getEVPN(input);
3287 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3288 return neutronEvpnManager.deleteEVPN(input);
3291 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3292 Uuid extNetId = extNet.getUuid();
3293 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3294 .child(Networks.class, new NetworksKey(extNetId)).build();
3297 Optional<Networks> optionalExtNets =
3298 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3300 if (!optionalExtNets.isPresent()) {
3301 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3302 extNetId.getValue());
3305 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3306 builder.setVpnid(vpnId);
3307 Networks networks = builder.build();
3308 // Add Networks object to the ExternalNetworks list
3309 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3310 extNetId.getValue());
3311 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3314 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3315 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3316 extNetId.getValue(), ex);
3321 private boolean removeExternalNetworkFromVpn(Network extNet) {
3322 Uuid extNetId = extNet.getUuid();
3323 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3324 .child(Networks.class, new NetworksKey(extNetId)).build();
3326 Optional<Networks> optionalNets =
3327 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3329 NetworksBuilder builder = null;
3330 if (optionalNets.isPresent()) {
3331 builder = new NetworksBuilder(optionalNets.get());
3333 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3334 extNetId.getValue());
3337 builder.setVpnid(null);
3338 Networks networks = builder.build();
3339 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3340 extNetId.getValue());
3341 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3343 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3344 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3345 extNetId.getValue(), ex);
3350 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3351 Optional<String> existingVpnName = Optional.of(primaryRd);
3352 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3354 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3355 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3356 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3357 } catch (ReadFailedException e) {
3358 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3360 /*Read failed. We don't know if a VPN exists or not.
3361 * Return primaryRd to halt caller execution, to be safe.*/
3362 return existingVpnName;
3364 if (vpnInstanceOpDataOptional.isPresent()) {
3365 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3367 existingVpnName = Optional.absent();
3369 return existingVpnName;
3372 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3373 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3376 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3377 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3380 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3381 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3384 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3385 String message = tuple.getMessage();
3386 logger.accept(message);
3390 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3391 @NonNull Subnetmap subnetMap) {
3392 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3393 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3394 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3395 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3396 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3397 subnetMap.getId().getValue(), internetVpnId.getValue());
3401 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3402 @NonNull Subnetmap subnetMap) {
3403 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3404 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3407 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3408 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3409 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3410 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3411 internetVpnId.getValue(), routerId.getValue());
3412 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3418 private AcquireResult tryInterfaceLock(final String infName) {
3419 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3423 private AcquireResult tryVpnLock(final Uuid vpnId) {
3424 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3427 private static ReentrantLock lockForUuid(Uuid uuid) {
3428 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3429 return JvmGlobalLocks.getLockForString(uuid.getValue());
3432 private static void logTryLockFailure(Object objectId) {
3433 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());