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,
271 boolean isExternalNw) {
273 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
274 final ReentrantLock lock = lockForUuid(subnetId);
277 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
278 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
279 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
280 if (sn.isPresent()) {
281 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
282 subnetId.getValue());
285 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
286 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
287 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
288 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
289 subnetId.getValue());
290 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
291 subnetMapIdentifier, subnetmapBuilder.build());
295 } catch (TransactionCommitFailedException | ReadFailedException e) {
296 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
298 // check if there are ports to update for already created Subnetmap node
299 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
300 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
301 if (entry.getValue().getValue().equals(subnetId.getValue())) {
302 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
303 unprocessedPortsMap.remove(entry.getKey());
309 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
310 @Nullable Uuid internetvpnId) {
311 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
312 .child(Subnetmap.class, new SubnetmapKey(subnetId))
314 final ReentrantLock lock = lockForUuid(subnetId);
317 Optional<Subnetmap> sn =
318 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
319 if (!sn.isPresent()) {
320 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
323 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
324 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
325 if (routerId != null) {
326 builder.setRouterId(routerId);
329 builder.setVpnId(vpnId);
331 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
332 builder.setInternetVpnId(internetvpnId);
334 Subnetmap subnetmap = builder.build();
335 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
336 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
338 } catch (ReadFailedException | TransactionCommitFailedException e) {
339 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
346 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
347 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
348 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
349 InstanceIdentifier<Subnetmap> id =
350 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
351 final ReentrantLock lock = lockForUuid(subnetId);
354 Optional<Subnetmap> sn =
355 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
356 if (!sn.isPresent()) {
357 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
358 subnetId.getValue());
361 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
362 subnetId.getValue());
363 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
364 builder.setRouterId(routerId);
365 builder.setRouterInterfacePortId(routerInterfacePortId);
366 builder.setRouterIntfMacAddress(routerIntfMacAddress);
367 builder.setRouterInterfaceFixedIp(fixedIp);
369 builder.setVpnId(vpnId);
371 Subnetmap subnetmap = builder.build();
372 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
373 subnetId.getValue());
374 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
375 } catch (ReadFailedException | TransactionCommitFailedException e) {
376 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
377 subnetId.getValue(), e);
383 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
384 @Nullable Uuid directPortId) {
385 Subnetmap subnetmap = null;
386 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
387 new SubnetmapKey(subnetId)).build();
388 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
389 final ReentrantLock lock = lockForUuid(subnetId);
392 Optional<Subnetmap> sn =
393 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
395 if (sn.isPresent()) {
396 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
397 if (null != portId) {
398 List<Uuid> existingPortList = builder.getPortList();
399 List<Uuid> portList = new ArrayList<>();
400 if (null != existingPortList) {
401 portList.addAll(existingPortList);
403 portList.add(portId);
404 builder.setPortList(portList);
405 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
406 subnetId.getValue(), portId.getValue());
408 if (null != directPortId) {
409 List<Uuid> existingDirectPortList = builder.getDirectPortList();
410 List<Uuid> directPortList = new ArrayList<>();
411 if (null != existingDirectPortList) {
412 directPortList.addAll(existingDirectPortList);
414 directPortList.add(directPortId);
415 builder.setDirectPortList(directPortList);
416 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
417 directPortId.getValue());
419 subnetmap = builder.build();
420 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
423 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
424 + "cache ", subnetId.getValue(), portId.getValue());
425 unprocessedPortsMap.put(portId, subnetId);
427 } catch (ReadFailedException | TransactionCommitFailedException e) {
428 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
435 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
436 Uuid vpnId, @Nullable Uuid portId) {
437 Subnetmap subnetmap = null;
438 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
439 .child(Subnetmap.class, new SubnetmapKey(subnetId))
441 final ReentrantLock lock = lockForUuid(subnetId);
444 Optional<Subnetmap> sn =
445 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
447 if (sn.isPresent()) {
448 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
449 if (routerId != null) {
450 builder.setRouterId(null);
452 if (networkId != null) {
453 builder.setNetworkId(null);
456 builder.setVpnId(null);
458 builder.setInternetVpnId(null);
459 if (portId != null && builder.getPortList() != null) {
460 List<Uuid> portList = new ArrayList<>(builder.getPortList());
461 portList.remove(portId);
462 builder.setPortList(portList);
465 subnetmap = builder.build();
466 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
467 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
470 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
472 } catch (ReadFailedException | TransactionCommitFailedException e) {
473 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
481 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
482 @Nullable Uuid directPortId) {
483 Subnetmap subnetmap = null;
484 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
485 new SubnetmapKey(subnetId)).build();
486 final ReentrantLock lock = lockForUuid(subnetId);
489 Optional<Subnetmap> sn =
490 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
492 if (sn.isPresent()) {
493 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
494 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
495 List<Uuid> portList = new ArrayList<>(builder.getPortList());
496 portList.remove(portId);
497 builder.setPortList(portList);
498 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
499 subnetId.getValue());
501 if (null != directPortId && null != builder.getDirectPortList()
502 && !builder.getDirectPortList().isEmpty()) {
503 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
504 directPortList.remove(directPortId);
505 builder.setDirectPortList(directPortList);
506 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
507 .getValue(), subnetId.getValue());
509 subnetmap = builder.build();
510 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
513 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
515 } catch (ReadFailedException | TransactionCommitFailedException e) {
516 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
517 subnetId.getValue(), e);
524 // TODO Clean up the exception handling
525 @SuppressWarnings("checkstyle:IllegalCatch")
526 protected void deleteSubnetMapNode(Uuid subnetId) {
527 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
528 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
529 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
530 final ReentrantLock lock = lockForUuid(subnetId);
533 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
534 } catch (TransactionCommitFailedException e) {
535 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
541 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
542 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
543 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
545 Optional<VpnInstance> vpnInstanceConfig =
546 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
548 if (!vpnInstanceConfig.isPresent()) {
549 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
552 VpnInstance vpnInstance = vpnInstanceConfig.get();
553 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
554 if (vpnInstance.getIpv4Family() != null) {
555 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
556 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
558 if (vpnInstance.getIpv6Family() != null) {
559 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
560 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
562 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
563 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
564 updateVpnInstanceBuilder.build());
565 } catch (ReadFailedException | TransactionCommitFailedException ex) {
566 LOG.warn("Error configuring feature ", ex);
570 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
571 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
572 String vpnName = vpnId.getValue();
573 VpnInstanceBuilder builder = null;
574 List<VpnTarget> vpnTargetList = new ArrayList<>();
575 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
576 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
577 Optional<VpnInstance> optionalVpn;
579 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
581 } catch (ReadFailedException e) {
582 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
586 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
587 if (optionalVpn.isPresent()) {
588 builder = new VpnInstanceBuilder(optionalVpn.get());
589 LOG.debug("updating existing vpninstance node");
591 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
592 .setType(type).setL3vni(l3vni);
594 if (irt != null && !irt.isEmpty()) {
595 if (ert != null && !ert.isEmpty()) {
596 List<String> commonRT = new ArrayList<>(irt);
597 commonRT.retainAll(ert);
599 for (String common : commonRT) {
602 VpnTarget vpnTarget =
603 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
604 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
605 vpnTargetList.add(vpnTarget);
608 for (String importRT : irt) {
609 VpnTarget vpnTarget =
610 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
611 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
612 vpnTargetList.add(vpnTarget);
616 if (ert != null && !ert.isEmpty()) {
617 for (String exportRT : ert) {
618 VpnTarget vpnTarget =
619 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
620 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
621 vpnTargetList.add(vpnTarget);
625 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
626 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
627 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
629 if (rd != null && !rd.isEmpty()) {
630 ipv4vpnBuilder.setRouteDistinguisher(rd);
631 ipv6vpnBuilder.setRouteDistinguisher(rd);
634 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
635 builder.setIpv4Family(ipv4vpnBuilder.build());
637 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
638 builder.setIpv6Family(ipv6vpnBuilder.build());
640 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
641 builder.setIpv4Family(ipv4vpnBuilder.build());
643 VpnInstance newVpn = builder.build();
645 try (AcquireResult lock = tryVpnLock(vpnId)) {
646 if (!lock.wasAcquired()) {
647 // FIXME: why do we even bother with locking if we do not honor it?!
648 logTryLockFailure(vpnId);
651 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
653 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
655 } catch (TransactionCommitFailedException e) {
656 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
661 private void deleteVpnMapsNode(Uuid vpnId) {
662 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
663 .child(VpnMap.class, new VpnMapKey(vpnId))
665 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
666 try (AcquireResult lock = tryVpnLock(vpnId)) {
667 if (!lock.wasAcquired()) {
668 // FIXME: why do we even bother with locking if we do not honor it?!
669 logTryLockFailure(vpnId);
673 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
675 } catch (TransactionCommitFailedException e) {
676 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
681 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
682 @Nullable List<Uuid> networks) {
683 VpnMapBuilder builder;
684 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
685 .child(VpnMap.class, new VpnMapKey(vpnId))
688 Optional<VpnMap> optionalVpnMap =
689 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
691 if (optionalVpnMap.isPresent()) {
692 builder = new VpnMapBuilder(optionalVpnMap.get());
694 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
698 builder.setName(name);
700 if (tenantId != null) {
701 builder.setTenantId(tenantId);
703 if (router != null) {
704 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
705 List<RouterIds> rtrIds = builder.getRouterIds() != null
706 ? new ArrayList<>(builder.getRouterIds()) : null;
707 if (rtrIds == null) {
708 rtrIds = Collections.singletonList(vpnRouterId);
710 rtrIds.add(vpnRouterId);
712 builder.setRouterIds(rtrIds);
714 if (networks != null) {
715 List<Uuid> nwList = builder.getNetworkIds() != null
716 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
717 nwList.addAll(networks);
718 builder.setNetworkIds(nwList);
721 try (AcquireResult lock = tryVpnLock(vpnId)) {
722 if (!lock.wasAcquired()) {
723 // FIXME: why do we even bother with locking if we do not honor it?!
724 logTryLockFailure(vpnId);
727 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
728 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
730 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
732 } catch (ReadFailedException | TransactionCommitFailedException e) {
733 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
737 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
738 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
739 .child(VpnMap.class, new VpnMapKey(vpnId))
741 Optional<VpnMap> optionalVpnMap;
744 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
746 } catch (ReadFailedException e) {
747 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
750 if (optionalVpnMap.isPresent()) {
751 VpnMap vpnMap = optionalVpnMap.get();
752 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
753 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds());
754 if (rtrIds == null) {
755 rtrIds = new ArrayList<>();
757 if (routerId != null) {
758 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
759 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
760 vpnMapBuilder.setRouterIds(rtrIds);
762 try (AcquireResult lock = tryVpnLock(vpnId)) {
763 if (!lock.wasAcquired()) {
764 // FIXME: why do we even bother with locking if we do not honor it?!
765 logTryLockFailure(vpnId);
768 LOG.debug("removing vpnMaps node: {} ", vpnId);
770 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
772 } catch (TransactionCommitFailedException e) {
773 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
777 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
778 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
779 vpnMapBuilder.setRouterIds(rtrIds);
780 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
783 if (networkIds != null) {
784 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
785 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
786 vpnNw.removeAll(networkIds);
787 if (vpnNw.isEmpty()) {
788 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
789 vpnMapBuilder.setNetworkIds(null);
791 vpnMapBuilder.setNetworkIds(vpnNw);
795 try (AcquireResult lock = tryVpnLock(vpnId)) {
796 if (!lock.wasAcquired()) {
797 // FIXME: why do we even bother with locking if we do not honor it?!
798 logTryLockFailure(vpnId);
801 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
803 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
804 vpnMapIdentifier, vpnMapBuilder.build());
805 } catch (TransactionCommitFailedException e) {
806 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
810 LOG.error("VPN : {} not found", vpnId.getValue());
812 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
815 private void deleteVpnInstance(Uuid vpnId) {
816 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
817 .child(VpnInstance.class,
818 new VpnInstanceKey(vpnId.getValue()))
821 try (AcquireResult lock = tryVpnLock(vpnId)) {
822 if (!lock.wasAcquired()) {
823 // FIXME: why do we even bother with locking if we do not honor it?!
824 logTryLockFailure(vpnId);
827 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
829 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
830 } catch (TransactionCommitFailedException e) {
831 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
836 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
837 TypedWriteTransaction<Configuration> wrtConfigTxn,
838 @Nullable VpnInterface vpnIface) {
839 List<Adjacency> adjList = new ArrayList<>();
840 if (vpnIface != null) {
841 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
843 String infName = port.getUuid().getValue();
844 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
845 for (FixedIps ip : port.nonnullFixedIps()) {
846 String ipValue = ip.getIpAddress().stringValue();
847 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
848 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
849 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
850 snTemp.getSubnetIp(), false)) {
853 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
855 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
856 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
857 //Create Neutron port adjacency if VPN presence is existing for subnet
858 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
859 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
860 .setSubnetId(ip.getSubnetId()).build();
861 if (!adjList.contains(vmAdj)) {
865 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
866 if (snTemp != null && snTemp.getInternetVpnId() != null) {
867 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
868 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
870 if (routerId != null) {
871 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
872 if (rtr != null && rtr.getRoutes() != null) {
873 List<Routes> routeList = rtr.getRoutes();
874 // create extraroute Adjacence for each ipValue,
875 // because router can have IPv4 and IPv6 subnet ports, or can have
876 // more that one IPv4 subnet port or more than one IPv6 subnet port
877 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
878 if (!erAdjList.isEmpty()) {
879 adjList.addAll(erAdjList);
884 return new AdjacenciesBuilder().setAdjacency(adjList).build();
887 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
888 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
889 boolean isRouterInterface = false;
890 if (port.getDeviceOwner() != null) {
891 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
893 String infName = port.getUuid().getValue();
894 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
895 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
896 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
897 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
898 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
901 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
902 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
903 String infName = port.getUuid().getValue();
904 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
905 Optional<VpnInterface> optionalVpnInterface = null;
906 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
907 vpnId, internetVpnId, infName);
909 optionalVpnInterface = SingleTransactionDataBroker
910 .syncReadOptional(dataBroker, LogicalDatastoreType
911 .CONFIGURATION, vpnIfIdentifier);
912 } catch (ReadFailedException e) {
913 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
916 if (!optionalVpnInterface.isPresent()) {
919 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
920 sn != null ? sn.getSubnetIp() : "null");
921 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
922 List<Adjacency> updatedAdjsList = new ArrayList<>();
923 boolean isIpFromAnotherSubnet = false;
924 for (Adjacency adj : vpnAdjsList) {
925 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
926 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
927 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
928 isIpFromAnotherSubnet = true;
930 updatedAdjsList.add(adj);
933 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
934 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
937 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
938 String.valueOf(adjString), wrtConfigTxn);
940 if (internetVpnId != null) {
941 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
942 String.valueOf(adjString), wrtConfigTxn);
945 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
946 && sn.getRouterId() != null) {
947 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
948 if (rtr != null && rtr.getRoutes() != null) {
949 List<Routes> extraRoutesToRemove = new ArrayList<>();
950 for (Routes rt: rtr.getRoutes()) {
951 if (rt.getNexthop().toString().equals(adjString)) {
952 extraRoutesToRemove.add(rt);
956 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
957 extraRoutesToRemove, vpnId);
958 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
960 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
965 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
967 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
969 if (!isIpFromAnotherSubnet) {
970 // no more subnetworks for neutron port
971 if (sn != null && sn.getRouterId() != null) {
972 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
974 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
980 // TODO Clean up the exception handling
981 @SuppressWarnings("checkstyle:IllegalCatch")
982 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
983 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
984 if (wrtConfigTxn == null) {
985 ListenableFutures.addErrorLogging(
986 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
987 tx -> deleteVpnInterface(infName, vpnId, tx)),
988 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
992 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
993 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
994 Optional<VpnInterface> optionalVpnInterface;
996 optionalVpnInterface =
997 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
999 } catch (ReadFailedException ex) {
1000 LOG.error("Error during deletion of vpninterface {}", infName, ex);
1003 if (!optionalVpnInterface.isPresent()) {
1004 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
1007 if (vpnId != null) {
1008 VpnInterface vpnInterface = optionalVpnInterface.get();
1009 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
1011 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
1012 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
1013 if (!vpnList.isEmpty()) {
1014 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1015 + "List not empty", infName);
1018 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1019 .setVpnInstanceNames(vpnList);
1020 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1024 LOG.debug("Deleting vpn interface {}", infName);
1025 wrtConfigTxn.delete(vpnIfIdentifier);
1028 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1029 TypedWriteTransaction<Configuration> writeConfigTxn,
1031 if (vpnId == null || port == null) {
1034 String infName = port.getUuid().getValue();
1035 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1037 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1038 .syncReadOptional(dataBroker, LogicalDatastoreType
1039 .CONFIGURATION, vpnIfIdentifier);
1040 if (optionalVpnInterface.isPresent()) {
1041 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1043 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1044 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1046 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1047 .setVpnInstanceNames(listVpn);
1048 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1049 LOG.debug("Updating vpn interface {}", infName);
1050 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1051 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1052 while (adjacencyIter.hasNext()) {
1053 Adjacency adjacency = adjacencyIter.next();
1054 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1057 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1058 InstanceIdentifier<LearntVpnVipToPort> id =
1059 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1060 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1061 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1062 LogicalDatastoreType.OPERATIONAL, id);
1063 if (optionalVpnVipToPort.isPresent()) {
1064 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1066 if (listVpn == null || listVpn.isEmpty()) {
1067 adjacencyIter.remove();
1069 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1070 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1071 mipToQuery, infName, vpnId.getValue());
1074 for (FixedIps ip : port.nonnullFixedIps()) {
1075 String ipValue = ip.getIpAddress().stringValue();
1077 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1080 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1081 ipValue, writeConfigTxn);
1083 if (listVpn == null || listVpn.isEmpty()) {
1084 if (sm != null && sm.getRouterId() != null) {
1085 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1087 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1089 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1092 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1094 } catch (ReadFailedException ex) {
1095 LOG.error("Update of vpninterface {} failed", infName, ex);
1099 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1101 TypedWriteTransaction<Configuration> writeConfigTxn,
1102 boolean isInternetVpn) {
1103 if (vpnId == null || port == null) {
1106 String infName = port.getUuid().getValue();
1107 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1109 try (AcquireResult lock = tryInterfaceLock(infName)) {
1110 if (!lock.wasAcquired()) {
1111 // FIXME: why do we even bother with locking if we do not honor it?!
1112 logTryLockFailure(infName);
1116 Optional<VpnInterface> optionalVpnInterface =
1117 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1119 if (optionalVpnInterface.isPresent()) {
1120 VpnInstanceNames vpnInstance = VpnHelper
1121 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1122 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1123 .get().getVpnInstanceNames());
1124 if (oldVpnId != null
1125 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1126 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1128 if (vpnId.getValue() != null
1129 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1130 listVpn.add(vpnInstance);
1132 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1133 .setVpnInstanceNames(listVpn);
1134 LOG.debug("Updating vpn interface {}", infName);
1135 if (!isBeingAssociated) {
1136 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1137 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1138 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1139 while (adjacencyIter.hasNext()) {
1140 Adjacency adjacency = adjacencyIter.next();
1141 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1142 InstanceIdentifier<LearntVpnVipToPort> id =
1143 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1144 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1145 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1146 LogicalDatastoreType.OPERATIONAL, id);
1147 if (optionalVpnVipToPort.isPresent()
1148 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1149 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1150 + "from VPN {}", infName, vpnId, oldVpnId);
1151 adjacencyIter.remove();
1152 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1154 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1155 mipToQuery, infName, vpnId.getValue());
1157 InstanceIdentifier<VpnPortipToPort> build =
1158 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1159 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1160 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1161 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1162 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1163 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1164 mipToQuery, infName, vpnId.getValue());
1167 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1168 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1170 for (FixedIps ip : port.nonnullFixedIps()) {
1171 String ipValue = ip.getIpAddress().stringValue();
1172 if (oldVpnId != null) {
1173 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1174 ipValue, writeConfigTxn);
1176 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1177 && isInternetVpn == true) {
1181 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1182 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1184 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1186 LOG.error("VPN Interface {} not found", infName);
1188 } catch (ReadFailedException ex) {
1189 LOG.error("Updation of vpninterface {} failed", infName, ex);
1194 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1195 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1197 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1199 // Update VPN Instance node
1200 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1202 // Update local vpn-subnet DS
1203 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1205 if (routerId != null) {
1206 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1207 if (existingVpn != null) {
1208 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1209 // if before reboot, router was already associated to VPN, should not proceed associating router to
1210 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1211 // preserved upon reboot.
1212 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1213 // RouterInterfacesMap via #createVPNInterface call.
1214 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1215 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1218 associateRouterToInternalVpn(vpnId, routerId);
1223 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1224 * specified Neutron Networks and Routers.
1226 * @param vpnId Uuid of the VPN tp be created
1227 * @param name Representative name of the new VPN
1228 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1229 * @param rdList Route-distinguisher for the VPN
1230 * @param irtList A list of Import Route Targets
1231 * @param ertList A list of Export Route Targets
1232 * @param routerIdsList ist of neutron router Id to associate with created VPN
1233 * @param networkList UUID of the neutron network the VPN may be associated to
1234 * @param type Type of the VPN Instance
1235 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1236 * @throws Exception if association of L3VPN failed
1238 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1239 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1240 VpnInstance.Type type, long l3vni) throws Exception {
1242 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1244 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1245 for (Uuid routerId : routerIdsList) {
1246 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1247 ipVersChoices = ipVersChoices.addVersion(vers);
1250 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1252 // Please note that router and networks will be filled into VPNMaps
1253 // by subsequent calls here to associateRouterToVpn and
1254 // associateNetworksToVpn
1255 updateVpnMaps(vpnId, name, null, tenantId, null);
1256 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1257 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1260 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1261 for (Uuid routerId : routerIdsList) {
1262 associateRouterToVpn(vpnId, routerId);
1265 if (networkList != null) {
1266 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1267 if (!failStrings.isEmpty()) {
1268 LOG.error("VPN {} association to networks failed for networks: {}. ",
1269 vpnId.getValue(), failStrings);
1270 throw new Exception(failStrings.toString());
1276 * It handles the invocations to the createVPN RPC method.
1279 // TODO Clean up the exception handling
1280 @SuppressWarnings("checkstyle:IllegalCatch")
1281 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1283 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1284 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1285 List<RpcError> errorList = new ArrayList<>();
1286 int failurecount = 0;
1287 int warningcount = 0;
1289 List<L3vpn> vpns = input.getL3vpn();
1291 vpns = Collections.emptyList();
1293 for (L3vpn vpn : vpns) {
1294 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1295 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1296 formatAndLog(LOG::warn,
1297 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1298 vpn.getId().getValue())));
1302 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1303 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1304 formatAndLog(LOG::warn,
1305 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1306 vpn.getId().getValue())));
1310 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1312 if (vpn.getL3vni() != null) {
1313 l3vni = vpn.getL3vni().toJava();
1316 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1317 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1318 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1319 formatAndLog(LOG::warn,
1320 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1321 + "is already configured",
1322 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1326 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1327 if (operationalVpn.isPresent()) {
1328 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1329 formatAndLog(LOG::error,
1330 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1331 + "is still available. Please retry creation of a new vpn with the same RD"
1332 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1333 vpn.getRouteDistinguisher().get(0))));
1337 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1338 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1339 routerIdsList = vpn.getRouterIds();
1340 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1341 routerId : routerIdsList) {
1342 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1343 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1344 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1345 + "{}", vpn.getId(), routerId.getRouterId())));
1349 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1350 if (vpnId != null) {
1351 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1352 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1353 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1354 vpnId.getValue())));
1360 if (vpn.getNetworkIds() != null) {
1361 int initialWarningCount = warningcount;
1362 for (Uuid nw : vpn.getNetworkIds()) {
1363 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1364 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1365 if (network == null) {
1366 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1367 formatAndLog(LOG::warn,
1368 "Creation of L3VPN failed for VPN {} due to network not found {}",
1369 vpn.getId().getValue(), nw.getValue())));
1371 } else if (vpnId != null) {
1372 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1373 formatAndLog(LOG::warn,
1374 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1375 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1376 vpnId.getValue())));
1380 if (warningcount != initialWarningCount) {
1384 List<Uuid> rtrIdsList = new ArrayList<>();
1385 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1386 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1387 rtrId : vpn.getRouterIds()) {
1388 rtrIdsList.add(rtrId.getRouterId());
1392 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1393 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1394 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1395 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1397 List<String> rdList = vpn.getRouteDistinguisher() != null
1398 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1399 List<String> importRdList = vpn.getImportRT() != null
1400 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1401 List<String> exportRdList = vpn.getExportRT() != null
1402 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1404 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1405 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), vpnInstanceType, l3vni);
1406 } catch (Exception ex) {
1407 LOG.error("VPN Creation exception :", ex);
1408 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1409 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1414 // if at least one succeeds; result is success
1415 // if none succeeds; result is failure
1416 if (failurecount + warningcount == vpns.size()) {
1417 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1419 List<String> errorResponseList = new ArrayList<>();
1420 if (!errorList.isEmpty()) {
1421 for (RpcError rpcError : errorList) {
1422 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1423 + ", ErrorMessage: " + rpcError.getMessage());
1426 errorResponseList.add("Operation successful with no errors");
1428 opBuilder.setResponse(errorResponseList);
1429 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1435 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1438 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1440 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1441 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1442 Uuid inputVpnId = input.getId();
1443 List<VpnInstance> vpns = new ArrayList<>();
1444 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1447 if (inputVpnId == null) {
1449 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1451 Optional<VpnInstances> optionalVpns =
1452 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1454 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1455 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1456 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1457 // from getL3VPN output
1458 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1461 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1467 opBuilder.setL3vpnInstances(l3vpnList);
1468 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1472 String name = inputVpnId.getValue();
1473 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1474 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1475 // read VpnInstance Info
1476 Optional<VpnInstance> optionalVpn =
1477 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1479 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1481 if (optionalVpn.isPresent() && (optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1482 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
1483 vpns.add(optionalVpn.get());
1486 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1487 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1491 for (VpnInstance vpnInstance : vpns) {
1492 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1493 // create VpnMaps id
1494 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1495 List<String> rd = Collections.EMPTY_LIST;
1496 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1497 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1498 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1499 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1501 List<String> ertList = new ArrayList<>();
1502 List<String> irtList = new ArrayList<>();
1504 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1505 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1506 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1507 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1508 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1509 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1510 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1512 if (!vpnTargetList.isEmpty()) {
1513 for (VpnTarget vpnTarget : vpnTargetList) {
1514 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1515 ertList.add(vpnTarget.getVrfRTValue());
1517 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1518 irtList.add(vpnTarget.getVrfRTValue());
1520 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1521 ertList.add(vpnTarget.getVrfRTValue());
1522 irtList.add(vpnTarget.getVrfRTValue());
1528 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1530 if (vpnInstance.getL3vni() != null) {
1531 l3vpn.setL3vni(vpnInstance.getL3vni());
1533 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1534 .class, new VpnMapKey(vpnId)).build();
1535 Optional<VpnMap> optionalVpnMap =
1536 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1538 if (optionalVpnMap.isPresent()) {
1539 VpnMap vpnMap = optionalVpnMap.get();
1540 List<Uuid> rtrIds = new ArrayList<>();
1541 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1542 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1543 rtrIds.add(rtrId.getRouterId());
1546 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1547 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1548 .setName(vpnMap.getName());
1551 l3vpnList.add(l3vpn.build());
1554 opBuilder.setL3vpnInstances(l3vpnList);
1555 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1557 } catch (ReadFailedException ex) {
1558 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1559 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1565 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1568 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1570 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1571 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1572 List<RpcError> errorList = new ArrayList<>();
1574 int failurecount = 0;
1575 int warningcount = 0;
1576 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1577 for (Uuid vpn : vpns) {
1579 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1580 InstanceIdentifier<VpnInstance> vpnIdentifier =
1581 InstanceIdentifier.builder(VpnInstances.class)
1582 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1583 Optional<VpnInstance> optionalVpn =
1584 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1586 if (optionalVpn.isPresent()) {
1589 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1590 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1593 } catch (ReadFailedException ex) {
1594 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1595 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1600 // if at least one succeeds; result is success
1601 // if none succeeds; result is failure
1602 if (failurecount + warningcount == vpns.size()) {
1603 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1605 List<String> errorResponseList = new ArrayList<>();
1606 if (!errorList.isEmpty()) {
1607 for (RpcError rpcError : errorList) {
1608 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1609 + ", ErrorMessage: " + rpcError.getMessage());
1612 errorResponseList.add("Operation successful with no errors");
1614 opBuilder.setResponse(errorResponseList);
1615 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1620 public void createVpnInstanceForSubnet(Uuid subnetId) {
1621 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1622 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1625 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1626 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1627 removeVpn(subnetId);
1630 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1631 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1632 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1633 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1635 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1636 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1639 if (vpnId != null) {
1640 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1641 if (vpnMap == null) {
1642 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1643 + " cannot add subnet {} to VPN", vpnId.getValue(),
1647 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1648 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1649 if (isVpnOfTypeL2(vpnInstance)) {
1650 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1651 NeutronEvpnUtils.Operation.ADD);
1654 if (internetVpnId != null) {
1655 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1656 if (vpnMap == null) {
1657 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1658 + "subnet {} to VPN", internetVpnId.getValue(),
1663 final Uuid internetId = internetVpnId;
1664 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1665 List<Uuid> portList = sn.getPortList();
1666 if (portList != null) {
1667 for (final Uuid portId : portList) {
1668 String vpnInfName = portId.getValue();
1669 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1670 Port port = neutronvpnUtils.getNeutronPort(portId);
1672 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1673 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1676 final Boolean isRouterInterface = port.getDeviceOwner()
1677 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1678 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1679 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1681 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1683 if (vpnIface == null) {
1684 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1685 Set<Uuid> listVpn = new HashSet<>();
1686 if (vpnId != null) {
1689 if (internetId != null) {
1690 listVpn.add(internetId);
1692 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1693 isRouterInterface, wrtConfigTxn);
1694 if (sn.getRouterId() != null) {
1695 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1698 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1699 if (vpnId != null) {
1700 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1702 if (internetId != null) {
1703 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1707 ListenableFutures.addErrorLogging(future, LOG,
1708 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1709 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1710 return Collections.singletonList(future);
1716 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1717 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1718 "removeSubnetFromVpn: at least one VPN must be not null");
1719 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1720 vpnId, internetVpnId);
1721 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1723 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1726 VpnMap vpnMap = null;
1727 VpnInstance vpnInstance = null;
1728 if (vpnId != null) {
1729 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1730 if (vpnMap == null) {
1731 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1732 vpnId.getValue(), subnet.getValue());
1735 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1737 if (internetVpnId == null) {
1738 internetVpnId = sn.getInternetVpnId();
1740 if (internetVpnId != null) {
1741 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1742 if (vpnMap == null) {
1743 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1744 + " from Internet VPN",
1745 internetVpnId.getValue(), subnet.getValue());
1749 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1750 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1751 NeutronEvpnUtils.Operation.DELETE);
1753 boolean subnetVpnAssociation = false;
1754 if (vpnId != null && sn.getVpnId() != null
1755 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1756 subnetVpnAssociation = true;
1757 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1758 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1759 subnetVpnAssociation = true;
1761 if (subnetVpnAssociation == false) {
1762 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1763 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1766 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1767 List<Uuid> portList = sn.getPortList();
1768 final Uuid internetId = internetVpnId;
1769 if (portList != null) {
1770 for (final Uuid portId : portList) {
1771 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1772 final Port port = neutronvpnUtils.getNeutronPort(portId);
1773 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1774 List<ListenableFuture<Void>> futures = new ArrayList<>();
1775 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1776 CONFIGURATION, tx -> {
1778 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1780 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1781 + " port is absent in Neutron config DS", portId.getValue(),
1785 ListenableFutures.addErrorLogging(future, LOG,
1786 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1787 + " belonging to subnet {} and vpnId {}",
1788 portId.getValue(), subnet.getValue(), vpnId.getValue());
1789 futures.add(future);
1794 //update subnet-vpn association
1795 removeFromSubnetNode(subnet, null, null, vpnId, null);
1798 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1799 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1800 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1802 Uuid internalVpnId = sm.getVpnId();
1803 if (internalVpnId == null) {
1804 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1805 sm.getId().getValue());
1808 if (isBeingAssociated) {
1809 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1811 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1814 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1815 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1816 if (isBeingAssociated) {
1817 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1818 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1820 removeInternetVpnFromVpnInterface(vpn,
1821 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1826 // Check for ports on this subnet and update association of
1827 // corresponding vpn-interfaces to internet vpn
1828 List<Uuid> portList = sm.getPortList();
1829 if (portList != null) {
1830 for (Uuid port : portList) {
1831 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1832 port.getValue(), isBeingAssociated);
1833 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1834 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1836 if (isBeingAssociated) {
1837 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1838 true, false, tx, true);
1840 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1848 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1849 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1850 oldVpnId.getValue(), newVpnId.getValue());
1851 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1852 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1853 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1854 Uuid vpnExtUuid = netIsExternal ? null
1855 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1856 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1858 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1861 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1862 * associated with internet BGP-VPN.
1864 if (vpnExtUuid != null) {
1865 /* Update V6 Internet default route match with new VPN metadata.
1866 * isBeingAssociated = true means oldVpnId is same as routerId
1867 * isBeingAssociated = false means newVpnId is same as routerId
1869 if (isBeingAssociated) {
1870 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1872 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1875 //Update Router Interface first synchronously.
1876 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1877 ListenableFuture<Void> future =
1878 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1879 tx -> updateVpnInterface(newVpnId, oldVpnId,
1880 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1881 isBeingAssociated, true, tx, false));
1882 Futures.addCallback(future, new FutureCallback<Void>() {
1884 public void onSuccess(Void result) {
1885 // Check for ports on this subnet and update association of
1886 // corresponding vpn-interfaces to external vpn
1887 List<Uuid> portList = sn.getPortList();
1888 if (portList != null) {
1889 for (Uuid port : portList) {
1890 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1891 port.getValue(), isBeingAssociated);
1892 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1893 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1894 tx -> updateVpnInterface(newVpnId, oldVpnId,
1895 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1902 public void onFailure(Throwable throwable) {
1904 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1906 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1908 }, MoreExecutors.directExecutor());
1913 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1914 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1915 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1918 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1919 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1920 final ReentrantLock lock = lockForUuid(routerId);
1923 Optional<RouterInterfaces> optRouterInterfaces =
1924 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1925 routerInterfacesId);
1926 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1927 .setInterfaceId(interfaceName).build();
1928 if (optRouterInterfaces.isPresent()) {
1929 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1930 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1932 // TODO Shouldn't we be doing something with builder and interfaces?
1933 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1934 // List<Interfaces> interfaces = new ArrayList<>();
1935 // interfaces.add(routerInterface);
1937 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1938 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1940 } catch (ReadFailedException | TransactionCommitFailedException e) {
1941 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1947 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1948 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1949 final ReentrantLock lock = lockForUuid(routerId);
1952 Optional<RouterInterfaces> optRouterInterfaces =
1953 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1954 routerInterfacesId);
1955 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1956 .setInterfaceId(interfaceName).build();
1957 if (optRouterInterfaces.isPresent()) {
1958 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1959 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
1960 if (interfaces != null && interfaces.remove(routerInterface)) {
1961 if (interfaces.isEmpty()) {
1962 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1963 routerInterfacesId);
1965 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1966 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1970 } catch (ReadFailedException | TransactionCommitFailedException e) {
1971 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1978 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1979 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1980 * route will be ignored.
1982 * @param vpnName the VPN identifier
1983 * @param interVpnLinkRoutes The list of static routes
1984 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1986 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1987 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1988 for (Routes route : interVpnLinkRoutes) {
1989 String nexthop = route.getNexthop().stringValue();
1990 String destination = route.getDestination().stringValue();
1991 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1992 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1993 AddStaticRouteInput rpcInput =
1994 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1995 .setVpnInstanceName(vpnName.getValue())
1997 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1998 RpcResult<AddStaticRouteOutput> rpcResult;
2000 rpcResult = labelOuputFtr.get();
2001 if (rpcResult.isSuccessful()) {
2002 LOG.debug("Label generated for destination {} is: {}",
2003 destination, rpcResult.getResult().getLabel());
2005 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
2006 destination, nexthop, rpcResult.getErrors());
2008 } catch (InterruptedException | ExecutionException e) {
2009 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
2010 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
2013 // Any other case is a fault.
2014 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2015 route.getDestination().stringValue(), nexthop);
2022 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2023 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2025 * @param vpnName the VPN identifier
2026 * @param interVpnLinkRoutes The list of static routes
2027 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2029 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2030 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2031 for (Routes route : interVpnLinkRoutes) {
2032 String nexthop = route.getNexthop().stringValue();
2033 String destination = route.getDestination().stringValue();
2034 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2035 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2036 RemoveStaticRouteInput rpcInput =
2037 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2038 .setVpnInstanceName(vpnName.getValue())
2041 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2042 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2044 // Any other case is a fault.
2045 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2046 route.getDestination().stringValue(), nexthop);
2053 * Returns true if the specified nexthop is the other endpoint in an
2054 * InterVpnLink, regarding one of the VPN's point of view.
2056 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2057 InterVpnLink interVpnLink) {
2059 interVpnLink != null
2060 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2061 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2062 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2063 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2067 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2068 List<Adjacency> adjList = new ArrayList<>();
2069 Map<String, List<String>> adjMap = new HashMap<>();
2070 for (Routes route : routeList) {
2071 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2072 LOG.error("Incorrect input received for extra route. {}", route);
2074 String nextHop = route.getNexthop().stringValue();
2075 String destination = route.getDestination().stringValue();
2076 if (!nextHop.equals(fixedIp)) {
2077 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2080 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2082 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2083 if (!hops.contains(nextHop)) {
2089 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2090 final String destination = entry.getKey();
2091 final List<String> ipList = entry.getValue();
2092 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2093 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2094 .withKey(new AdjacencyKey(destination)).build();
2100 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2101 checkAlarmExtraRoutes(vpnId, routeList);
2103 for (Routes route : routeList) {
2104 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2105 LOG.error("Incorrect input received for extra route. {}", route);
2107 String nextHop = route.getNexthop().stringValue();
2108 String destination = route.getDestination().stringValue();
2109 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2111 if (infName != null) {
2112 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2113 destination, vpnId.getValue(), nextHop, infName);
2114 boolean isLockAcquired = false;
2116 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2117 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2118 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2119 .child(Adjacency.class, new AdjacencyKey(destination));
2120 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2121 LogicalDatastoreType.CONFIGURATION, path);
2122 if (existingAdjacency.isPresent()
2123 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2124 LOG.error("The route with destination {} nextHop {} is already present as"
2125 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2126 destination, nextHop, infName);
2129 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2130 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2131 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2133 try (AcquireResult lock = tryInterfaceLock(infName)) {
2134 if (!lock.wasAcquired()) {
2135 // FIXME: why do we even bother with locking if we do not honor it?!
2136 logTryLockFailure(infName);
2139 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2142 } catch (TransactionCommitFailedException e) {
2143 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2144 destination, nextHop, e);
2145 } catch (ReadFailedException e) {
2146 LOG.error("Exception on reading data-store ", e);
2149 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2150 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2157 * This method setup or down an alarm about extra route fault.
2158 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2159 * available RDs, then an alarm and an error is generated.<br>
2160 * <b>Be careful</b> the routeList could be changed.
2162 * @param vpnId the vpnId of vpn to control.
2163 * @param routeList the list of router to check, it could be modified.
2165 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2166 if (!neutronvpnAlarm.isAlarmEnabled()) {
2167 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2170 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2171 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2172 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2176 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2177 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2178 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2182 for (Routes route : routeList) {
2183 // count the number of nexthops for each same route.getDestingation().getValue()
2184 String destination = route.getDestination().stringValue();
2185 String nextHop = route.getNexthop().stringValue();
2186 List<String> nextHopList = new ArrayList<>();
2187 nextHopList.add(nextHop);
2189 for (Routes routeTmp : routeList) {
2190 String routeDest = routeTmp.getDestination().stringValue();
2191 if (!destination.equals(routeDest)) {
2194 String routeNextH = routeTmp.getNexthop().stringValue();
2195 if (nextHop.equals(routeNextH)) {
2199 nextHopList.add(routeTmp.getNexthop().stringValue());
2201 final List<String> rdList = new ArrayList<>();
2202 if (vpnInstance.getIpv4Family() != null
2203 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2204 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2210 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2211 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2212 if (rd != null && !rdList.contains(rd)) {
2217 // 1. VPN Instance Name
2218 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2221 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2222 Uuid routerUuid = routerUuidList.get(0);
2223 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2224 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2226 // 3. List of RDs associated with the VPN
2227 detailsAlarm.append(" List of RDs associated with the VPN: ");
2228 for (String s : rdList) {
2229 detailsAlarm.append(s);
2230 detailsAlarm.append(", ");
2233 // 4. Prefix in question
2234 detailsAlarm.append(" for prefix: ");
2235 detailsAlarm.append(route.getDestination().stringValue());
2237 // 5. List of NHs for the prefix
2238 detailsAlarm.append(" for nextHops: ");
2239 for (String s : nextHopList) {
2240 detailsAlarm.append(s);
2241 detailsAlarm.append(", ");
2244 if (rdList.size() < nbNextHops) {
2245 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2247 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2252 // TODO Clean up the exception handling
2253 @SuppressWarnings("checkstyle:IllegalCatch")
2254 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2255 for (Routes route : routeList) {
2256 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2257 String nextHop = route.getNexthop().stringValue();
2258 String destination = route.getDestination().stringValue();
2259 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2261 if (infName == null) {
2262 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2263 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2264 // Proceed to remove the next extra-route
2267 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2268 destination, vpnId.getValue(), nextHop, infName);
2270 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2271 InstanceIdentifier.builder(VpnInterfaces.class)
2272 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2273 .augmentation(Adjacencies.class)
2274 .child(Adjacency.class, new AdjacencyKey(destination))
2278 // Looking for existing prefix in MDSAL database
2279 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2280 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2281 boolean updateNextHops = false;
2282 List<String> nextHopList = new ArrayList<>();
2283 if (adjacency.isPresent()) {
2284 List<String> nhListRead = adjacency.get().getNextHopIpList();
2285 if (nhListRead.size() > 1) { // ECMP case
2286 for (String nextHopRead : nhListRead) {
2287 if (nextHopRead.equals(nextHop)) {
2288 updateNextHops = true;
2290 nextHopList.add(nextHopRead);
2296 try (AcquireResult lock = tryInterfaceLock(infName)) {
2297 if (!lock.wasAcquired()) {
2298 // FIXME: why do we even bother with locking if we do not honor it?!
2299 logTryLockFailure(infName);
2302 if (updateNextHops) {
2303 // An update must be done, not including the current next hop
2304 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2305 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2306 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2307 .setNextHopIpList(nextHopList)
2308 .withKey(new AdjacencyKey(destination))
2310 Adjacencies erAdjs =
2311 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2312 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2313 .addAugmentation(Adjacencies.class, erAdjs).build();
2314 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2315 vpnIfIdentifier, vpnIf);
2317 // Remove the whole route
2318 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2319 adjacencyIdentifier);
2320 LOG.trace("extra route {} deleted successfully", route);
2323 } catch (TransactionCommitFailedException | ReadFailedException e) {
2324 LOG.error("exception in deleting extra route with destination {} for interface {}",
2325 destination, infName, e);
2328 LOG.error("Incorrect input received for extra route: {}", route);
2333 public void removeVpn(Uuid vpnId) {
2335 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2336 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2337 List<Uuid> routerUuidList = new ArrayList<>();
2338 // dissociate router
2339 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2340 for (RouterIds router : routerIdsList) {
2341 Uuid routerId = router.getRouterId();
2342 routerUuidList.add(routerId);
2343 dissociateRouterFromVpn(vpnId, routerId);
2346 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2347 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2349 // remove entire vpnMaps node
2350 deleteVpnMapsNode(vpnId);
2352 // remove vpn-instance
2353 deleteVpnInstance(vpnId);
2354 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2357 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2358 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2361 // TODO Clean up the exception handling
2362 @SuppressWarnings("checkstyle:IllegalCatch")
2363 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2364 updateVpnMaps(vpnId, null, routerId, null, null);
2365 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2366 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2367 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2368 for (Subnetmap sn : subMapList) {
2369 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2370 if (!ipVersion.isIpVersionChosen(ipVers)) {
2371 ipVersion = ipVersion.addVersion(ipVers);
2374 if (ipVersion != IpVersionChoice.UNDEFINED) {
2375 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2377 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2379 for (Subnetmap sn : subMapList) {
2380 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2384 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2385 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2386 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2387 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2388 for (Uuid subnet : routerSubnets) {
2389 IpVersionChoice version = NeutronvpnUtils
2390 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2391 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2392 addSubnetToVpn(vpnId, subnet, null);
2394 addSubnetToVpn(vpnId, subnet, internetVpnId);
2399 // TODO Clean up the exception handling
2400 @SuppressWarnings("checkstyle:IllegalCatch")
2401 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2403 clearFromVpnMaps(vpnId, routerId, null);
2404 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2405 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2406 for (Subnetmap sn : subMapList) {
2407 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2408 if (ipVersion.isIpVersionChosen(ipVers)) {
2409 ipVersion = ipVersion.addVersion(ipVers);
2411 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2412 routerId.getValue());
2413 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2415 if (ipVersion != IpVersionChoice.UNDEFINED) {
2416 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2418 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2424 * Parses and associates networks list with given VPN.
2426 * @param vpnId Uuid of given VPN.
2427 * @param networkList List list of network Ids (Uuid), which will be associated.
2428 * @return list of formatted strings with detailed error messages.
2431 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2432 List<String> failedNwList = new ArrayList<>();
2433 HashSet<Uuid> passedNwList = new HashSet<>();
2434 boolean isExternalNetwork = false;
2435 if (networkList.isEmpty()) {
2436 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2437 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2439 return failedNwList;
2441 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2442 if (vpnInstance == null) {
2443 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2444 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2445 + "in ConfigDS", vpnId.getValue()));
2446 return failedNwList;
2449 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2450 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2452 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2453 + "associated with", vpnId.getValue()));
2454 return failedNwList;
2456 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2457 for (Uuid nw : networkList) {
2458 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2459 if (network == null) {
2460 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2461 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2465 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2466 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2467 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2468 nw.getValue(), vpnId.getValue());
2469 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2470 nw.getValue(), vpnId.getValue()));
2473 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2474 if (networkVpnId != null) {
2475 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2476 nw.getValue(), networkVpnId.getValue());
2477 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2478 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2481 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2482 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2483 nw.getValue(), vpnId.getValue());
2484 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2485 nw.getValue(), vpnId.getValue()));
2488 if (NeutronvpnUtils.getIsExternal(network)) {
2489 isExternalNetwork = true;
2491 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2492 if (subnetmapList == null || subnetmapList.isEmpty()) {
2493 passedNwList.add(nw);
2496 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2499 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2500 for (Subnetmap subnetmap : subnetmapList) {
2501 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2502 if (!ipVersion.isIpVersionChosen(ipVers)) {
2503 ipVersion = ipVersion.addVersion(ipVers);
2506 if (ipVersion != IpVersionChoice.UNDEFINED) {
2507 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2508 + " for VPN {} ", ipVersion, vpnId);
2509 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2511 for (Subnetmap subnetmap : subnetmapList) {
2512 Uuid subnetId = subnetmap.getId();
2513 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2514 if (subnetVpnId != null) {
2515 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2516 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2517 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2518 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2521 if (!NeutronvpnUtils.getIsExternal(network)) {
2522 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2524 addSubnetToVpn(vpnId, subnetId, null);
2525 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2527 passedNwList.add(nw);
2530 passedNwList.add(nw);
2532 } catch (ReadFailedException e) {
2533 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2535 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2538 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2539 if (!isExternalNetwork) {
2540 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2542 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2543 return failedNwList;
2546 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2547 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2550 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2551 if (vpnOpDataEntry == null) {
2552 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2555 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2556 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2557 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2559 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2560 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2561 updateVpnMaps(vpnId, null, null, null, extNwList);
2562 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2563 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2564 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2566 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2569 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2570 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2573 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2574 updateVpnInternetForSubnet(sm, vpnId, true);
2576 if (!ipVersion.isIpVersionChosen(ipVers)) {
2577 ipVersion = ipVersion.addVersion(ipVers);
2580 if (ipVersion != IpVersionChoice.UNDEFINED) {
2581 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2582 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2583 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2589 * Parses and disassociates networks list from given VPN.
2591 * @param vpnId Uuid of given VPN.
2592 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2593 * @return list of formatted strings with detailed error messages.
2596 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2597 List<String> failedNwList = new ArrayList<>();
2598 HashSet<Uuid> passedNwList = new HashSet<>();
2599 if (networkList.isEmpty()) {
2600 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2601 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2603 return failedNwList;
2605 for (Uuid nw : networkList) {
2606 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2607 if (networkSubnets == null) {
2608 passedNwList.add(nw);
2611 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2612 if (network == null) {
2613 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2614 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2618 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2619 if (networkVpnId == null) {
2620 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2621 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2625 if (!vpnId.equals(networkVpnId)) {
2626 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2627 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2628 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2629 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2633 if (NeutronvpnUtils.getIsExternal(network)) {
2634 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2635 passedNwList.add(nw);
2637 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2638 nw.getValue(), vpnId.getValue());
2639 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2644 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2645 for (Uuid subnet : networkSubnets) {
2646 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2647 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2648 if (!ipVersion.isIpVersionChosen(ipVers)) {
2649 ipVersion = ipVersion.addVersion(ipVers);
2651 if (!NeutronvpnUtils.getIsExternal(network)) {
2652 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2654 removeSubnetFromVpn(vpnId, subnet, null);
2655 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2656 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2658 passedNwList.add(nw);
2661 if (ipVersion != IpVersionChoice.UNDEFINED) {
2662 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2663 + " for VPN {}", ipVersion, vpnId);
2664 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2667 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2668 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2669 passedNwList, vpnId.getValue());
2670 return failedNwList;
2673 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2674 if (!removeExternalNetworkFromVpn(extNet)) {
2677 // check, if there is another Provider Networks associated with given VPN
2678 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2679 if (vpnNets != null) {
2680 //Remove currently disassociated network from the list
2681 vpnNets.remove(extNet.getUuid());
2682 for (Uuid netId : vpnNets) {
2683 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2684 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2685 + "{}", vpnId.getValue(), netId.getValue());
2690 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2691 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2692 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2693 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2694 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2695 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2696 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2698 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2701 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2702 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2705 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2706 updateVpnInternetForSubnet(sm, vpnId, false);
2708 if (!ipVersion.isIpVersionChosen(ipVers)) {
2709 ipVersion = ipVersion.addVersion(ipVers);
2712 if (ipVersion != IpVersionChoice.UNDEFINED) {
2713 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2714 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2716 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2722 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2725 // TODO Clean up the exception handling
2726 @SuppressWarnings("checkstyle:IllegalCatch")
2727 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2729 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2730 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2731 StringBuilder returnMsg = new StringBuilder();
2732 Uuid vpnId = input.getVpnId();
2735 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2736 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2737 input.getNetworkId());
2738 List<Uuid> netIds = input.getNetworkId();
2739 if (netIds != null && !netIds.isEmpty()) {
2740 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2741 if (!failed.isEmpty()) {
2742 returnMsg.append(failed);
2746 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2748 if (returnMsg.length() != 0) {
2749 opBuilder.setResponse(
2750 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2751 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2752 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2754 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2756 } catch (Exception ex) {
2757 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2758 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2759 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2760 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2762 LOG.debug("associateNetworks returns..");
2767 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2770 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2772 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2773 LOG.debug("associateRouter {}", input);
2774 StringBuilder returnMsg = new StringBuilder();
2775 Uuid vpnId = input.getVpnId();
2776 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2777 routerIds = input.getRouterIds();
2778 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2779 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2780 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2781 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2782 .RouterIds routerId : routerIds) {
2783 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2784 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2785 if (vpnMap != null) {
2787 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2788 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2789 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2790 .append(routerId.getRouterId());
2791 } else if (extVpnId != null) {
2792 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2793 + "another VPN ").append(extVpnId.getValue());
2795 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2796 routerId.getRouterId());
2797 associateRouterToVpn(vpnId, routerId.getRouterId());
2800 returnMsg.append("router not found : ").append(routerId.getRouterId());
2803 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2805 if (returnMsg.length() != 0) {
2806 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2807 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2808 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2810 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2813 LOG.debug("associateRouter returns..");
2818 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2821 // TODO Clean up the exception handling
2822 @SuppressWarnings("checkstyle:IllegalCatch")
2823 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2824 GetFixedIPsForNeutronPortInput input) {
2825 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2826 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2827 Uuid portId = input.getPortId();
2828 StringBuilder returnMsg = new StringBuilder();
2830 List<String> fixedIPList = new ArrayList<>();
2831 Port port = neutronvpnUtils.getNeutronPort(portId);
2833 for (FixedIps ip : port.nonnullFixedIps()) {
2834 fixedIPList.add(ip.getIpAddress().stringValue());
2837 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2839 if (returnMsg.length() != 0) {
2840 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2842 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2843 returnMsg)).build());
2845 opBuilder.setFixedIPs(fixedIPList);
2846 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2848 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2850 } catch (Exception ex) {
2851 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2852 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2853 portId.getValue(), ex.getMessage(), ex)).build());
2859 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2862 // TODO Clean up the exception handling
2863 @SuppressWarnings("checkstyle:IllegalCatch")
2864 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2866 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2867 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2869 LOG.debug("dissociateNetworks {}", input);
2870 StringBuilder returnMsg = new StringBuilder();
2871 Uuid vpnId = input.getVpnId();
2874 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2875 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2876 input.getNetworkId());
2877 List<Uuid> netIds = input.getNetworkId();
2878 if (netIds != null && !netIds.isEmpty()) {
2879 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2880 if (!failed.isEmpty()) {
2881 returnMsg.append(failed);
2885 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2887 if (returnMsg.length() != 0) {
2888 opBuilder.setResponse(
2889 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2890 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2892 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2894 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2896 } catch (Exception ex) {
2897 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2898 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2899 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2901 LOG.debug("dissociateNetworks returns..");
2906 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2909 // TODO Clean up the exception handling
2910 @SuppressWarnings("checkstyle:IllegalCatch")
2911 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2913 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2915 LOG.debug("dissociateRouter {}", input);
2916 StringBuilder returnMsg = new StringBuilder();
2917 Uuid vpnId = input.getVpnId();
2918 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2919 .RouterIds> routerIdList = input.getRouterIds();
2920 String routerIdsString = "";
2921 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2922 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2923 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2924 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2925 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2926 .RouterIds routerId : routerIdList) {
2928 if (routerId != null) {
2929 routerIdsString += routerId.getRouterId() + ", ";
2930 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2932 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2933 if (routerVpnId == null) {
2934 returnMsg.append("input router ").append(routerId.getRouterId())
2935 .append(" not associated to any vpn yet");
2936 } else if (vpnId.equals(routerVpnId)) {
2937 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2939 returnMsg.append("input router ").append(routerId.getRouterId())
2940 .append(" associated to vpn ")
2941 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2944 returnMsg.append("router not found : ").append(routerId.getRouterId());
2947 if (returnMsg.length() != 0) {
2948 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2949 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2950 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2951 returnMsg)).build());
2953 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2955 } catch (Exception ex) {
2956 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2957 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2958 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2962 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2965 LOG.debug("dissociateRouter returns..");
2969 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2970 // check if the router is associated to some VPN
2971 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2972 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2973 if (vpnId != null) {
2974 // remove existing external vpn interfaces
2975 for (Uuid subnetId : routerSubnetIds) {
2976 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2978 clearFromVpnMaps(vpnId, routerId, null);
2980 // remove existing internal vpn interfaces
2981 for (Uuid subnetId : routerSubnetIds) {
2982 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2985 // delete entire vpnMaps node for internal VPN
2986 deleteVpnMapsNode(routerId);
2988 // delete vpn-instance for internal VPN
2989 deleteVpnInstance(routerId);
2992 protected Subnet getNeutronSubnet(Uuid subnetId) {
2993 return neutronvpnUtils.getNeutronSubnet(subnetId);
2997 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2998 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
3000 return sn.getGatewayIp();
3006 protected Network getNeutronNetwork(Uuid networkId) {
3007 return neutronvpnUtils.getNeutronNetwork(networkId);
3010 protected Port getNeutronPort(String name) {
3011 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3014 protected Port getNeutronPort(Uuid portId) {
3015 return neutronvpnUtils.getNeutronPort(portId);
3018 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3019 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3022 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3023 return neutronvpnUtils.getNetworksForVpn(vpnId);
3027 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3029 * @return a List of String to be printed on screen
3030 * @throws ReadFailedException if there was a problem reading from the data store
3032 public List<String> showNeutronPortsCLI() throws ReadFailedException {
3033 List<String> result = new ArrayList<>();
3034 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3036 result.add("-------------------------------------------------------------------------------------------");
3037 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3039 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3040 if (ports.isPresent() && ports.get().getPort() != null) {
3041 for (Port port : ports.get().nonnullPort()) {
3042 List<FixedIps> fixedIPs = port.getFixedIps();
3043 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3044 List<String> ipList = new ArrayList<>();
3045 for (FixedIps fixedIp : fixedIPs) {
3046 IpAddress ipAddress = fixedIp.getIpAddress();
3047 if (ipAddress.getIpv4Address() != null) {
3048 ipList.add(ipAddress.getIpv4Address().getValue());
3050 ipList.add(ipAddress.getIpv6Address().getValue());
3053 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3054 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3055 ipList.toString()));
3057 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3058 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3067 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3069 * @param vpnuuid Uuid of the VPN whose config must be shown
3070 * @return formatted output list
3071 * @throws InterruptedException if there was a thread related problem getting the data to display
3072 * @throws ExecutionException if there was any other problem getting the data to display
3074 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3075 List<String> result = new ArrayList<>();
3076 if (vpnuuid == null) {
3078 result.add("Displaying VPN config for all VPNs");
3079 result.add("To display VPN config for a particular VPN, use the following syntax");
3080 result.add(getshowVpnConfigCLIHelp());
3082 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3083 if (rpcResult.isSuccessful()) {
3085 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3087 result.add(String.format(" %-80s ", "Import-RTs"));
3089 result.add(String.format(" %-80s ", "Export-RTs"));
3091 result.add(String.format(" %-76s ", "Subnet IDs"));
3093 result.add("------------------------------------------------------------------------------------");
3095 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3096 rpcResult.getResult().nonnullL3vpnInstances()) {
3097 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3099 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3100 vpn.getRouteDistinguisher()));
3102 result.add(String.format(" %-80s ", vpn.getImportRT()));
3104 result.add(String.format(" %-80s ", vpn.getExportRT()));
3107 Uuid vpnid = vpn.getId();
3108 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3109 if (!subnetList.isEmpty()) {
3110 for (Uuid subnetuuid : subnetList) {
3111 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3114 result.add(String.format(" %-76s ", "\" \""));
3117 result.add("----------------------------------------");
3121 String errortag = rpcResult.getErrors().iterator().next().getTag();
3122 if (Objects.equals(errortag, "")) {
3124 result.add("No VPN has been configured yet");
3125 } else if (Objects.equals(errortag, "invalid-value")) {
3127 result.add("VPN " + vpnuuid.getValue() + " is not present");
3129 result.add("error getting VPN info : " + rpcResult.getErrors());
3130 result.add(getshowVpnConfigCLIHelp());
3136 protected void createExternalVpnInterfaces(Uuid extNetId) {
3137 if (extNetId == null) {
3138 LOG.error("createExternalVpnInterfaces: external network is null");
3142 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3143 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3144 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3148 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3149 for (String elanInterface : extElanInterfaces) {
3150 createExternalVpnInterface(extNetId, elanInterface, tx);
3152 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3155 // TODO Clean up the exception handling
3156 @SuppressWarnings("checkstyle:IllegalCatch")
3157 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3158 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3159 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3160 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3163 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3164 for (String elanInterface : extElanInterfaces) {
3165 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3166 .buildVpnInterfaceIdentifier(elanInterface);
3167 LOG.info("Removing vpn interface {}", elanInterface);
3168 tx.delete(vpnIfIdentifier);
3170 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3173 private void createExternalVpnInterface(Uuid vpnId, String infName,
3174 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3175 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3176 false /* not a router iface */, wrtConfigTxn);
3179 // TODO Clean up the exception handling
3180 @SuppressWarnings("checkstyle:IllegalCatch")
3181 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3182 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3183 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3184 if (vpnIdList.isEmpty() || infName == null) {
3185 LOG.error("vpnid is empty or interface({}) is null", infName);
3188 if (wrtConfigTxn == null) {
3189 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3190 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3191 "Error writing VPN interface");
3194 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3195 for (Uuid vpnId: vpnIdList) {
3196 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3197 AssociatedSubnetType.V4AndV6Subnets);
3198 vpnIdListStruct.add(vpnInstance);
3201 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3202 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3204 .setVpnInstanceNames(vpnIdListStruct)
3205 .setRouterInterface(isRouterInterface);
3206 LOG.info("Network Id is {}", networkUuid);
3207 if (networkUuid != null) {
3208 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3209 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3210 NetworkAttributes.NetworkType networkType = providerType != null
3211 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3212 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3213 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3214 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3217 if (adjacencies != null) {
3218 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3220 VpnInterface vpnIf = vpnb.build();
3222 LOG.info("Creating vpn interface {}", vpnIf);
3223 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3224 } catch (Exception ex) {
3225 LOG.error("Creation of vpninterface {} failed", infName, ex);
3229 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3230 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3231 if (vpnId == null || infName == null) {
3232 LOG.error("vpn id or interface is null");
3235 if (wrtConfigTxn == null) {
3236 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3237 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3238 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3239 }), LOG, "Error updating VPN interface with adjacencies");
3243 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3245 try (AcquireResult lock = tryInterfaceLock(infName)) {
3246 if (!lock.wasAcquired()) {
3247 // FIXME: why do we even bother with locking if we do not honor it?!
3248 logTryLockFailure(infName);
3252 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3253 .syncReadOptional(dataBroker, LogicalDatastoreType
3254 .CONFIGURATION, vpnIfIdentifier);
3255 if (optionalVpnInterface.isPresent()) {
3256 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3257 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3259 if (adjacencies == null) {
3262 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3263 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3264 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3265 optionalVpnInterface.get().getVpnInstanceNames());
3266 if (listVpnInstances.isEmpty()
3267 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3268 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3269 AssociatedSubnetType.V4AndV6Subnets);
3270 listVpnInstances.add(vpnInstance);
3271 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3274 VpnInstanceNames vpnInstance = VpnHelper
3275 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3276 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3277 listVpnInstances.add(vpnInstance);
3278 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3280 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3281 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3283 } catch (IllegalStateException | ReadFailedException ex) {
3284 // FIXME: why are we catching IllegalStateException here?
3285 LOG.error("Update of vpninterface {} failed", infName, ex);
3290 private String getshowVpnConfigCLIHelp() {
3291 StringBuilder help = new StringBuilder("Usage:");
3292 help.append("display vpn-config [-vid/--vpnid <id>]");
3293 return help.toString();
3296 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3297 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3301 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3302 return neutronEvpnManager.createEVPN(input);
3306 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3307 return neutronEvpnManager.getEVPN(input);
3311 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3312 return neutronEvpnManager.deleteEVPN(input);
3315 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3316 Uuid extNetId = extNet.getUuid();
3317 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3318 .child(Networks.class, new NetworksKey(extNetId)).build();
3321 Optional<Networks> optionalExtNets =
3322 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3324 if (!optionalExtNets.isPresent()) {
3325 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3326 extNetId.getValue());
3329 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3330 builder.setVpnid(vpnId);
3331 Networks networks = builder.build();
3332 // Add Networks object to the ExternalNetworks list
3333 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3334 extNetId.getValue());
3335 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3338 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3339 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3340 extNetId.getValue(), ex);
3345 private boolean removeExternalNetworkFromVpn(Network extNet) {
3346 Uuid extNetId = extNet.getUuid();
3347 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3348 .child(Networks.class, new NetworksKey(extNetId)).build();
3350 Optional<Networks> optionalNets =
3351 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3353 NetworksBuilder builder = null;
3354 if (optionalNets.isPresent()) {
3355 builder = new NetworksBuilder(optionalNets.get());
3357 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3358 extNetId.getValue());
3361 builder.setVpnid(null);
3362 Networks networks = builder.build();
3363 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3364 extNetId.getValue());
3365 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3367 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3368 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3369 extNetId.getValue(), ex);
3374 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3375 Optional<String> existingVpnName = Optional.of(primaryRd);
3376 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3378 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3379 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3380 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3381 } catch (ReadFailedException e) {
3382 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3384 /*Read failed. We don't know if a VPN exists or not.
3385 * Return primaryRd to halt caller execution, to be safe.*/
3386 return existingVpnName;
3388 if (vpnInstanceOpDataOptional.isPresent()) {
3389 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3391 existingVpnName = Optional.absent();
3393 return existingVpnName;
3396 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3397 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3400 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3401 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3404 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3405 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3408 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3409 String message = tuple.getMessage();
3410 logger.accept(message);
3414 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3415 @NonNull Subnetmap subnetMap) {
3416 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3417 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3418 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3419 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3420 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3421 subnetMap.getId().getValue(), internetVpnId.getValue());
3425 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3426 @NonNull Subnetmap subnetMap) {
3427 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3428 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3431 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3432 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3433 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3434 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3435 internetVpnId.getValue(), routerId.getValue());
3436 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3442 private AcquireResult tryInterfaceLock(final String infName) {
3443 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3447 private AcquireResult tryVpnLock(final Uuid vpnId) {
3448 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3451 private static ReentrantLock lockForUuid(Uuid uuid) {
3452 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3453 return JvmGlobalLocks.getLockForString(uuid.getValue());
3456 private static void logTryLockFailure(Object objectId) {
3457 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());