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 if (vpnMap != null) {
2337 List<RouterIds> routerIdsList = vpnMap.getRouterIds();
2338 List<Uuid> routerUuidList = new ArrayList<>();
2339 // dissociate router
2340 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2341 for (RouterIds router : routerIdsList) {
2342 Uuid routerId = router.getRouterId();
2343 routerUuidList.add(routerId);
2344 dissociateRouterFromVpn(vpnId, routerId);
2347 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2348 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2351 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2353 // remove entire vpnMaps node
2354 deleteVpnMapsNode(vpnId);
2356 // remove vpn-instance
2357 deleteVpnInstance(vpnId);
2358 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2361 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2362 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2365 // TODO Clean up the exception handling
2366 @SuppressWarnings("checkstyle:IllegalCatch")
2367 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2368 updateVpnMaps(vpnId, null, routerId, null, null);
2369 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2370 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2371 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2372 for (Subnetmap sn : subMapList) {
2373 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2374 if (!ipVersion.isIpVersionChosen(ipVers)) {
2375 ipVersion = ipVersion.addVersion(ipVers);
2378 if (ipVersion != IpVersionChoice.UNDEFINED) {
2379 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2381 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2383 for (Subnetmap sn : subMapList) {
2384 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2388 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2389 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2390 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2391 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2392 for (Uuid subnet : routerSubnets) {
2393 IpVersionChoice version = NeutronvpnUtils
2394 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2395 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2396 addSubnetToVpn(vpnId, subnet, null);
2398 addSubnetToVpn(vpnId, subnet, internetVpnId);
2403 // TODO Clean up the exception handling
2404 @SuppressWarnings("checkstyle:IllegalCatch")
2405 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2407 clearFromVpnMaps(vpnId, routerId, null);
2408 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2409 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2410 for (Subnetmap sn : subMapList) {
2411 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2412 if (ipVersion.isIpVersionChosen(ipVers)) {
2413 ipVersion = ipVersion.addVersion(ipVers);
2415 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2416 routerId.getValue());
2417 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2419 if (ipVersion != IpVersionChoice.UNDEFINED) {
2420 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2422 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2428 * Parses and associates networks list with given VPN.
2430 * @param vpnId Uuid of given VPN.
2431 * @param networkList List list of network Ids (Uuid), which will be associated.
2432 * @return list of formatted strings with detailed error messages.
2435 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2436 List<String> failedNwList = new ArrayList<>();
2437 HashSet<Uuid> passedNwList = new HashSet<>();
2438 boolean isExternalNetwork = false;
2439 if (networkList.isEmpty()) {
2440 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2441 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2443 return failedNwList;
2445 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2446 if (vpnInstance == null) {
2447 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2448 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2449 + "in ConfigDS", vpnId.getValue()));
2450 return failedNwList;
2453 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2454 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2456 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2457 + "associated with", vpnId.getValue()));
2458 return failedNwList;
2460 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2461 for (Uuid nw : networkList) {
2462 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2463 if (network == null) {
2464 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2465 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2469 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2470 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2471 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2472 nw.getValue(), vpnId.getValue());
2473 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2474 nw.getValue(), vpnId.getValue()));
2477 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2478 if (networkVpnId != null) {
2479 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2480 nw.getValue(), networkVpnId.getValue());
2481 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2482 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2485 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2486 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2487 nw.getValue(), vpnId.getValue());
2488 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2489 nw.getValue(), vpnId.getValue()));
2492 if (NeutronvpnUtils.getIsExternal(network)) {
2493 isExternalNetwork = true;
2495 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2496 if (subnetmapList == null || subnetmapList.isEmpty()) {
2497 passedNwList.add(nw);
2500 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2503 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2504 for (Subnetmap subnetmap : subnetmapList) {
2505 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2506 if (!ipVersion.isIpVersionChosen(ipVers)) {
2507 ipVersion = ipVersion.addVersion(ipVers);
2510 if (ipVersion != IpVersionChoice.UNDEFINED) {
2511 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2512 + " for VPN {} ", ipVersion, vpnId);
2513 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2515 for (Subnetmap subnetmap : subnetmapList) {
2516 Uuid subnetId = subnetmap.getId();
2517 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2518 if (subnetVpnId != null) {
2519 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2520 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2521 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2522 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2525 if (!NeutronvpnUtils.getIsExternal(network)) {
2526 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2528 addSubnetToVpn(vpnId, subnetId, null);
2529 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2531 passedNwList.add(nw);
2534 passedNwList.add(nw);
2536 } catch (ReadFailedException e) {
2537 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2539 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2542 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2543 if (!isExternalNetwork) {
2544 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2546 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2547 return failedNwList;
2550 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2551 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2554 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2555 if (vpnOpDataEntry == null) {
2556 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2559 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2560 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2561 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2563 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2564 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2565 updateVpnMaps(vpnId, null, null, null, extNwList);
2566 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2567 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2568 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2570 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2573 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2574 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2577 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2578 updateVpnInternetForSubnet(sm, vpnId, true);
2580 if (!ipVersion.isIpVersionChosen(ipVers)) {
2581 ipVersion = ipVersion.addVersion(ipVers);
2584 if (ipVersion != IpVersionChoice.UNDEFINED) {
2585 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2586 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2587 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2593 * Parses and disassociates networks list from given VPN.
2595 * @param vpnId Uuid of given VPN.
2596 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2597 * @return list of formatted strings with detailed error messages.
2600 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2601 List<String> failedNwList = new ArrayList<>();
2602 HashSet<Uuid> passedNwList = new HashSet<>();
2603 if (networkList.isEmpty()) {
2604 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2605 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2607 return failedNwList;
2609 for (Uuid nw : networkList) {
2610 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2611 if (networkSubnets == null) {
2612 passedNwList.add(nw);
2615 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2616 if (network == null) {
2617 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2618 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2622 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2623 if (networkVpnId == null) {
2624 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2625 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2629 if (!vpnId.equals(networkVpnId)) {
2630 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2631 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2632 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2633 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2637 if (NeutronvpnUtils.getIsExternal(network)) {
2638 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2639 passedNwList.add(nw);
2641 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2642 nw.getValue(), vpnId.getValue());
2643 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2648 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2649 for (Uuid subnet : networkSubnets) {
2650 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2651 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2652 if (!ipVersion.isIpVersionChosen(ipVers)) {
2653 ipVersion = ipVersion.addVersion(ipVers);
2655 if (!NeutronvpnUtils.getIsExternal(network)) {
2656 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2658 removeSubnetFromVpn(vpnId, subnet, null);
2659 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2660 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2662 passedNwList.add(nw);
2665 if (ipVersion != IpVersionChoice.UNDEFINED) {
2666 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2667 + " for VPN {}", ipVersion, vpnId);
2668 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2671 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2672 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2673 passedNwList, vpnId.getValue());
2674 return failedNwList;
2677 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2678 if (!removeExternalNetworkFromVpn(extNet)) {
2681 // check, if there is another Provider Networks associated with given VPN
2682 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2683 if (vpnNets != null) {
2684 //Remove currently disassociated network from the list
2685 vpnNets.remove(extNet.getUuid());
2686 for (Uuid netId : vpnNets) {
2687 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2688 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2689 + "{}", vpnId.getValue(), netId.getValue());
2694 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2695 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2696 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2697 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2698 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2699 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2700 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2702 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2705 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2706 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2709 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2710 updateVpnInternetForSubnet(sm, vpnId, false);
2712 if (!ipVersion.isIpVersionChosen(ipVers)) {
2713 ipVersion = ipVersion.addVersion(ipVers);
2716 if (ipVersion != IpVersionChoice.UNDEFINED) {
2717 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2718 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2720 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2726 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2729 // TODO Clean up the exception handling
2730 @SuppressWarnings("checkstyle:IllegalCatch")
2731 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2733 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2734 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2735 StringBuilder returnMsg = new StringBuilder();
2736 Uuid vpnId = input.getVpnId();
2739 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2740 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2741 input.getNetworkId());
2742 List<Uuid> netIds = input.getNetworkId();
2743 if (netIds != null && !netIds.isEmpty()) {
2744 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2745 if (!failed.isEmpty()) {
2746 returnMsg.append(failed);
2750 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2752 if (returnMsg.length() != 0) {
2753 opBuilder.setResponse(
2754 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2755 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2756 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2758 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2760 } catch (Exception ex) {
2761 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2762 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2763 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2764 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2766 LOG.debug("associateNetworks returns..");
2771 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2774 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2776 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2777 LOG.debug("associateRouter {}", input);
2778 StringBuilder returnMsg = new StringBuilder();
2779 Uuid vpnId = input.getVpnId();
2780 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2781 routerIds = input.getRouterIds();
2782 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2783 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2784 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2785 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2786 .RouterIds routerId : routerIds) {
2787 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2788 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2789 if (vpnMap != null) {
2791 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2792 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2793 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2794 .append(routerId.getRouterId());
2795 } else if (extVpnId != null) {
2796 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2797 + "another VPN ").append(extVpnId.getValue());
2799 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2800 routerId.getRouterId());
2801 associateRouterToVpn(vpnId, routerId.getRouterId());
2804 returnMsg.append("router not found : ").append(routerId.getRouterId());
2807 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2809 if (returnMsg.length() != 0) {
2810 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2811 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2812 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2814 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2817 LOG.debug("associateRouter returns..");
2822 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2825 // TODO Clean up the exception handling
2826 @SuppressWarnings("checkstyle:IllegalCatch")
2827 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2828 GetFixedIPsForNeutronPortInput input) {
2829 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2830 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2831 Uuid portId = input.getPortId();
2832 StringBuilder returnMsg = new StringBuilder();
2834 List<String> fixedIPList = new ArrayList<>();
2835 Port port = neutronvpnUtils.getNeutronPort(portId);
2837 for (FixedIps ip : port.nonnullFixedIps()) {
2838 fixedIPList.add(ip.getIpAddress().stringValue());
2841 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2843 if (returnMsg.length() != 0) {
2844 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2846 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2847 returnMsg)).build());
2849 opBuilder.setFixedIPs(fixedIPList);
2850 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2852 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2854 } catch (Exception ex) {
2855 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2856 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2857 portId.getValue(), ex.getMessage(), ex)).build());
2863 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2866 // TODO Clean up the exception handling
2867 @SuppressWarnings("checkstyle:IllegalCatch")
2868 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2870 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2871 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2873 LOG.debug("dissociateNetworks {}", input);
2874 StringBuilder returnMsg = new StringBuilder();
2875 Uuid vpnId = input.getVpnId();
2878 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2879 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2880 input.getNetworkId());
2881 List<Uuid> netIds = input.getNetworkId();
2882 if (netIds != null && !netIds.isEmpty()) {
2883 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2884 if (!failed.isEmpty()) {
2885 returnMsg.append(failed);
2889 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2891 if (returnMsg.length() != 0) {
2892 opBuilder.setResponse(
2893 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2894 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2896 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2898 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2900 } catch (Exception ex) {
2901 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2902 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2903 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2905 LOG.debug("dissociateNetworks returns..");
2910 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2913 // TODO Clean up the exception handling
2914 @SuppressWarnings("checkstyle:IllegalCatch")
2915 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2917 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2919 LOG.debug("dissociateRouter {}", input);
2920 StringBuilder returnMsg = new StringBuilder();
2921 Uuid vpnId = input.getVpnId();
2922 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2923 .RouterIds> routerIdList = input.getRouterIds();
2924 String routerIdsString = "";
2925 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2926 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2927 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2928 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2929 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2930 .RouterIds routerId : routerIdList) {
2932 if (routerId != null) {
2933 routerIdsString += routerId.getRouterId() + ", ";
2934 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2936 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2937 if (routerVpnId == null) {
2938 returnMsg.append("input router ").append(routerId.getRouterId())
2939 .append(" not associated to any vpn yet");
2940 } else if (vpnId.equals(routerVpnId)) {
2941 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2943 returnMsg.append("input router ").append(routerId.getRouterId())
2944 .append(" associated to vpn ")
2945 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2948 returnMsg.append("router not found : ").append(routerId.getRouterId());
2951 if (returnMsg.length() != 0) {
2952 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2953 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2954 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2955 returnMsg)).build());
2957 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2959 } catch (Exception ex) {
2960 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2961 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2962 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2966 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2969 LOG.debug("dissociateRouter returns..");
2973 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2974 // check if the router is associated to some VPN
2975 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2976 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2977 if (vpnId != null) {
2978 // remove existing external vpn interfaces
2979 for (Uuid subnetId : routerSubnetIds) {
2980 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2982 clearFromVpnMaps(vpnId, routerId, null);
2984 // remove existing internal vpn interfaces
2985 for (Uuid subnetId : routerSubnetIds) {
2986 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2989 // delete entire vpnMaps node for internal VPN
2990 deleteVpnMapsNode(routerId);
2992 // delete vpn-instance for internal VPN
2993 deleteVpnInstance(routerId);
2996 protected Subnet getNeutronSubnet(Uuid subnetId) {
2997 return neutronvpnUtils.getNeutronSubnet(subnetId);
3001 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
3002 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
3004 return sn.getGatewayIp();
3010 protected Network getNeutronNetwork(Uuid networkId) {
3011 return neutronvpnUtils.getNeutronNetwork(networkId);
3014 protected Port getNeutronPort(String name) {
3015 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3018 protected Port getNeutronPort(Uuid portId) {
3019 return neutronvpnUtils.getNeutronPort(portId);
3022 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3023 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3026 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3027 return neutronvpnUtils.getNetworksForVpn(vpnId);
3031 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3033 * @return a List of String to be printed on screen
3034 * @throws ReadFailedException if there was a problem reading from the data store
3036 public List<String> showNeutronPortsCLI() throws ReadFailedException {
3037 List<String> result = new ArrayList<>();
3038 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3040 result.add("-------------------------------------------------------------------------------------------");
3041 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3043 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3044 if (ports.isPresent() && ports.get().getPort() != null) {
3045 for (Port port : ports.get().nonnullPort()) {
3046 List<FixedIps> fixedIPs = port.getFixedIps();
3047 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3048 List<String> ipList = new ArrayList<>();
3049 for (FixedIps fixedIp : fixedIPs) {
3050 IpAddress ipAddress = fixedIp.getIpAddress();
3051 if (ipAddress.getIpv4Address() != null) {
3052 ipList.add(ipAddress.getIpv4Address().getValue());
3054 ipList.add(ipAddress.getIpv6Address().getValue());
3057 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3058 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3059 ipList.toString()));
3061 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3062 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3071 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3073 * @param vpnuuid Uuid of the VPN whose config must be shown
3074 * @return formatted output list
3075 * @throws InterruptedException if there was a thread related problem getting the data to display
3076 * @throws ExecutionException if there was any other problem getting the data to display
3078 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3079 List<String> result = new ArrayList<>();
3080 if (vpnuuid == null) {
3082 result.add("Displaying VPN config for all VPNs");
3083 result.add("To display VPN config for a particular VPN, use the following syntax");
3084 result.add(getshowVpnConfigCLIHelp());
3086 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3087 if (rpcResult.isSuccessful()) {
3089 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3091 result.add(String.format(" %-80s ", "Import-RTs"));
3093 result.add(String.format(" %-80s ", "Export-RTs"));
3095 result.add(String.format(" %-76s ", "Subnet IDs"));
3097 result.add("------------------------------------------------------------------------------------");
3099 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3100 rpcResult.getResult().nonnullL3vpnInstances()) {
3101 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3103 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3104 vpn.getRouteDistinguisher()));
3106 result.add(String.format(" %-80s ", vpn.getImportRT()));
3108 result.add(String.format(" %-80s ", vpn.getExportRT()));
3111 Uuid vpnid = vpn.getId();
3112 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3113 if (!subnetList.isEmpty()) {
3114 for (Uuid subnetuuid : subnetList) {
3115 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3118 result.add(String.format(" %-76s ", "\" \""));
3121 result.add("----------------------------------------");
3125 String errortag = rpcResult.getErrors().iterator().next().getTag();
3126 if (Objects.equals(errortag, "")) {
3128 result.add("No VPN has been configured yet");
3129 } else if (Objects.equals(errortag, "invalid-value")) {
3131 result.add("VPN " + vpnuuid.getValue() + " is not present");
3133 result.add("error getting VPN info : " + rpcResult.getErrors());
3134 result.add(getshowVpnConfigCLIHelp());
3140 protected void createExternalVpnInterfaces(Uuid extNetId) {
3141 if (extNetId == null) {
3142 LOG.error("createExternalVpnInterfaces: external network is null");
3146 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3147 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3148 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3152 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3153 for (String elanInterface : extElanInterfaces) {
3154 createExternalVpnInterface(extNetId, elanInterface, tx);
3156 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3159 // TODO Clean up the exception handling
3160 @SuppressWarnings("checkstyle:IllegalCatch")
3161 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3162 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3163 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3164 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3167 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3168 for (String elanInterface : extElanInterfaces) {
3169 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3170 .buildVpnInterfaceIdentifier(elanInterface);
3171 LOG.info("Removing vpn interface {}", elanInterface);
3172 tx.delete(vpnIfIdentifier);
3174 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3177 private void createExternalVpnInterface(Uuid vpnId, String infName,
3178 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3179 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3180 false /* not a router iface */, wrtConfigTxn);
3183 // TODO Clean up the exception handling
3184 @SuppressWarnings("checkstyle:IllegalCatch")
3185 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3186 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3187 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3188 if (vpnIdList.isEmpty() || infName == null) {
3189 LOG.error("vpnid is empty or interface({}) is null", infName);
3192 if (wrtConfigTxn == null) {
3193 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3194 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3195 "Error writing VPN interface");
3198 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3199 for (Uuid vpnId: vpnIdList) {
3200 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3201 AssociatedSubnetType.V4AndV6Subnets);
3202 vpnIdListStruct.add(vpnInstance);
3205 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3206 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3208 .setVpnInstanceNames(vpnIdListStruct)
3209 .setRouterInterface(isRouterInterface);
3210 LOG.info("Network Id is {}", networkUuid);
3211 if (networkUuid != null) {
3212 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3213 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3214 NetworkAttributes.NetworkType networkType = providerType != null
3215 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3216 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3217 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3218 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3221 if (adjacencies != null) {
3222 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3224 VpnInterface vpnIf = vpnb.build();
3226 LOG.info("Creating vpn interface {}", vpnIf);
3227 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3228 } catch (Exception ex) {
3229 LOG.error("Creation of vpninterface {} failed", infName, ex);
3233 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3234 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3235 if (vpnId == null || infName == null) {
3236 LOG.error("vpn id or interface is null");
3239 if (wrtConfigTxn == null) {
3240 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3241 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3242 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3243 }), LOG, "Error updating VPN interface with adjacencies");
3247 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3249 try (AcquireResult lock = tryInterfaceLock(infName)) {
3250 if (!lock.wasAcquired()) {
3251 // FIXME: why do we even bother with locking if we do not honor it?!
3252 logTryLockFailure(infName);
3256 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3257 .syncReadOptional(dataBroker, LogicalDatastoreType
3258 .CONFIGURATION, vpnIfIdentifier);
3259 if (optionalVpnInterface.isPresent()) {
3260 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3261 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3263 if (adjacencies == null) {
3266 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3267 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3268 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3269 optionalVpnInterface.get().getVpnInstanceNames());
3270 if (listVpnInstances.isEmpty()
3271 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3272 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3273 AssociatedSubnetType.V4AndV6Subnets);
3274 listVpnInstances.add(vpnInstance);
3275 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3278 VpnInstanceNames vpnInstance = VpnHelper
3279 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3280 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3281 listVpnInstances.add(vpnInstance);
3282 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3284 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3285 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3287 } catch (IllegalStateException | ReadFailedException ex) {
3288 // FIXME: why are we catching IllegalStateException here?
3289 LOG.error("Update of vpninterface {} failed", infName, ex);
3294 private String getshowVpnConfigCLIHelp() {
3295 StringBuilder help = new StringBuilder("Usage:");
3296 help.append("display vpn-config [-vid/--vpnid <id>]");
3297 return help.toString();
3300 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3301 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3305 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3306 return neutronEvpnManager.createEVPN(input);
3310 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3311 return neutronEvpnManager.getEVPN(input);
3315 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3316 return neutronEvpnManager.deleteEVPN(input);
3319 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3320 Uuid extNetId = extNet.getUuid();
3321 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3322 .child(Networks.class, new NetworksKey(extNetId)).build();
3325 Optional<Networks> optionalExtNets =
3326 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3328 if (!optionalExtNets.isPresent()) {
3329 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3330 extNetId.getValue());
3333 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3334 builder.setVpnid(vpnId);
3335 Networks networks = builder.build();
3336 // Add Networks object to the ExternalNetworks list
3337 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3338 extNetId.getValue());
3339 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3342 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3343 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3344 extNetId.getValue(), ex);
3349 private boolean removeExternalNetworkFromVpn(Network extNet) {
3350 Uuid extNetId = extNet.getUuid();
3351 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3352 .child(Networks.class, new NetworksKey(extNetId)).build();
3354 Optional<Networks> optionalNets =
3355 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3357 NetworksBuilder builder = null;
3358 if (optionalNets.isPresent()) {
3359 builder = new NetworksBuilder(optionalNets.get());
3361 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3362 extNetId.getValue());
3365 builder.setVpnid(null);
3366 Networks networks = builder.build();
3367 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3368 extNetId.getValue());
3369 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3371 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3372 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3373 extNetId.getValue(), ex);
3378 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3379 Optional<String> existingVpnName = Optional.of(primaryRd);
3380 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3382 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3383 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3384 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3385 } catch (ReadFailedException e) {
3386 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3388 /*Read failed. We don't know if a VPN exists or not.
3389 * Return primaryRd to halt caller execution, to be safe.*/
3390 return existingVpnName;
3392 if (vpnInstanceOpDataOptional.isPresent()) {
3393 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3395 existingVpnName = Optional.absent();
3397 return existingVpnName;
3400 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3401 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3404 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3405 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3408 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3409 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3412 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3413 String message = tuple.getMessage();
3414 logger.accept(message);
3418 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3419 @NonNull Subnetmap subnetMap) {
3420 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3421 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3422 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3423 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3424 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3425 subnetMap.getId().getValue(), internetVpnId.getValue());
3429 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3430 @NonNull Subnetmap subnetMap) {
3431 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3432 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3435 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3436 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3437 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3438 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3439 internetVpnId.getValue(), routerId.getValue());
3440 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3446 private AcquireResult tryInterfaceLock(final String infName) {
3447 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3451 private AcquireResult tryVpnLock(final Uuid vpnId) {
3452 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3455 private static ReentrantLock lockForUuid(Uuid uuid) {
3456 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3457 return JvmGlobalLocks.getLockForString(uuid.getValue());
3460 private static void logTryLockFailure(Object objectId) {
3461 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());