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.toString());
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("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
358 subnetId.getValue());
361 LOG.debug("WithRouterFixedIP: 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("WithRouterFixedIP: 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 : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
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> directPortList = builder.getDirectPortList();
410 if (null == directPortList) {
411 directPortList = new ArrayList<>();
413 directPortList.add(directPortId);
414 builder.setDirectPortList(directPortList);
415 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
416 directPortId.getValue());
418 subnetmap = builder.build();
419 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
422 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
423 + "cache ", subnetId.getValue(), portId.getValue());
424 unprocessedPortsMap.put(portId, subnetId);
426 } catch (ReadFailedException | TransactionCommitFailedException e) {
427 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
434 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
435 Uuid vpnId, @Nullable Uuid portId) {
436 Subnetmap subnetmap = null;
437 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
438 .child(Subnetmap.class, new SubnetmapKey(subnetId))
440 final ReentrantLock lock = lockForUuid(subnetId);
443 Optional<Subnetmap> sn =
444 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
446 if (sn.isPresent()) {
447 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
448 if (routerId != null) {
449 builder.setRouterId(null);
451 if (networkId != null) {
452 builder.setNetworkId(null);
455 builder.setVpnId(null);
457 builder.setInternetVpnId(null);
458 if (portId != null && builder.getPortList() != null) {
459 List<Uuid> portList = new ArrayList<>(builder.getPortList());
460 portList.remove(portId);
461 builder.setPortList(portList);
464 subnetmap = builder.build();
465 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
466 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
469 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
471 } catch (ReadFailedException | TransactionCommitFailedException e) {
472 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
480 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
481 @Nullable Uuid directPortId) {
482 Subnetmap subnetmap = null;
483 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
484 new SubnetmapKey(subnetId)).build();
485 final ReentrantLock lock = lockForUuid(subnetId);
488 Optional<Subnetmap> sn =
489 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
491 if (sn.isPresent()) {
492 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
493 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
494 List<Uuid> portList = new ArrayList<>(builder.getPortList());
495 portList.remove(portId);
496 builder.setPortList(portList);
497 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
498 subnetId.getValue());
500 if (null != directPortId && null != builder.getDirectPortList()
501 && !builder.getDirectPortList().isEmpty()) {
502 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
503 directPortList.remove(directPortId);
504 builder.setDirectPortList(directPortList);
505 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
506 .getValue(), subnetId.getValue());
508 subnetmap = builder.build();
509 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
512 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
514 } catch (ReadFailedException | TransactionCommitFailedException e) {
515 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
516 subnetId.getValue(), e);
523 // TODO Clean up the exception handling
524 @SuppressWarnings("checkstyle:IllegalCatch")
525 protected void deleteSubnetMapNode(Uuid subnetId) {
526 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
527 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
528 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
529 final ReentrantLock lock = lockForUuid(subnetId);
532 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
533 } catch (TransactionCommitFailedException e) {
534 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
540 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
541 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
542 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
544 Optional<VpnInstance> vpnInstanceConfig =
545 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
547 if (!vpnInstanceConfig.isPresent()) {
548 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
551 VpnInstance vpnInstance = vpnInstanceConfig.get();
552 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
553 if (vpnInstance.getIpv4Family() != null) {
554 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
555 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
557 if (vpnInstance.getIpv6Family() != null) {
558 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
559 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
561 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
562 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
563 updateVpnInstanceBuilder.build());
564 } catch (ReadFailedException | TransactionCommitFailedException ex) {
565 LOG.warn("Error configuring feature ", ex);
569 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
570 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
571 String vpnName = vpnId.getValue();
572 VpnInstanceBuilder builder = null;
573 List<VpnTarget> vpnTargetList = new ArrayList<>();
574 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
575 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
576 Optional<VpnInstance> optionalVpn;
578 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
580 } catch (ReadFailedException e) {
581 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
585 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
586 if (optionalVpn.isPresent()) {
587 builder = new VpnInstanceBuilder(optionalVpn.get());
588 LOG.debug("updating existing vpninstance node");
590 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
591 .setType(type).setL3vni(l3vni);
593 if (irt != null && !irt.isEmpty()) {
594 if (ert != null && !ert.isEmpty()) {
595 List<String> commonRT = new ArrayList<>(irt);
596 commonRT.retainAll(ert);
598 for (String common : commonRT) {
601 VpnTarget vpnTarget =
602 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
603 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
604 vpnTargetList.add(vpnTarget);
607 for (String importRT : irt) {
608 VpnTarget vpnTarget =
609 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
610 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
611 vpnTargetList.add(vpnTarget);
615 if (ert != null && !ert.isEmpty()) {
616 for (String exportRT : ert) {
617 VpnTarget vpnTarget =
618 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
619 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
620 vpnTargetList.add(vpnTarget);
624 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
625 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
626 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
628 if (rd != null && !rd.isEmpty()) {
629 ipv4vpnBuilder.setRouteDistinguisher(rd);
630 ipv6vpnBuilder.setRouteDistinguisher(rd);
633 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
634 builder.setIpv4Family(ipv4vpnBuilder.build());
636 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
637 builder.setIpv6Family(ipv6vpnBuilder.build());
639 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
640 builder.setIpv4Family(ipv4vpnBuilder.build());
642 VpnInstance newVpn = builder.build();
644 try (AcquireResult lock = tryVpnLock(vpnId)) {
645 if (!lock.wasAcquired()) {
646 // FIXME: why do we even bother with locking if we do not honor it?!
647 logTryLockFailure(vpnId);
650 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
652 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
654 } catch (TransactionCommitFailedException e) {
655 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
660 private void deleteVpnMapsNode(Uuid vpnId) {
661 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
662 .child(VpnMap.class, new VpnMapKey(vpnId))
664 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
665 try (AcquireResult lock = tryVpnLock(vpnId)) {
666 if (!lock.wasAcquired()) {
667 // FIXME: why do we even bother with locking if we do not honor it?!
668 logTryLockFailure(vpnId);
672 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
674 } catch (TransactionCommitFailedException e) {
675 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
680 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
681 @Nullable List<Uuid> networks) {
682 VpnMapBuilder builder;
683 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
684 .child(VpnMap.class, new VpnMapKey(vpnId))
687 Optional<VpnMap> optionalVpnMap =
688 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
690 if (optionalVpnMap.isPresent()) {
691 builder = new VpnMapBuilder(optionalVpnMap.get());
693 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
697 builder.setName(name);
699 if (tenantId != null) {
700 builder.setTenantId(tenantId);
702 if (router != null) {
703 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
704 List<RouterIds> rtrIds = builder.getRouterIds() != null
705 ? new ArrayList<>(builder.getRouterIds()) : null;
706 if (rtrIds == null) {
707 rtrIds = Collections.singletonList(vpnRouterId);
709 rtrIds.add(vpnRouterId);
711 builder.setRouterIds(rtrIds);
713 if (networks != null) {
714 List<Uuid> nwList = builder.getNetworkIds() != null
715 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
716 nwList.addAll(networks);
717 builder.setNetworkIds(nwList);
720 try (AcquireResult lock = tryVpnLock(vpnId)) {
721 if (!lock.wasAcquired()) {
722 // FIXME: why do we even bother with locking if we do not honor it?!
723 logTryLockFailure(vpnId);
726 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
727 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
729 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
731 } catch (ReadFailedException | TransactionCommitFailedException e) {
732 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
736 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
737 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
738 .child(VpnMap.class, new VpnMapKey(vpnId))
740 Optional<VpnMap> optionalVpnMap;
743 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
745 } catch (ReadFailedException e) {
746 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
749 if (optionalVpnMap.isPresent()) {
750 VpnMap vpnMap = optionalVpnMap.get();
751 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
752 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds());
753 if (rtrIds == null) {
754 rtrIds = new ArrayList<>();
756 if (routerId != null) {
757 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
758 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
759 vpnMapBuilder.setRouterIds(rtrIds);
761 try (AcquireResult lock = tryVpnLock(vpnId)) {
762 if (!lock.wasAcquired()) {
763 // FIXME: why do we even bother with locking if we do not honor it?!
764 logTryLockFailure(vpnId);
767 LOG.debug("removing vpnMaps node: {} ", vpnId);
769 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
771 } catch (TransactionCommitFailedException e) {
772 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
776 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
777 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
778 vpnMapBuilder.setRouterIds(rtrIds);
779 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
782 if (networkIds != null) {
783 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
784 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
785 vpnNw.removeAll(networkIds);
786 if (vpnNw.isEmpty()) {
787 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
788 vpnMapBuilder.setNetworkIds(null);
790 vpnMapBuilder.setNetworkIds(vpnNw);
794 try (AcquireResult lock = tryVpnLock(vpnId)) {
795 if (!lock.wasAcquired()) {
796 // FIXME: why do we even bother with locking if we do not honor it?!
797 logTryLockFailure(vpnId);
800 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
802 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
803 vpnMapIdentifier, vpnMapBuilder.build());
804 } catch (TransactionCommitFailedException e) {
805 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
809 LOG.error("VPN : {} not found", vpnId.getValue());
811 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
814 private void deleteVpnInstance(Uuid vpnId) {
815 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
816 .child(VpnInstance.class,
817 new VpnInstanceKey(vpnId.getValue()))
820 try (AcquireResult lock = tryVpnLock(vpnId)) {
821 if (!lock.wasAcquired()) {
822 // FIXME: why do we even bother with locking if we do not honor it?!
823 logTryLockFailure(vpnId);
826 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
828 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
829 } catch (TransactionCommitFailedException e) {
830 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
835 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
836 TypedWriteTransaction<Configuration> wrtConfigTxn,
837 @Nullable VpnInterface vpnIface) {
838 List<Adjacency> adjList = new ArrayList<>();
839 if (vpnIface != null) {
840 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
842 String infName = port.getUuid().getValue();
843 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
844 for (FixedIps ip : port.nonnullFixedIps()) {
845 String ipValue = ip.getIpAddress().stringValue();
846 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
847 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
848 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
849 snTemp.getSubnetIp(), false)) {
852 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
854 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
855 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
856 //Create Neutron port adjacency if VPN presence is existing for subnet
857 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
858 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
859 .setSubnetId(ip.getSubnetId()).build();
860 if (!adjList.contains(vmAdj)) {
864 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
865 if (snTemp != null && snTemp.getInternetVpnId() != null) {
866 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
867 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
869 if (routerId != null) {
870 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
871 if (rtr != null && rtr.getRoutes() != null) {
872 List<Routes> routeList = rtr.getRoutes();
873 // create extraroute Adjacence for each ipValue,
874 // because router can have IPv4 and IPv6 subnet ports, or can have
875 // more that one IPv4 subnet port or more than one IPv6 subnet port
876 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
877 if (!erAdjList.isEmpty()) {
878 adjList.addAll(erAdjList);
883 return new AdjacenciesBuilder().setAdjacency(adjList).build();
886 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
887 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
888 boolean isRouterInterface = false;
889 if (port.getDeviceOwner() != null) {
890 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
892 String infName = port.getUuid().getValue();
893 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
894 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
895 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
896 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
897 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
900 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
901 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
902 String infName = port.getUuid().getValue();
903 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
904 Optional<VpnInterface> optionalVpnInterface = null;
905 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
906 vpnId, internetVpnId, infName);
908 optionalVpnInterface = SingleTransactionDataBroker
909 .syncReadOptional(dataBroker, LogicalDatastoreType
910 .CONFIGURATION, vpnIfIdentifier);
911 } catch (ReadFailedException e) {
912 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
915 if (!optionalVpnInterface.isPresent()) {
918 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
919 sn != null ? sn.getSubnetIp() : "null");
920 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
921 List<Adjacency> updatedAdjsList = new ArrayList<>();
922 boolean isIpFromAnotherSubnet = false;
923 for (Adjacency adj : vpnAdjsList) {
924 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
925 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
926 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
927 isIpFromAnotherSubnet = true;
929 updatedAdjsList.add(adj);
932 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
933 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
936 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
937 String.valueOf(adjString), wrtConfigTxn);
939 if (internetVpnId != null) {
940 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
941 String.valueOf(adjString), wrtConfigTxn);
944 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
945 && sn.getRouterId() != null) {
946 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
947 if (rtr != null && rtr.getRoutes() != null) {
948 List<Routes> extraRoutesToRemove = new ArrayList<>();
949 for (Routes rt: rtr.getRoutes()) {
950 if (rt.getNexthop().toString().equals(adjString)) {
951 extraRoutesToRemove.add(rt);
955 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
956 extraRoutesToRemove, vpnId);
957 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
959 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
964 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
966 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
968 if (!isIpFromAnotherSubnet) {
969 // no more subnetworks for neutron port
970 if (sn != null && sn.getRouterId() != null) {
971 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
973 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
979 // TODO Clean up the exception handling
980 @SuppressWarnings("checkstyle:IllegalCatch")
981 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
982 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
983 if (wrtConfigTxn == null) {
984 ListenableFutures.addErrorLogging(
985 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
986 tx -> deleteVpnInterface(infName, vpnId, tx)),
987 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
991 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
992 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
993 Optional<VpnInterface> optionalVpnInterface;
995 optionalVpnInterface =
996 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
998 } catch (ReadFailedException ex) {
999 LOG.error("Error during deletion of vpninterface {}", infName, ex);
1002 if (!optionalVpnInterface.isPresent()) {
1003 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
1006 if (vpnId != null) {
1007 VpnInterface vpnInterface = optionalVpnInterface.get();
1008 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
1010 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
1011 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
1012 if (!vpnList.isEmpty()) {
1013 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1014 + "List not empty", infName);
1017 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1018 .setVpnInstanceNames(vpnList);
1019 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1023 LOG.debug("Deleting vpn interface {}", infName);
1024 wrtConfigTxn.delete(vpnIfIdentifier);
1027 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1028 TypedWriteTransaction<Configuration> writeConfigTxn,
1030 if (vpnId == null || port == null) {
1033 String infName = port.getUuid().getValue();
1034 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1036 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1037 .syncReadOptional(dataBroker, LogicalDatastoreType
1038 .CONFIGURATION, vpnIfIdentifier);
1039 if (optionalVpnInterface.isPresent()) {
1040 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1042 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1043 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1045 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1046 .setVpnInstanceNames(listVpn);
1047 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1048 LOG.debug("Updating vpn interface {}", infName);
1049 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1050 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1051 while (adjacencyIter.hasNext()) {
1052 Adjacency adjacency = adjacencyIter.next();
1053 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1056 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1057 InstanceIdentifier<LearntVpnVipToPort> id =
1058 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1059 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1060 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1061 LogicalDatastoreType.OPERATIONAL, id);
1062 if (optionalVpnVipToPort.isPresent()) {
1063 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1065 if (listVpn == null || listVpn.isEmpty()) {
1066 adjacencyIter.remove();
1068 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1069 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1070 mipToQuery, infName, vpnId.getValue());
1073 for (FixedIps ip : port.nonnullFixedIps()) {
1074 String ipValue = ip.getIpAddress().stringValue();
1076 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1079 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1080 ipValue, writeConfigTxn);
1082 if (listVpn == null || listVpn.isEmpty()) {
1083 if (sm != null && sm.getRouterId() != null) {
1084 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1086 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1088 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1091 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1093 } catch (ReadFailedException ex) {
1094 LOG.error("Update of vpninterface {} failed", infName, ex);
1098 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1100 TypedWriteTransaction<Configuration> writeConfigTxn,
1101 boolean isInternetVpn) {
1102 if (vpnId == null || port == null) {
1105 String infName = port.getUuid().getValue();
1106 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1108 try (AcquireResult lock = tryInterfaceLock(infName)) {
1109 if (!lock.wasAcquired()) {
1110 // FIXME: why do we even bother with locking if we do not honor it?!
1111 logTryLockFailure(infName);
1115 Optional<VpnInterface> optionalVpnInterface =
1116 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1118 if (optionalVpnInterface.isPresent()) {
1119 VpnInstanceNames vpnInstance = VpnHelper
1120 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1121 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1122 .get().getVpnInstanceNames());
1123 if (oldVpnId != null
1124 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1125 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1127 if (vpnId.getValue() != null
1128 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1129 listVpn.add(vpnInstance);
1131 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1132 .setVpnInstanceNames(listVpn);
1133 LOG.debug("Updating vpn interface {}", infName);
1134 if (!isBeingAssociated) {
1135 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1136 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1137 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1138 while (adjacencyIter.hasNext()) {
1139 Adjacency adjacency = adjacencyIter.next();
1140 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1141 InstanceIdentifier<LearntVpnVipToPort> id =
1142 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1143 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1144 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1145 LogicalDatastoreType.OPERATIONAL, id);
1146 if (optionalVpnVipToPort.isPresent()
1147 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1148 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1149 + "from VPN {}", infName, vpnId, oldVpnId);
1150 adjacencyIter.remove();
1151 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1153 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1154 mipToQuery, infName, vpnId.getValue());
1156 InstanceIdentifier<VpnPortipToPort> build =
1157 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1158 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1159 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1160 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1161 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1162 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1163 mipToQuery, infName, vpnId.getValue());
1166 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1167 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1169 for (FixedIps ip : port.nonnullFixedIps()) {
1170 String ipValue = ip.getIpAddress().stringValue();
1171 if (oldVpnId != null) {
1172 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1173 ipValue, writeConfigTxn);
1175 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1176 && isInternetVpn == true) {
1180 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1181 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1183 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1185 LOG.error("VPN Interface {} not found", infName);
1187 } catch (ReadFailedException ex) {
1188 LOG.error("Updation of vpninterface {} failed", infName, ex);
1193 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1194 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1196 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1198 // Update VPN Instance node
1199 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1201 // Update local vpn-subnet DS
1202 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1204 if (routerId != null) {
1205 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1206 if (existingVpn != null) {
1207 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1208 // if before reboot, router was already associated to VPN, should not proceed associating router to
1209 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1210 // preserved upon reboot.
1211 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1212 // RouterInterfacesMap via #createVPNInterface call.
1213 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1214 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1217 associateRouterToInternalVpn(vpnId, routerId);
1222 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1223 * specified Neutron Networks and Routers.
1225 * @param vpnId Uuid of the VPN tp be created
1226 * @param name Representative name of the new VPN
1227 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1228 * @param rdList Route-distinguisher for the VPN
1229 * @param irtList A list of Import Route Targets
1230 * @param ertList A list of Export Route Targets
1231 * @param routerIdsList ist of neutron router Id to associate with created VPN
1232 * @param networkList UUID of the neutron network the VPN may be associated to
1233 * @param type Type of the VPN Instance
1234 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1235 * @throws Exception if association of L3VPN failed
1237 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1238 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1239 VpnInstance.Type type, long l3vni) throws Exception {
1241 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1243 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1244 for (Uuid routerId : routerIdsList) {
1245 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1246 ipVersChoices = ipVersChoices.addVersion(vers);
1249 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1251 // Please note that router and networks will be filled into VPNMaps
1252 // by subsequent calls here to associateRouterToVpn and
1253 // associateNetworksToVpn
1254 updateVpnMaps(vpnId, name, null, tenantId, null);
1255 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1256 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1259 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1260 for (Uuid routerId : routerIdsList) {
1261 associateRouterToVpn(vpnId, routerId);
1264 if (networkList != null) {
1265 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1266 if (!failStrings.isEmpty()) {
1267 LOG.error("VPN {} association to networks failed for networks: {}. ",
1268 vpnId.getValue(), failStrings.toString());
1269 throw new Exception(failStrings.toString());
1275 * It handles the invocations to the createVPN RPC method.
1278 // TODO Clean up the exception handling
1279 @SuppressWarnings("checkstyle:IllegalCatch")
1280 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1282 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1283 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1284 List<RpcError> errorList = new ArrayList<>();
1285 int failurecount = 0;
1286 int warningcount = 0;
1288 List<L3vpn> vpns = input.getL3vpn();
1290 vpns = Collections.emptyList();
1292 for (L3vpn vpn : vpns) {
1293 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1294 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1295 formatAndLog(LOG::warn,
1296 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1297 vpn.getId().getValue())));
1301 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1302 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1303 formatAndLog(LOG::warn,
1304 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1305 vpn.getId().getValue())));
1309 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1311 if (vpn.getL3vni() != null) {
1312 l3vni = vpn.getL3vni().toJava();
1315 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1316 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1317 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1318 formatAndLog(LOG::warn,
1319 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1320 + "is already configured",
1321 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1325 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1326 if (operationalVpn.isPresent()) {
1327 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1328 formatAndLog(LOG::error,
1329 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1330 + "is still available. Please retry creation of a new vpn with the same RD"
1331 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1332 vpn.getRouteDistinguisher().get(0))));
1336 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1337 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1338 routerIdsList = vpn.getRouterIds();
1339 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1340 routerId : routerIdsList) {
1341 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1342 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1343 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1344 + "{}", vpn.getId(), routerId.getRouterId())));
1348 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1349 if (vpnId != null) {
1350 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1351 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1352 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1353 vpnId.getValue())));
1359 if (vpn.getNetworkIds() != null) {
1360 int initialWarningCount = warningcount;
1361 for (Uuid nw : vpn.getNetworkIds()) {
1362 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1363 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1364 if (network == null) {
1365 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1366 formatAndLog(LOG::warn,
1367 "Creation of L3VPN failed for VPN {} due to network not found {}",
1368 vpn.getId().getValue(), nw.getValue())));
1370 } else if (vpnId != null) {
1371 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1372 formatAndLog(LOG::warn,
1373 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1374 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1375 vpnId.getValue())));
1379 if (warningcount != initialWarningCount) {
1383 List<Uuid> rtrIdsList = new ArrayList<>();
1384 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1385 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1386 rtrId : vpn.getRouterIds()) {
1387 rtrIdsList.add(rtrId.getRouterId());
1391 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1392 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1393 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1394 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1396 List<String> rdList = vpn.getRouteDistinguisher() != null
1397 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1398 List<String> importRdList = vpn.getImportRT() != null
1399 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1400 List<String> exportRdList = vpn.getExportRT() != null
1401 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1403 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1404 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), vpnInstanceType, l3vni);
1405 } catch (Exception ex) {
1406 LOG.error("VPN Creation exception :", ex);
1407 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1408 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1413 // if at least one succeeds; result is success
1414 // if none succeeds; result is failure
1415 if (failurecount + warningcount == vpns.size()) {
1416 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1418 List<String> errorResponseList = new ArrayList<>();
1419 if (!errorList.isEmpty()) {
1420 for (RpcError rpcError : errorList) {
1421 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1422 + ", ErrorMessage: " + rpcError.getMessage());
1425 errorResponseList.add("Operation successful with no errors");
1427 opBuilder.setResponse(errorResponseList);
1428 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1434 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1437 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1439 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1440 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1441 Uuid inputVpnId = input.getId();
1442 List<VpnInstance> vpns = new ArrayList<>();
1443 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1446 if (inputVpnId == null) {
1448 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1450 Optional<VpnInstances> optionalVpns =
1451 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1453 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1454 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1455 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1456 // from getL3VPN output
1457 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1460 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1466 opBuilder.setL3vpnInstances(l3vpnList);
1467 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1471 String name = inputVpnId.getValue();
1472 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1473 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1474 // read VpnInstance Info
1475 Optional<VpnInstance> optionalVpn =
1476 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1478 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1480 if (optionalVpn.isPresent() && (optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1481 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
1482 vpns.add(optionalVpn.get());
1485 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1486 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1490 for (VpnInstance vpnInstance : vpns) {
1491 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1492 // create VpnMaps id
1493 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1494 List<String> rd = Collections.EMPTY_LIST;
1495 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1496 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1497 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1498 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1500 List<String> ertList = new ArrayList<>();
1501 List<String> irtList = new ArrayList<>();
1503 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1504 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1505 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1506 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1507 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1508 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1509 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1511 if (!vpnTargetList.isEmpty()) {
1512 for (VpnTarget vpnTarget : vpnTargetList) {
1513 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1514 ertList.add(vpnTarget.getVrfRTValue());
1516 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1517 irtList.add(vpnTarget.getVrfRTValue());
1519 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1520 ertList.add(vpnTarget.getVrfRTValue());
1521 irtList.add(vpnTarget.getVrfRTValue());
1527 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1529 if (vpnInstance.getL3vni() != null) {
1530 l3vpn.setL3vni(vpnInstance.getL3vni());
1532 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1533 .class, new VpnMapKey(vpnId)).build();
1534 Optional<VpnMap> optionalVpnMap =
1535 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1537 if (optionalVpnMap.isPresent()) {
1538 VpnMap vpnMap = optionalVpnMap.get();
1539 List<Uuid> rtrIds = new ArrayList<>();
1540 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1541 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1542 rtrIds.add(rtrId.getRouterId());
1545 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1546 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1547 .setName(vpnMap.getName());
1550 l3vpnList.add(l3vpn.build());
1553 opBuilder.setL3vpnInstances(l3vpnList);
1554 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1556 } catch (ReadFailedException ex) {
1557 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1558 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1564 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1567 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1569 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1570 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1571 List<RpcError> errorList = new ArrayList<>();
1573 int failurecount = 0;
1574 int warningcount = 0;
1575 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1576 for (Uuid vpn : vpns) {
1578 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1579 InstanceIdentifier<VpnInstance> vpnIdentifier =
1580 InstanceIdentifier.builder(VpnInstances.class)
1581 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1582 Optional<VpnInstance> optionalVpn =
1583 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1585 if (optionalVpn.isPresent()) {
1588 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1589 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1592 } catch (ReadFailedException ex) {
1593 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1594 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1599 // if at least one succeeds; result is success
1600 // if none succeeds; result is failure
1601 if (failurecount + warningcount == vpns.size()) {
1602 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1604 List<String> errorResponseList = new ArrayList<>();
1605 if (!errorList.isEmpty()) {
1606 for (RpcError rpcError : errorList) {
1607 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1608 + ", ErrorMessage: " + rpcError.getMessage());
1611 errorResponseList.add("Operation successful with no errors");
1613 opBuilder.setResponse(errorResponseList);
1614 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1619 public void createVpnInstanceForSubnet(Uuid subnetId) {
1620 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1621 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1624 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1625 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1626 removeVpn(subnetId);
1629 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1630 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1631 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1632 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1634 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1635 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1638 if (vpnId != null) {
1639 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1640 if (vpnMap == null) {
1641 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1642 + " cannot add subnet {} to VPN", vpnId.getValue(),
1646 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1647 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1648 if (isVpnOfTypeL2(vpnInstance)) {
1649 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1650 NeutronEvpnUtils.Operation.ADD);
1653 if (internetVpnId != null) {
1654 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1655 if (vpnMap == null) {
1656 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1657 + "subnet {} to VPN", internetVpnId.getValue(),
1662 final Uuid internetId = internetVpnId;
1663 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1664 List<Uuid> portList = sn.getPortList();
1665 if (portList != null) {
1666 for (final Uuid portId : portList) {
1667 String vpnInfName = portId.getValue();
1668 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1669 Port port = neutronvpnUtils.getNeutronPort(portId);
1671 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1672 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1675 final Boolean isRouterInterface = port.getDeviceOwner()
1676 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1677 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1678 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1680 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1682 if (vpnIface == null) {
1683 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1684 Set<Uuid> listVpn = new HashSet<>();
1685 if (vpnId != null) {
1688 if (internetId != null) {
1689 listVpn.add(internetId);
1691 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1692 isRouterInterface, wrtConfigTxn);
1693 if (sn.getRouterId() != null) {
1694 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1697 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1698 if (vpnId != null) {
1699 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1701 if (internetId != null) {
1702 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1706 ListenableFutures.addErrorLogging(future, LOG,
1707 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1708 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1709 return Collections.singletonList(future);
1715 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1716 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1717 "removeSubnetFromVpn: at least one VPN must be not null");
1718 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1719 vpnId, internetVpnId);
1720 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1722 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1725 VpnMap vpnMap = null;
1726 VpnInstance vpnInstance = null;
1727 if (vpnId != null) {
1728 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1729 if (vpnMap == null) {
1730 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1731 vpnId.getValue(), subnet.getValue());
1734 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1736 if (internetVpnId == null) {
1737 internetVpnId = sn.getInternetVpnId();
1739 if (internetVpnId != null) {
1740 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1741 if (vpnMap == null) {
1742 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1743 + " from Internet VPN",
1744 internetVpnId.getValue(), subnet.getValue());
1748 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1749 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1750 NeutronEvpnUtils.Operation.DELETE);
1752 boolean subnetVpnAssociation = false;
1753 if (vpnId != null && sn.getVpnId() != null
1754 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1755 subnetVpnAssociation = true;
1756 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1757 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1758 subnetVpnAssociation = true;
1760 if (subnetVpnAssociation == false) {
1761 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1762 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1765 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1766 List<Uuid> portList = sn.getPortList();
1767 final Uuid internetId = internetVpnId;
1768 if (portList != null) {
1769 for (final Uuid portId : portList) {
1770 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1771 final Port port = neutronvpnUtils.getNeutronPort(portId);
1772 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1773 List<ListenableFuture<Void>> futures = new ArrayList<>();
1774 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1775 CONFIGURATION, tx -> {
1777 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1779 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1780 + " port is absent in Neutron config DS", portId.getValue(),
1784 ListenableFutures.addErrorLogging(future, LOG,
1785 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1786 + " belonging to subnet {} and vpnId {}",
1787 portId.getValue(), subnet.getValue(), vpnId.getValue());
1788 futures.add(future);
1793 //update subnet-vpn association
1794 removeFromSubnetNode(subnet, null, null, vpnId, null);
1797 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1798 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1799 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1801 Uuid internalVpnId = sm.getVpnId();
1802 if (internalVpnId == null) {
1803 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1804 sm.getId().getValue());
1807 if (isBeingAssociated) {
1808 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1810 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1813 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1814 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1815 if (isBeingAssociated) {
1816 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1817 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1819 removeInternetVpnFromVpnInterface(vpn,
1820 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1825 // Check for ports on this subnet and update association of
1826 // corresponding vpn-interfaces to internet vpn
1827 List<Uuid> portList = sm.getPortList();
1828 if (portList != null) {
1829 for (Uuid port : portList) {
1830 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1831 port.getValue(), isBeingAssociated);
1832 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1833 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1835 if (isBeingAssociated) {
1836 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1837 true, false, tx, true);
1839 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1847 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1848 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1849 oldVpnId.getValue(), newVpnId.getValue());
1850 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1851 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1852 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1853 Uuid vpnExtUuid = netIsExternal ? null
1854 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1855 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1857 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1860 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1861 * associated with internet BGP-VPN.
1863 if (vpnExtUuid != null) {
1864 /* Update V6 Internet default route match with new VPN metadata.
1865 * isBeingAssociated = true means oldVpnId is same as routerId
1866 * isBeingAssociated = false means newVpnId is same as routerId
1868 if (isBeingAssociated) {
1869 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1871 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1874 //Update Router Interface first synchronously.
1875 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1876 ListenableFuture<Void> future =
1877 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1878 tx -> updateVpnInterface(newVpnId, oldVpnId,
1879 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1880 isBeingAssociated, true, tx, false));
1881 Futures.addCallback(future, new FutureCallback<Void>() {
1883 public void onSuccess(Void result) {
1884 // Check for ports on this subnet and update association of
1885 // corresponding vpn-interfaces to external vpn
1886 List<Uuid> portList = sn.getPortList();
1887 if (portList != null) {
1888 for (Uuid port : portList) {
1889 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1890 port.getValue(), isBeingAssociated);
1891 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1892 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1893 tx -> updateVpnInterface(newVpnId, oldVpnId,
1894 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1901 public void onFailure(Throwable throwable) {
1903 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1905 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1907 }, MoreExecutors.directExecutor());
1912 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1913 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1914 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1917 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1918 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1919 final ReentrantLock lock = lockForUuid(routerId);
1922 Optional<RouterInterfaces> optRouterInterfaces =
1923 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1924 routerInterfacesId);
1925 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1926 .setInterfaceId(interfaceName).build();
1927 if (optRouterInterfaces.isPresent()) {
1928 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1929 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1931 // TODO Shouldn't we be doing something with builder and interfaces?
1932 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1933 // List<Interfaces> interfaces = new ArrayList<>();
1934 // interfaces.add(routerInterface);
1936 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1937 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1939 } catch (ReadFailedException | TransactionCommitFailedException e) {
1940 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1946 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1947 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1948 final ReentrantLock lock = lockForUuid(routerId);
1951 Optional<RouterInterfaces> optRouterInterfaces =
1952 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1953 routerInterfacesId);
1954 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1955 .setInterfaceId(interfaceName).build();
1956 if (optRouterInterfaces.isPresent()) {
1957 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1958 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
1959 if (interfaces != null && interfaces.remove(routerInterface)) {
1960 if (interfaces.isEmpty()) {
1961 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1962 routerInterfacesId);
1964 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1965 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1969 } catch (ReadFailedException | TransactionCommitFailedException e) {
1970 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1977 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1978 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1979 * route will be ignored.
1981 * @param vpnName the VPN identifier
1982 * @param interVpnLinkRoutes The list of static routes
1983 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1985 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1986 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1987 for (Routes route : interVpnLinkRoutes) {
1988 String nexthop = route.getNexthop().stringValue();
1989 String destination = route.getDestination().stringValue();
1990 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1991 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1992 AddStaticRouteInput rpcInput =
1993 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1994 .setVpnInstanceName(vpnName.getValue())
1996 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1997 RpcResult<AddStaticRouteOutput> rpcResult;
1999 rpcResult = labelOuputFtr.get();
2000 if (rpcResult.isSuccessful()) {
2001 LOG.debug("Label generated for destination {} is: {}",
2002 destination, rpcResult.getResult().getLabel());
2004 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
2005 destination, nexthop, rpcResult.getErrors());
2007 } catch (InterruptedException | ExecutionException e) {
2008 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
2009 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
2012 // Any other case is a fault.
2013 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2014 route.getDestination().stringValue(), nexthop);
2021 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2022 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2024 * @param vpnName the VPN identifier
2025 * @param interVpnLinkRoutes The list of static routes
2026 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2028 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2029 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2030 for (Routes route : interVpnLinkRoutes) {
2031 String nexthop = route.getNexthop().stringValue();
2032 String destination = route.getDestination().stringValue();
2033 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2034 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2035 RemoveStaticRouteInput rpcInput =
2036 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2037 .setVpnInstanceName(vpnName.getValue())
2040 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2041 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2043 // Any other case is a fault.
2044 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2045 route.getDestination().stringValue(), nexthop);
2052 * Returns true if the specified nexthop is the other endpoint in an
2053 * InterVpnLink, regarding one of the VPN's point of view.
2055 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2056 InterVpnLink interVpnLink) {
2058 interVpnLink != null
2059 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2060 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2061 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2062 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2066 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2067 List<Adjacency> adjList = new ArrayList<>();
2068 Map<String, List<String>> adjMap = new HashMap<>();
2069 for (Routes route : routeList) {
2070 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2071 LOG.error("Incorrect input received for extra route. {}", route);
2073 String nextHop = route.getNexthop().stringValue();
2074 String destination = route.getDestination().stringValue();
2075 if (!nextHop.equals(fixedIp)) {
2076 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2079 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2081 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2082 if (!hops.contains(nextHop)) {
2088 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2089 final String destination = entry.getKey();
2090 final List<String> ipList = entry.getValue();
2091 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2092 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2093 .withKey(new AdjacencyKey(destination)).build();
2099 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2100 checkAlarmExtraRoutes(vpnId, routeList);
2102 for (Routes route : routeList) {
2103 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2104 LOG.error("Incorrect input received for extra route. {}", route);
2106 String nextHop = route.getNexthop().stringValue();
2107 String destination = route.getDestination().stringValue();
2108 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2110 if (infName != null) {
2111 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2112 destination, vpnId.getValue(), nextHop, infName);
2113 boolean isLockAcquired = false;
2115 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2116 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2117 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2118 .child(Adjacency.class, new AdjacencyKey(destination));
2119 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2120 LogicalDatastoreType.CONFIGURATION, path);
2121 if (existingAdjacency.isPresent()
2122 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2123 LOG.error("The route with destination {} nextHop {} is already present as"
2124 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2125 destination, nextHop, infName);
2128 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2129 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2130 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2132 try (AcquireResult lock = tryInterfaceLock(infName)) {
2133 if (!lock.wasAcquired()) {
2134 // FIXME: why do we even bother with locking if we do not honor it?!
2135 logTryLockFailure(infName);
2138 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2141 } catch (TransactionCommitFailedException e) {
2142 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2143 destination, nextHop, e);
2144 } catch (ReadFailedException e) {
2145 LOG.error("Exception on reading data-store ", e);
2148 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2149 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2156 * This method setup or down an alarm about extra route fault.
2157 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2158 * available RDs, then an alarm and an error is generated.<br>
2159 * <b>Be careful</b> the routeList could be changed.
2161 * @param vpnId the vpnId of vpn to control.
2162 * @param routeList the list of router to check, it could be modified.
2164 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2165 if (!neutronvpnAlarm.isAlarmEnabled()) {
2166 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2169 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2170 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2171 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2175 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2176 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2177 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2181 for (Routes route : routeList) {
2182 // count the number of nexthops for each same route.getDestingation().getValue()
2183 String destination = route.getDestination().stringValue();
2184 String nextHop = route.getNexthop().stringValue();
2185 List<String> nextHopList = new ArrayList<>();
2186 nextHopList.add(nextHop);
2188 for (Routes routeTmp : routeList) {
2189 String routeDest = routeTmp.getDestination().stringValue();
2190 if (!destination.equals(routeDest)) {
2193 String routeNextH = routeTmp.getNexthop().stringValue();
2194 if (nextHop.equals(routeNextH)) {
2198 nextHopList.add(routeTmp.getNexthop().stringValue());
2200 final List<String> rdList = new ArrayList<>();
2201 if (vpnInstance.getIpv4Family() != null
2202 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2203 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2209 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2210 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2211 if (rd != null && !rdList.contains(rd)) {
2216 // 1. VPN Instance Name
2217 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2220 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2221 Uuid routerUuid = routerUuidList.get(0);
2222 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2223 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2225 // 3. List of RDs associated with the VPN
2226 detailsAlarm.append(" List of RDs associated with the VPN: ");
2227 for (String s : rdList) {
2228 detailsAlarm.append(s);
2229 detailsAlarm.append(", ");
2232 // 4. Prefix in question
2233 detailsAlarm.append(" for prefix: ");
2234 detailsAlarm.append(route.getDestination().stringValue());
2236 // 5. List of NHs for the prefix
2237 detailsAlarm.append(" for nextHops: ");
2238 for (String s : nextHopList) {
2239 detailsAlarm.append(s);
2240 detailsAlarm.append(", ");
2243 if (rdList.size() < nbNextHops) {
2244 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2246 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2251 // TODO Clean up the exception handling
2252 @SuppressWarnings("checkstyle:IllegalCatch")
2253 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2254 for (Routes route : routeList) {
2255 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2256 String nextHop = route.getNexthop().stringValue();
2257 String destination = route.getDestination().stringValue();
2258 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2260 if (infName == null) {
2261 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2262 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2263 // Proceed to remove the next extra-route
2266 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2267 destination, vpnId.getValue(), nextHop, infName);
2269 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2270 InstanceIdentifier.builder(VpnInterfaces.class)
2271 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2272 .augmentation(Adjacencies.class)
2273 .child(Adjacency.class, new AdjacencyKey(destination))
2277 // Looking for existing prefix in MDSAL database
2278 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2279 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2280 boolean updateNextHops = false;
2281 List<String> nextHopList = new ArrayList<>();
2282 if (adjacency.isPresent()) {
2283 List<String> nhListRead = adjacency.get().getNextHopIpList();
2284 if (nhListRead.size() > 1) { // ECMP case
2285 for (String nextHopRead : nhListRead) {
2286 if (nextHopRead.equals(nextHop)) {
2287 updateNextHops = true;
2289 nextHopList.add(nextHopRead);
2295 try (AcquireResult lock = tryInterfaceLock(infName)) {
2296 if (!lock.wasAcquired()) {
2297 // FIXME: why do we even bother with locking if we do not honor it?!
2298 logTryLockFailure(infName);
2301 if (updateNextHops) {
2302 // An update must be done, not including the current next hop
2303 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2304 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2305 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2306 .setNextHopIpList(nextHopList)
2307 .withKey(new AdjacencyKey(destination))
2309 Adjacencies erAdjs =
2310 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2311 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2312 .addAugmentation(Adjacencies.class, erAdjs).build();
2313 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2314 vpnIfIdentifier, vpnIf);
2316 // Remove the whole route
2317 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2318 adjacencyIdentifier);
2319 LOG.trace("extra route {} deleted successfully", route);
2322 } catch (TransactionCommitFailedException | ReadFailedException e) {
2323 LOG.error("exception in deleting extra route with destination {} for interface {}",
2324 destination, infName, e);
2327 LOG.error("Incorrect input received for extra route: {}", route);
2332 public void removeVpn(Uuid vpnId) {
2334 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2335 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2336 List<Uuid> routerUuidList = new ArrayList<>();
2337 // dissociate router
2338 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2339 for (RouterIds router : routerIdsList) {
2340 Uuid routerId = router.getRouterId();
2341 routerUuidList.add(routerId);
2342 dissociateRouterFromVpn(vpnId, routerId);
2345 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2346 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2348 // remove entire vpnMaps node
2349 deleteVpnMapsNode(vpnId);
2351 // remove vpn-instance
2352 deleteVpnInstance(vpnId);
2353 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2356 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2357 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2360 // TODO Clean up the exception handling
2361 @SuppressWarnings("checkstyle:IllegalCatch")
2362 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2363 updateVpnMaps(vpnId, null, routerId, null, null);
2364 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2365 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2366 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2367 for (Subnetmap sn : subMapList) {
2368 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2369 if (!ipVersion.isIpVersionChosen(ipVers)) {
2370 ipVersion = ipVersion.addVersion(ipVers);
2373 if (ipVersion != IpVersionChoice.UNDEFINED) {
2374 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2376 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2378 for (Subnetmap sn : subMapList) {
2379 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2383 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2384 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2385 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2386 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2387 for (Uuid subnet : routerSubnets) {
2388 IpVersionChoice version = NeutronvpnUtils
2389 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2390 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2391 addSubnetToVpn(vpnId, subnet, null);
2393 addSubnetToVpn(vpnId, subnet, internetVpnId);
2398 // TODO Clean up the exception handling
2399 @SuppressWarnings("checkstyle:IllegalCatch")
2400 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2402 clearFromVpnMaps(vpnId, routerId, null);
2403 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2404 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2405 for (Subnetmap sn : subMapList) {
2406 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2407 if (ipVersion.isIpVersionChosen(ipVers)) {
2408 ipVersion = ipVersion.addVersion(ipVers);
2410 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2411 routerId.getValue());
2412 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2414 if (ipVersion != IpVersionChoice.UNDEFINED) {
2415 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2417 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2423 * Parses and associates networks list with given VPN.
2425 * @param vpnId Uuid of given VPN.
2426 * @param networkList List list of network Ids (Uuid), which will be associated.
2427 * @return list of formatted strings with detailed error messages.
2430 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2431 List<String> failedNwList = new ArrayList<>();
2432 HashSet<Uuid> passedNwList = new HashSet<>();
2433 boolean isExternalNetwork = false;
2434 if (networkList.isEmpty()) {
2435 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2436 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2438 return failedNwList;
2440 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2441 if (vpnInstance == null) {
2442 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2443 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2444 + "in ConfigDS", vpnId.getValue()));
2445 return failedNwList;
2448 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2449 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2451 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2452 + "associated with", vpnId.getValue()));
2453 return failedNwList;
2455 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2456 for (Uuid nw : networkList) {
2457 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2458 if (network == null) {
2459 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2460 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2464 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2465 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2466 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2467 nw.getValue(), vpnId.getValue());
2468 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2469 nw.getValue(), vpnId.getValue()));
2472 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2473 if (networkVpnId != null) {
2474 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2475 nw.getValue(), networkVpnId.getValue());
2476 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2477 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2480 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2481 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2482 nw.getValue(), vpnId.getValue());
2483 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2484 nw.getValue(), vpnId.getValue()));
2487 if (NeutronvpnUtils.getIsExternal(network)) {
2488 isExternalNetwork = true;
2490 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2491 if (subnetmapList == null || subnetmapList.isEmpty()) {
2492 passedNwList.add(nw);
2495 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2498 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2499 for (Subnetmap subnetmap : subnetmapList) {
2500 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2501 if (!ipVersion.isIpVersionChosen(ipVers)) {
2502 ipVersion = ipVersion.addVersion(ipVers);
2505 if (ipVersion != IpVersionChoice.UNDEFINED) {
2506 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2507 + " for VPN {} ", ipVersion, vpnId);
2508 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2510 for (Subnetmap subnetmap : subnetmapList) {
2511 Uuid subnetId = subnetmap.getId();
2512 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2513 if (subnetVpnId != null) {
2514 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2515 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2516 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2517 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2520 if (!NeutronvpnUtils.getIsExternal(network)) {
2521 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2523 addSubnetToVpn(vpnId, subnetId, null);
2524 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2526 passedNwList.add(nw);
2529 passedNwList.add(nw);
2531 } catch (ReadFailedException e) {
2532 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2534 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2537 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2538 if (!isExternalNetwork) {
2539 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2541 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2542 return failedNwList;
2545 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2546 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2549 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2550 if (vpnOpDataEntry == null) {
2551 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2554 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2555 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2556 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2558 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2559 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2560 updateVpnMaps(vpnId, null, null, null, extNwList);
2561 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2562 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2563 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2565 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2568 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2569 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2572 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2573 updateVpnInternetForSubnet(sm, vpnId, true);
2575 if (!ipVersion.isIpVersionChosen(ipVers)) {
2576 ipVersion = ipVersion.addVersion(ipVers);
2579 if (ipVersion != IpVersionChoice.UNDEFINED) {
2580 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2581 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2582 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2588 * Parses and disassociates networks list from given VPN.
2590 * @param vpnId Uuid of given VPN.
2591 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2592 * @return list of formatted strings with detailed error messages.
2595 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2596 List<String> failedNwList = new ArrayList<>();
2597 HashSet<Uuid> passedNwList = new HashSet<>();
2598 if (networkList.isEmpty()) {
2599 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2600 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2602 return failedNwList;
2604 for (Uuid nw : networkList) {
2605 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2606 if (networkSubnets == null) {
2607 passedNwList.add(nw);
2610 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2611 if (network == null) {
2612 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2613 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2617 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2618 if (networkVpnId == null) {
2619 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2620 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2624 if (!vpnId.equals(networkVpnId)) {
2625 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2626 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2627 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2628 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2632 if (NeutronvpnUtils.getIsExternal(network)) {
2633 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2634 passedNwList.add(nw);
2636 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2637 nw.getValue(), vpnId.getValue());
2638 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2643 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2644 for (Uuid subnet : networkSubnets) {
2645 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2646 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2647 if (!ipVersion.isIpVersionChosen(ipVers)) {
2648 ipVersion = ipVersion.addVersion(ipVers);
2650 if (!NeutronvpnUtils.getIsExternal(network)) {
2651 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2653 removeSubnetFromVpn(vpnId, subnet, null);
2654 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2655 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2657 passedNwList.add(nw);
2660 if (ipVersion != IpVersionChoice.UNDEFINED) {
2661 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2662 + " for VPN {}", ipVersion, vpnId);
2663 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2666 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2667 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2668 passedNwList.toString(), vpnId.getValue());
2669 return failedNwList;
2672 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2673 if (!removeExternalNetworkFromVpn(extNet)) {
2676 // check, if there is another Provider Networks associated with given VPN
2677 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2678 if (vpnNets != null) {
2679 //Remove currently disassociated network from the list
2680 vpnNets.remove(extNet.getUuid());
2681 for (Uuid netId : vpnNets) {
2682 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2683 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2684 + "{}", vpnId.getValue(), netId.getValue());
2689 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2690 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2691 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2692 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2693 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2694 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2695 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2697 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2700 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2701 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2704 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2705 updateVpnInternetForSubnet(sm, vpnId, false);
2707 if (!ipVersion.isIpVersionChosen(ipVers)) {
2708 ipVersion = ipVersion.addVersion(ipVers);
2711 if (ipVersion != IpVersionChoice.UNDEFINED) {
2712 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2713 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2715 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2721 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2724 // TODO Clean up the exception handling
2725 @SuppressWarnings("checkstyle:IllegalCatch")
2726 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2728 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2729 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2730 StringBuilder returnMsg = new StringBuilder();
2731 Uuid vpnId = input.getVpnId();
2734 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2735 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2736 input.getNetworkId().toString());
2737 List<Uuid> netIds = input.getNetworkId();
2738 if (netIds != null && !netIds.isEmpty()) {
2739 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2740 if (!failed.isEmpty()) {
2741 returnMsg.append(failed);
2745 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2747 if (returnMsg.length() != 0) {
2748 opBuilder.setResponse(
2749 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2750 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2751 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2753 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2755 } catch (Exception ex) {
2756 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2757 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2758 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2759 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2761 LOG.debug("associateNetworks returns..");
2766 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2769 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2771 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2772 LOG.debug("associateRouter {}", input);
2773 StringBuilder returnMsg = new StringBuilder();
2774 Uuid vpnId = input.getVpnId();
2775 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2776 routerIds = input.getRouterIds();
2777 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2778 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2779 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2780 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2781 .RouterIds routerId : routerIds) {
2782 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2783 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2784 if (vpnMap != null) {
2786 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2787 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2788 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2789 .append(routerId.getRouterId());
2790 } else if (extVpnId != null) {
2791 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2792 + "another VPN ").append(extVpnId.getValue());
2794 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2795 routerId.getRouterId());
2796 associateRouterToVpn(vpnId, routerId.getRouterId());
2799 returnMsg.append("router not found : ").append(routerId.getRouterId());
2802 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2804 if (returnMsg.length() != 0) {
2805 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2806 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2807 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2809 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2812 LOG.debug("associateRouter returns..");
2817 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2820 // TODO Clean up the exception handling
2821 @SuppressWarnings("checkstyle:IllegalCatch")
2822 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2823 GetFixedIPsForNeutronPortInput input) {
2824 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2825 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2826 Uuid portId = input.getPortId();
2827 StringBuilder returnMsg = new StringBuilder();
2829 List<String> fixedIPList = new ArrayList<>();
2830 Port port = neutronvpnUtils.getNeutronPort(portId);
2832 for (FixedIps ip : port.nonnullFixedIps()) {
2833 fixedIPList.add(ip.getIpAddress().stringValue());
2836 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2838 if (returnMsg.length() != 0) {
2839 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2841 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2842 returnMsg)).build());
2844 opBuilder.setFixedIPs(fixedIPList);
2845 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2847 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2849 } catch (Exception ex) {
2850 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2851 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2852 portId.getValue(), ex.getMessage(), ex)).build());
2858 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2861 // TODO Clean up the exception handling
2862 @SuppressWarnings("checkstyle:IllegalCatch")
2863 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2865 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2866 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2868 LOG.debug("dissociateNetworks {}", input);
2869 StringBuilder returnMsg = new StringBuilder();
2870 Uuid vpnId = input.getVpnId();
2873 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2874 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2875 input.getNetworkId().toString());
2876 List<Uuid> netIds = input.getNetworkId();
2877 if (netIds != null && !netIds.isEmpty()) {
2878 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2879 if (!failed.isEmpty()) {
2880 returnMsg.append(failed);
2884 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2886 if (returnMsg.length() != 0) {
2887 opBuilder.setResponse(
2888 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2889 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2891 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2893 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2895 } catch (Exception ex) {
2896 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2897 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2898 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2900 LOG.debug("dissociateNetworks returns..");
2905 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2908 // TODO Clean up the exception handling
2909 @SuppressWarnings("checkstyle:IllegalCatch")
2910 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2912 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2914 LOG.debug("dissociateRouter {}", input);
2915 StringBuilder returnMsg = new StringBuilder();
2916 Uuid vpnId = input.getVpnId();
2917 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2918 .RouterIds> routerIdList = input.getRouterIds();
2919 String routerIdsString = "";
2920 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2921 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2922 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2923 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2924 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2925 .RouterIds routerId : routerIdList) {
2927 if (routerId != null) {
2928 routerIdsString += routerId.getRouterId() + ", ";
2929 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2931 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2932 if (routerVpnId == null) {
2933 returnMsg.append("input router ").append(routerId.getRouterId())
2934 .append(" not associated to any vpn yet");
2935 } else if (vpnId.equals(routerVpnId)) {
2936 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2938 returnMsg.append("input router ").append(routerId.getRouterId())
2939 .append(" associated to vpn ")
2940 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2943 returnMsg.append("router not found : ").append(routerId.getRouterId());
2946 if (returnMsg.length() != 0) {
2947 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2948 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2949 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2950 returnMsg)).build());
2952 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2954 } catch (Exception ex) {
2955 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2956 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2957 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2961 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2964 LOG.debug("dissociateRouter returns..");
2968 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2969 // check if the router is associated to some VPN
2970 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2971 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2972 if (vpnId != null) {
2973 // remove existing external vpn interfaces
2974 for (Uuid subnetId : routerSubnetIds) {
2975 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2977 clearFromVpnMaps(vpnId, routerId, null);
2979 // remove existing internal vpn interfaces
2980 for (Uuid subnetId : routerSubnetIds) {
2981 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2984 // delete entire vpnMaps node for internal VPN
2985 deleteVpnMapsNode(routerId);
2987 // delete vpn-instance for internal VPN
2988 deleteVpnInstance(routerId);
2991 protected Subnet getNeutronSubnet(Uuid subnetId) {
2992 return neutronvpnUtils.getNeutronSubnet(subnetId);
2996 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2997 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2999 return sn.getGatewayIp();
3005 protected Network getNeutronNetwork(Uuid networkId) {
3006 return neutronvpnUtils.getNeutronNetwork(networkId);
3009 protected Port getNeutronPort(String name) {
3010 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3013 protected Port getNeutronPort(Uuid portId) {
3014 return neutronvpnUtils.getNeutronPort(portId);
3017 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3018 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3021 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3022 return neutronvpnUtils.getNetworksForVpn(vpnId);
3026 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3028 * @return a List of String to be printed on screen
3029 * @throws ReadFailedException if there was a problem reading from the data store
3031 public List<String> showNeutronPortsCLI() throws ReadFailedException {
3032 List<String> result = new ArrayList<>();
3033 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3035 result.add("-------------------------------------------------------------------------------------------");
3036 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3038 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3039 if (ports.isPresent() && ports.get().getPort() != null) {
3040 for (Port port : ports.get().nonnullPort()) {
3041 List<FixedIps> fixedIPs = port.getFixedIps();
3042 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3043 List<String> ipList = new ArrayList<>();
3044 for (FixedIps fixedIp : fixedIPs) {
3045 IpAddress ipAddress = fixedIp.getIpAddress();
3046 if (ipAddress.getIpv4Address() != null) {
3047 ipList.add(ipAddress.getIpv4Address().getValue());
3049 ipList.add(ipAddress.getIpv6Address().getValue());
3052 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3053 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3054 ipList.toString()));
3056 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3057 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3066 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3068 * @param vpnuuid Uuid of the VPN whose config must be shown
3069 * @return formatted output list
3070 * @throws InterruptedException if there was a thread related problem getting the data to display
3071 * @throws ExecutionException if there was any other problem getting the data to display
3073 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3074 List<String> result = new ArrayList<>();
3075 if (vpnuuid == null) {
3077 result.add("Displaying VPN config for all VPNs");
3078 result.add("To display VPN config for a particular VPN, use the following syntax");
3079 result.add(getshowVpnConfigCLIHelp());
3081 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3082 if (rpcResult.isSuccessful()) {
3084 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3086 result.add(String.format(" %-80s ", "Import-RTs"));
3088 result.add(String.format(" %-80s ", "Export-RTs"));
3090 result.add(String.format(" %-76s ", "Subnet IDs"));
3092 result.add("------------------------------------------------------------------------------------");
3094 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3095 rpcResult.getResult().nonnullL3vpnInstances()) {
3096 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3098 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3099 vpn.getRouteDistinguisher()));
3101 result.add(String.format(" %-80s ", vpn.getImportRT()));
3103 result.add(String.format(" %-80s ", vpn.getExportRT()));
3106 Uuid vpnid = vpn.getId();
3107 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3108 if (!subnetList.isEmpty()) {
3109 for (Uuid subnetuuid : subnetList) {
3110 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3113 result.add(String.format(" %-76s ", "\" \""));
3116 result.add("----------------------------------------");
3120 String errortag = rpcResult.getErrors().iterator().next().getTag();
3121 if (Objects.equals(errortag, "")) {
3123 result.add("No VPN has been configured yet");
3124 } else if (Objects.equals(errortag, "invalid-value")) {
3126 result.add("VPN " + vpnuuid.getValue() + " is not present");
3128 result.add("error getting VPN info : " + rpcResult.getErrors());
3129 result.add(getshowVpnConfigCLIHelp());
3135 protected void createExternalVpnInterfaces(Uuid extNetId) {
3136 if (extNetId == null) {
3137 LOG.error("createExternalVpnInterfaces: external network is null");
3141 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3142 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3143 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3147 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3148 for (String elanInterface : extElanInterfaces) {
3149 createExternalVpnInterface(extNetId, elanInterface, tx);
3151 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3154 // TODO Clean up the exception handling
3155 @SuppressWarnings("checkstyle:IllegalCatch")
3156 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3157 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3158 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3159 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3162 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3163 for (String elanInterface : extElanInterfaces) {
3164 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3165 .buildVpnInterfaceIdentifier(elanInterface);
3166 LOG.info("Removing vpn interface {}", elanInterface);
3167 tx.delete(vpnIfIdentifier);
3169 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3172 private void createExternalVpnInterface(Uuid vpnId, String infName,
3173 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3174 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3175 false /* not a router iface */, wrtConfigTxn);
3178 // TODO Clean up the exception handling
3179 @SuppressWarnings("checkstyle:IllegalCatch")
3180 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3181 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3182 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3183 if (vpnIdList.isEmpty() || infName == null) {
3184 LOG.error("vpnid is empty or interface({}) is null", infName);
3187 if (wrtConfigTxn == null) {
3188 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3189 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3190 "Error writing VPN interface");
3193 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3194 for (Uuid vpnId: vpnIdList) {
3195 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3196 AssociatedSubnetType.V4AndV6Subnets);
3197 vpnIdListStruct.add(vpnInstance);
3200 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3201 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3203 .setVpnInstanceNames(vpnIdListStruct)
3204 .setRouterInterface(isRouterInterface);
3205 LOG.info("Network Id is {}", networkUuid);
3206 if (networkUuid != null) {
3207 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3208 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3209 NetworkAttributes.NetworkType networkType = providerType != null
3210 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3211 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3212 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3213 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3216 if (adjacencies != null) {
3217 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3219 VpnInterface vpnIf = vpnb.build();
3221 LOG.info("Creating vpn interface {}", vpnIf);
3222 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3223 } catch (Exception ex) {
3224 LOG.error("Creation of vpninterface {} failed", infName, ex);
3228 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3229 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3230 if (vpnId == null || infName == null) {
3231 LOG.error("vpn id or interface is null");
3234 if (wrtConfigTxn == null) {
3235 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3236 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3237 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3238 }), LOG, "Error updating VPN interface with adjacencies");
3242 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3244 try (AcquireResult lock = tryInterfaceLock(infName)) {
3245 if (!lock.wasAcquired()) {
3246 // FIXME: why do we even bother with locking if we do not honor it?!
3247 logTryLockFailure(infName);
3251 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3252 .syncReadOptional(dataBroker, LogicalDatastoreType
3253 .CONFIGURATION, vpnIfIdentifier);
3254 if (optionalVpnInterface.isPresent()) {
3255 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3256 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3258 if (adjacencies == null) {
3261 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3262 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3263 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3264 optionalVpnInterface.get().getVpnInstanceNames());
3265 if (listVpnInstances.isEmpty()
3266 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3267 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3268 AssociatedSubnetType.V4AndV6Subnets);
3269 listVpnInstances.add(vpnInstance);
3270 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3273 VpnInstanceNames vpnInstance = VpnHelper
3274 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3275 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3276 listVpnInstances.add(vpnInstance);
3277 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3279 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3280 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3282 } catch (IllegalStateException | ReadFailedException ex) {
3283 // FIXME: why are we catching IllegalStateException here?
3284 LOG.error("Update of vpninterface {} failed", infName, ex);
3289 private String getshowVpnConfigCLIHelp() {
3290 StringBuilder help = new StringBuilder("Usage:");
3291 help.append("display vpn-config [-vid/--vpnid <id>]");
3292 return help.toString();
3295 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3296 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3300 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3301 return neutronEvpnManager.createEVPN(input);
3305 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3306 return neutronEvpnManager.getEVPN(input);
3310 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3311 return neutronEvpnManager.deleteEVPN(input);
3314 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3315 Uuid extNetId = extNet.getUuid();
3316 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3317 .child(Networks.class, new NetworksKey(extNetId)).build();
3320 Optional<Networks> optionalExtNets =
3321 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3323 if (!optionalExtNets.isPresent()) {
3324 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3325 extNetId.getValue());
3328 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3329 builder.setVpnid(vpnId);
3330 Networks networks = builder.build();
3331 // Add Networks object to the ExternalNetworks list
3332 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3333 extNetId.getValue());
3334 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3337 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3338 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3339 extNetId.getValue(), ex);
3344 private boolean removeExternalNetworkFromVpn(Network extNet) {
3345 Uuid extNetId = extNet.getUuid();
3346 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3347 .child(Networks.class, new NetworksKey(extNetId)).build();
3349 Optional<Networks> optionalNets =
3350 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3352 NetworksBuilder builder = null;
3353 if (optionalNets.isPresent()) {
3354 builder = new NetworksBuilder(optionalNets.get());
3356 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3357 extNetId.getValue());
3360 builder.setVpnid(null);
3361 Networks networks = builder.build();
3362 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3363 extNetId.getValue());
3364 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3366 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3367 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3368 extNetId.getValue(), ex);
3373 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3374 Optional<String> existingVpnName = Optional.of(primaryRd);
3375 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3377 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3378 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3379 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3380 } catch (ReadFailedException e) {
3381 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3383 /*Read failed. We don't know if a VPN exists or not.
3384 * Return primaryRd to halt caller execution, to be safe.*/
3385 return existingVpnName;
3387 if (vpnInstanceOpDataOptional.isPresent()) {
3388 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3390 existingVpnName = Optional.absent();
3392 return existingVpnName;
3395 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3396 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3399 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3400 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3403 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3404 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3407 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3408 String message = tuple.getMessage();
3409 logger.accept(message);
3413 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3414 @NonNull Subnetmap subnetMap) {
3415 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3416 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3417 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3418 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3419 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3420 subnetMap.getId().getValue(), internetVpnId.getValue());
3424 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3425 @NonNull Subnetmap subnetMap) {
3426 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3427 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3430 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3431 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3432 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3433 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3434 internetVpnId.getValue(), routerId.getValue());
3435 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3441 private AcquireResult tryInterfaceLock(final String infName) {
3442 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3446 private AcquireResult tryVpnLock(final Uuid vpnId) {
3447 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3450 private static ReentrantLock lockForUuid(Uuid uuid) {
3451 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3452 return JvmGlobalLocks.getLockForString(uuid.getValue());
3455 private static void logTryLockFailure(Object objectId) {
3456 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());