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(), () -> singletonList(
1678 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1679 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1681 if (vpnIface == null) {
1682 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1683 Set<Uuid> listVpn = new HashSet<>();
1684 if (vpnId != null) {
1687 if (internetId != null) {
1688 listVpn.add(internetId);
1690 writeVpnInterfaceToDs(listVpn,
1691 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1692 if (sn.getRouterId() != null) {
1693 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1696 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1697 if (vpnId != null) {
1698 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1700 if (internetId != null) {
1701 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1710 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1711 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1712 "removeSubnetFromVpn: at least one VPN must be not null");
1713 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1714 vpnId, internetVpnId);
1715 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1717 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1720 VpnMap vpnMap = null;
1721 VpnInstance vpnInstance = null;
1722 if (vpnId != null) {
1723 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1724 if (vpnMap == null) {
1725 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1726 vpnId.getValue(), subnet.getValue());
1729 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1731 if (internetVpnId == null) {
1732 internetVpnId = sn.getInternetVpnId();
1734 if (internetVpnId != null) {
1735 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1736 if (vpnMap == null) {
1737 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1738 + " from Internet VPN",
1739 internetVpnId.getValue(), subnet.getValue());
1743 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1744 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1745 NeutronEvpnUtils.Operation.DELETE);
1747 boolean subnetVpnAssociation = false;
1748 if (vpnId != null && sn.getVpnId() != null
1749 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1750 subnetVpnAssociation = true;
1751 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1752 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1753 subnetVpnAssociation = true;
1755 if (subnetVpnAssociation == false) {
1756 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1757 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1760 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1761 List<Uuid> portList = sn.getPortList();
1762 final Uuid internetId = internetVpnId;
1763 if (portList != null) {
1764 for (final Uuid portId : portList) {
1765 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1766 final Port port = neutronvpnUtils.getNeutronPort(portId);
1767 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1768 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1769 CONFIGURATION, tx -> {
1771 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1774 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1775 + "port is absent in Neutron config DS", portId.getValue(),
1781 //update subnet-vpn association
1782 removeFromSubnetNode(subnet, null, null, vpnId, null);
1785 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1786 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1787 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1789 Uuid internalVpnId = sm.getVpnId();
1790 if (internalVpnId == null) {
1791 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1792 sm.getId().getValue());
1795 if (isBeingAssociated) {
1796 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1798 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1801 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1802 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1803 if (isBeingAssociated) {
1804 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1805 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1807 removeInternetVpnFromVpnInterface(vpn,
1808 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1813 // Check for ports on this subnet and update association of
1814 // corresponding vpn-interfaces to internet vpn
1815 List<Uuid> portList = sm.getPortList();
1816 if (portList != null) {
1817 for (Uuid port : portList) {
1818 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1819 port.getValue(), isBeingAssociated);
1820 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1821 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1823 if (isBeingAssociated) {
1824 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1825 true, false, tx, true);
1827 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1835 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1836 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1837 oldVpnId.getValue(), newVpnId.getValue());
1838 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1839 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1840 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1841 Uuid vpnExtUuid = netIsExternal ? null
1842 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1843 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1845 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1848 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1849 * associated with internet BGP-VPN.
1851 if (vpnExtUuid != null) {
1852 /* Update V6 Internet default route match with new VPN metadata.
1853 * isBeingAssociated = true means oldVpnId is same as routerId
1854 * isBeingAssociated = false means newVpnId is same as routerId
1856 if (isBeingAssociated) {
1857 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1859 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1862 //Update Router Interface first synchronously.
1863 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1864 ListenableFuture<Void> future =
1865 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1866 tx -> updateVpnInterface(newVpnId, oldVpnId,
1867 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1868 isBeingAssociated, true, tx, false));
1869 Futures.addCallback(future, new FutureCallback<Void>() {
1871 public void onSuccess(Void result) {
1872 // Check for ports on this subnet and update association of
1873 // corresponding vpn-interfaces to external vpn
1874 List<Uuid> portList = sn.getPortList();
1875 if (portList != null) {
1876 for (Uuid port : portList) {
1877 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1878 port.getValue(), isBeingAssociated);
1879 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1880 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1881 tx -> updateVpnInterface(newVpnId, oldVpnId,
1882 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1889 public void onFailure(Throwable throwable) {
1891 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1893 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1895 }, MoreExecutors.directExecutor());
1900 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1901 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1902 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1905 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1906 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1907 final ReentrantLock lock = lockForUuid(routerId);
1910 Optional<RouterInterfaces> optRouterInterfaces =
1911 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1912 routerInterfacesId);
1913 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1914 .setInterfaceId(interfaceName).build();
1915 if (optRouterInterfaces.isPresent()) {
1916 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1917 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1919 // TODO Shouldn't we be doing something with builder and interfaces?
1920 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1921 // List<Interfaces> interfaces = new ArrayList<>();
1922 // interfaces.add(routerInterface);
1924 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1925 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1927 } catch (ReadFailedException | TransactionCommitFailedException e) {
1928 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1934 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1935 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1936 final ReentrantLock lock = lockForUuid(routerId);
1939 Optional<RouterInterfaces> optRouterInterfaces =
1940 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1941 routerInterfacesId);
1942 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1943 .setInterfaceId(interfaceName).build();
1944 if (optRouterInterfaces.isPresent()) {
1945 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1946 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces());
1947 if (interfaces != null && interfaces.remove(routerInterface)) {
1948 if (interfaces.isEmpty()) {
1949 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1950 routerInterfacesId);
1952 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1953 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1957 } catch (ReadFailedException | TransactionCommitFailedException e) {
1958 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1965 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1966 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1967 * route will be ignored.
1969 * @param vpnName the VPN identifier
1970 * @param interVpnLinkRoutes The list of static routes
1971 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1973 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1974 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1975 for (Routes route : interVpnLinkRoutes) {
1976 String nexthop = route.getNexthop().stringValue();
1977 String destination = route.getDestination().stringValue();
1978 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1979 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1980 AddStaticRouteInput rpcInput =
1981 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1982 .setVpnInstanceName(vpnName.getValue())
1984 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1985 RpcResult<AddStaticRouteOutput> rpcResult;
1987 rpcResult = labelOuputFtr.get();
1988 if (rpcResult.isSuccessful()) {
1989 LOG.debug("Label generated for destination {} is: {}",
1990 destination, rpcResult.getResult().getLabel());
1992 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1993 destination, nexthop, rpcResult.getErrors());
1995 } catch (InterruptedException | ExecutionException e) {
1996 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1997 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
2000 // Any other case is a fault.
2001 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2002 route.getDestination().stringValue(), nexthop);
2009 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2010 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2012 * @param vpnName the VPN identifier
2013 * @param interVpnLinkRoutes The list of static routes
2014 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2016 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2017 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2018 for (Routes route : interVpnLinkRoutes) {
2019 String nexthop = route.getNexthop().stringValue();
2020 String destination = route.getDestination().stringValue();
2021 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2022 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2023 RemoveStaticRouteInput rpcInput =
2024 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2025 .setVpnInstanceName(vpnName.getValue())
2028 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2029 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2031 // Any other case is a fault.
2032 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2033 route.getDestination().stringValue(), nexthop);
2040 * Returns true if the specified nexthop is the other endpoint in an
2041 * InterVpnLink, regarding one of the VPN's point of view.
2043 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2044 InterVpnLink interVpnLink) {
2046 interVpnLink != null
2047 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2048 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2049 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2050 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2054 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2055 List<Adjacency> adjList = new ArrayList<>();
2056 Map<String, List<String>> adjMap = new HashMap<>();
2057 for (Routes route : routeList) {
2058 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2059 LOG.error("Incorrect input received for extra route. {}", route);
2061 String nextHop = route.getNexthop().stringValue();
2062 String destination = route.getDestination().stringValue();
2063 if (!nextHop.equals(fixedIp)) {
2064 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2067 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2069 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2070 if (!hops.contains(nextHop)) {
2076 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2077 final String destination = entry.getKey();
2078 final List<String> ipList = entry.getValue();
2079 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2080 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2081 .withKey(new AdjacencyKey(destination)).build();
2087 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2088 checkAlarmExtraRoutes(vpnId, routeList);
2090 for (Routes route : routeList) {
2091 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2092 LOG.error("Incorrect input received for extra route. {}", route);
2094 String nextHop = route.getNexthop().stringValue();
2095 String destination = route.getDestination().stringValue();
2096 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2098 if (infName != null) {
2099 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2100 destination, vpnId.getValue(), nextHop, infName);
2101 boolean isLockAcquired = false;
2103 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2104 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2105 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2106 .child(Adjacency.class, new AdjacencyKey(destination));
2107 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2108 LogicalDatastoreType.CONFIGURATION, path);
2109 if (existingAdjacency.isPresent()
2110 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2111 LOG.error("The route with destination {} nextHop {} is already present as"
2112 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2113 destination, nextHop, infName);
2116 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2117 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2118 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2120 try (AcquireResult lock = tryInterfaceLock(infName)) {
2121 if (!lock.wasAcquired()) {
2122 // FIXME: why do we even bother with locking if we do not honor it?!
2123 logTryLockFailure(infName);
2126 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2129 } catch (TransactionCommitFailedException e) {
2130 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2131 destination, nextHop, e);
2132 } catch (ReadFailedException e) {
2133 LOG.error("Exception on reading data-store ", e);
2136 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2137 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2144 * This method setup or down an alarm about extra route fault.
2145 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2146 * available RDs, then an alarm and an error is generated.<br>
2147 * <b>Be careful</b> the routeList could be changed.
2149 * @param vpnId the vpnId of vpn to control.
2150 * @param routeList the list of router to check, it could be modified.
2152 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2153 if (!neutronvpnAlarm.isAlarmEnabled()) {
2154 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2157 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2158 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2159 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2163 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2164 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2165 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2169 for (Routes route : routeList) {
2170 // count the number of nexthops for each same route.getDestingation().getValue()
2171 String destination = route.getDestination().stringValue();
2172 String nextHop = route.getNexthop().stringValue();
2173 List<String> nextHopList = new ArrayList<>();
2174 nextHopList.add(nextHop);
2176 for (Routes routeTmp : routeList) {
2177 String routeDest = routeTmp.getDestination().stringValue();
2178 if (!destination.equals(routeDest)) {
2181 String routeNextH = routeTmp.getNexthop().stringValue();
2182 if (nextHop.equals(routeNextH)) {
2186 nextHopList.add(routeTmp.getNexthop().stringValue());
2188 final List<String> rdList = new ArrayList<>();
2189 if (vpnInstance.getIpv4Family() != null
2190 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2191 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2197 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2198 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2199 if (rd != null && !rdList.contains(rd)) {
2204 // 1. VPN Instance Name
2205 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2208 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2209 Uuid routerUuid = routerUuidList.get(0);
2210 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2211 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2213 // 3. List of RDs associated with the VPN
2214 detailsAlarm.append(" List of RDs associated with the VPN: ");
2215 for (String s : rdList) {
2216 detailsAlarm.append(s);
2217 detailsAlarm.append(", ");
2220 // 4. Prefix in question
2221 detailsAlarm.append(" for prefix: ");
2222 detailsAlarm.append(route.getDestination().stringValue());
2224 // 5. List of NHs for the prefix
2225 detailsAlarm.append(" for nextHops: ");
2226 for (String s : nextHopList) {
2227 detailsAlarm.append(s);
2228 detailsAlarm.append(", ");
2231 if (rdList.size() < nbNextHops) {
2232 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2234 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2239 // TODO Clean up the exception handling
2240 @SuppressWarnings("checkstyle:IllegalCatch")
2241 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2242 for (Routes route : routeList) {
2243 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2244 String nextHop = route.getNexthop().stringValue();
2245 String destination = route.getDestination().stringValue();
2246 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2248 if (infName == null) {
2249 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2250 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2251 // Proceed to remove the next extra-route
2254 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2255 destination, vpnId.getValue(), nextHop, infName);
2257 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2258 InstanceIdentifier.builder(VpnInterfaces.class)
2259 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2260 .augmentation(Adjacencies.class)
2261 .child(Adjacency.class, new AdjacencyKey(destination))
2265 // Looking for existing prefix in MDSAL database
2266 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2267 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2268 boolean updateNextHops = false;
2269 List<String> nextHopList = new ArrayList<>();
2270 if (adjacency.isPresent()) {
2271 List<String> nhListRead = adjacency.get().getNextHopIpList();
2272 if (nhListRead.size() > 1) { // ECMP case
2273 for (String nextHopRead : nhListRead) {
2274 if (nextHopRead.equals(nextHop)) {
2275 updateNextHops = true;
2277 nextHopList.add(nextHopRead);
2283 try (AcquireResult lock = tryInterfaceLock(infName)) {
2284 if (!lock.wasAcquired()) {
2285 // FIXME: why do we even bother with locking if we do not honor it?!
2286 logTryLockFailure(infName);
2289 if (updateNextHops) {
2290 // An update must be done, not including the current next hop
2291 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2292 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2293 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2294 .setNextHopIpList(nextHopList)
2295 .withKey(new AdjacencyKey(destination))
2297 Adjacencies erAdjs =
2298 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2299 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2300 .addAugmentation(Adjacencies.class, erAdjs).build();
2301 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2302 vpnIfIdentifier, vpnIf);
2304 // Remove the whole route
2305 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2306 adjacencyIdentifier);
2307 LOG.trace("extra route {} deleted successfully", route);
2310 } catch (TransactionCommitFailedException | ReadFailedException e) {
2311 LOG.error("exception in deleting extra route with destination {} for interface {}",
2312 destination, infName, e);
2315 LOG.error("Incorrect input received for extra route: {}", route);
2320 public void removeVpn(Uuid vpnId) {
2322 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2323 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2324 List<Uuid> routerUuidList = new ArrayList<>();
2325 // dissociate router
2326 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2327 for (RouterIds router : routerIdsList) {
2328 Uuid routerId = router.getRouterId();
2329 routerUuidList.add(routerId);
2330 dissociateRouterFromVpn(vpnId, routerId);
2333 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2334 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2336 // remove entire vpnMaps node
2337 deleteVpnMapsNode(vpnId);
2339 // remove vpn-instance
2340 deleteVpnInstance(vpnId);
2341 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2344 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2345 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2348 // TODO Clean up the exception handling
2349 @SuppressWarnings("checkstyle:IllegalCatch")
2350 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2351 updateVpnMaps(vpnId, null, routerId, null, null);
2352 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2353 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2354 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2355 for (Subnetmap sn : subMapList) {
2356 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2357 if (!ipVersion.isIpVersionChosen(ipVers)) {
2358 ipVersion = ipVersion.addVersion(ipVers);
2361 if (ipVersion != IpVersionChoice.UNDEFINED) {
2362 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2364 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2366 for (Subnetmap sn : subMapList) {
2367 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2371 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2372 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2373 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2374 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2375 for (Uuid subnet : routerSubnets) {
2376 IpVersionChoice version = NeutronvpnUtils
2377 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2378 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2379 addSubnetToVpn(vpnId, subnet, null);
2381 addSubnetToVpn(vpnId, subnet, internetVpnId);
2386 // TODO Clean up the exception handling
2387 @SuppressWarnings("checkstyle:IllegalCatch")
2388 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2390 clearFromVpnMaps(vpnId, routerId, null);
2391 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2392 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2393 for (Subnetmap sn : subMapList) {
2394 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2395 if (ipVersion.isIpVersionChosen(ipVers)) {
2396 ipVersion = ipVersion.addVersion(ipVers);
2398 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2399 routerId.getValue());
2400 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2402 if (ipVersion != IpVersionChoice.UNDEFINED) {
2403 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2405 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2411 * Parses and associates networks list with given VPN.
2413 * @param vpnId Uuid of given VPN.
2414 * @param networkList List list of network Ids (Uuid), which will be associated.
2415 * @return list of formatted strings with detailed error messages.
2418 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2419 List<String> failedNwList = new ArrayList<>();
2420 HashSet<Uuid> passedNwList = new HashSet<>();
2421 boolean isExternalNetwork = false;
2422 if (networkList.isEmpty()) {
2423 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2424 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2426 return failedNwList;
2428 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2429 if (vpnInstance == null) {
2430 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2431 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2432 + "in ConfigDS", vpnId.getValue()));
2433 return failedNwList;
2436 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2437 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2439 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2440 + "associated with", vpnId.getValue()));
2441 return failedNwList;
2443 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2444 for (Uuid nw : networkList) {
2445 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2446 if (network == null) {
2447 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2448 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2452 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2453 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2454 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2455 nw.getValue(), vpnId.getValue());
2456 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2457 nw.getValue(), vpnId.getValue()));
2460 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2461 if (networkVpnId != null) {
2462 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2463 nw.getValue(), networkVpnId.getValue());
2464 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2465 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2468 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2469 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2470 nw.getValue(), vpnId.getValue());
2471 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2472 nw.getValue(), vpnId.getValue()));
2475 if (NeutronvpnUtils.getIsExternal(network)) {
2476 isExternalNetwork = true;
2478 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2479 if (subnetmapList == null || subnetmapList.isEmpty()) {
2480 passedNwList.add(nw);
2483 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2486 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2487 for (Subnetmap subnetmap : subnetmapList) {
2488 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2489 if (!ipVersion.isIpVersionChosen(ipVers)) {
2490 ipVersion = ipVersion.addVersion(ipVers);
2493 if (ipVersion != IpVersionChoice.UNDEFINED) {
2494 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2495 + " for VPN {} ", ipVersion, vpnId);
2496 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2498 for (Subnetmap subnetmap : subnetmapList) {
2499 Uuid subnetId = subnetmap.getId();
2500 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2501 if (subnetVpnId != null) {
2502 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2503 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2504 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2505 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2508 if (!NeutronvpnUtils.getIsExternal(network)) {
2509 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2511 addSubnetToVpn(vpnId, subnetId, null);
2512 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2514 passedNwList.add(nw);
2517 passedNwList.add(nw);
2519 } catch (ReadFailedException e) {
2520 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2522 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2525 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2526 if (!isExternalNetwork) {
2527 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2529 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2530 return failedNwList;
2533 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2534 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2537 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2538 if (vpnOpDataEntry == null) {
2539 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2542 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2543 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2544 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2546 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2547 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2548 updateVpnMaps(vpnId, null, null, null, extNwList);
2549 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2550 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2551 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2553 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2556 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2557 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2560 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2561 updateVpnInternetForSubnet(sm, vpnId, true);
2563 if (!ipVersion.isIpVersionChosen(ipVers)) {
2564 ipVersion = ipVersion.addVersion(ipVers);
2567 if (ipVersion != IpVersionChoice.UNDEFINED) {
2568 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2569 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2570 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2576 * Parses and disassociates networks list from given VPN.
2578 * @param vpnId Uuid of given VPN.
2579 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2580 * @return list of formatted strings with detailed error messages.
2583 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2584 List<String> failedNwList = new ArrayList<>();
2585 HashSet<Uuid> passedNwList = new HashSet<>();
2586 if (networkList.isEmpty()) {
2587 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2588 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2590 return failedNwList;
2592 for (Uuid nw : networkList) {
2593 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2594 if (networkSubnets == null) {
2595 passedNwList.add(nw);
2598 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2599 if (network == null) {
2600 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2601 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2605 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2606 if (networkVpnId == null) {
2607 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2608 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2612 if (!vpnId.equals(networkVpnId)) {
2613 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2614 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2615 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2616 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2620 if (NeutronvpnUtils.getIsExternal(network)) {
2621 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2622 passedNwList.add(nw);
2624 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2625 nw.getValue(), vpnId.getValue());
2626 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2631 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2632 for (Uuid subnet : networkSubnets) {
2633 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2634 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2635 if (!ipVersion.isIpVersionChosen(ipVers)) {
2636 ipVersion = ipVersion.addVersion(ipVers);
2638 if (!NeutronvpnUtils.getIsExternal(network)) {
2639 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2641 removeSubnetFromVpn(vpnId, subnet, null);
2642 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2643 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2645 passedNwList.add(nw);
2648 if (ipVersion != IpVersionChoice.UNDEFINED) {
2649 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2650 + " for VPN {}", ipVersion, vpnId);
2651 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2654 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2655 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2656 passedNwList.toString(), vpnId.getValue());
2657 return failedNwList;
2660 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2661 if (!removeExternalNetworkFromVpn(extNet)) {
2664 // check, if there is another Provider Networks associated with given VPN
2665 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2666 if (vpnNets != null) {
2667 //Remove currently disassociated network from the list
2668 vpnNets.remove(extNet.getUuid());
2669 for (Uuid netId : vpnNets) {
2670 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2671 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2672 + "{}", vpnId.getValue(), netId.getValue());
2677 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2678 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2679 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2680 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2681 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2682 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2683 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2685 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2688 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2689 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2692 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2693 updateVpnInternetForSubnet(sm, vpnId, false);
2695 if (!ipVersion.isIpVersionChosen(ipVers)) {
2696 ipVersion = ipVersion.addVersion(ipVers);
2699 if (ipVersion != IpVersionChoice.UNDEFINED) {
2700 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2701 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2703 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2709 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2712 // TODO Clean up the exception handling
2713 @SuppressWarnings("checkstyle:IllegalCatch")
2714 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2716 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2717 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2718 StringBuilder returnMsg = new StringBuilder();
2719 Uuid vpnId = input.getVpnId();
2722 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2723 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2724 input.getNetworkId().toString());
2725 List<Uuid> netIds = input.getNetworkId();
2726 if (netIds != null && !netIds.isEmpty()) {
2727 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2728 if (!failed.isEmpty()) {
2729 returnMsg.append(failed);
2733 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2735 if (returnMsg.length() != 0) {
2736 opBuilder.setResponse(
2737 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2738 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2739 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2741 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2743 } catch (Exception ex) {
2744 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2745 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2746 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2747 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2749 LOG.debug("associateNetworks returns..");
2754 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2757 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2759 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2760 LOG.debug("associateRouter {}", input);
2761 StringBuilder returnMsg = new StringBuilder();
2762 Uuid vpnId = input.getVpnId();
2763 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2764 routerIds = input.getRouterIds();
2765 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2766 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2767 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2768 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2769 .RouterIds routerId : routerIds) {
2770 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2771 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2772 if (vpnMap != null) {
2774 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2775 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2776 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2777 .append(routerId.getRouterId());
2778 } else if (extVpnId != null) {
2779 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2780 + "another VPN ").append(extVpnId.getValue());
2782 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2783 routerId.getRouterId());
2784 associateRouterToVpn(vpnId, routerId.getRouterId());
2787 returnMsg.append("router not found : ").append(routerId.getRouterId());
2790 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2792 if (returnMsg.length() != 0) {
2793 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2794 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2795 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2797 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2800 LOG.debug("associateRouter returns..");
2805 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2808 // TODO Clean up the exception handling
2809 @SuppressWarnings("checkstyle:IllegalCatch")
2810 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2811 GetFixedIPsForNeutronPortInput input) {
2812 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2813 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2814 Uuid portId = input.getPortId();
2815 StringBuilder returnMsg = new StringBuilder();
2817 List<String> fixedIPList = new ArrayList<>();
2818 Port port = neutronvpnUtils.getNeutronPort(portId);
2820 for (FixedIps ip : port.nonnullFixedIps()) {
2821 fixedIPList.add(ip.getIpAddress().stringValue());
2824 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2826 if (returnMsg.length() != 0) {
2827 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2829 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2830 returnMsg)).build());
2832 opBuilder.setFixedIPs(fixedIPList);
2833 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2835 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2837 } catch (Exception ex) {
2838 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2839 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2840 portId.getValue(), ex.getMessage(), ex)).build());
2846 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2849 // TODO Clean up the exception handling
2850 @SuppressWarnings("checkstyle:IllegalCatch")
2851 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2853 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2854 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2856 LOG.debug("dissociateNetworks {}", input);
2857 StringBuilder returnMsg = new StringBuilder();
2858 Uuid vpnId = input.getVpnId();
2861 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2862 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2863 input.getNetworkId().toString());
2864 List<Uuid> netIds = input.getNetworkId();
2865 if (netIds != null && !netIds.isEmpty()) {
2866 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2867 if (!failed.isEmpty()) {
2868 returnMsg.append(failed);
2872 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2874 if (returnMsg.length() != 0) {
2875 opBuilder.setResponse(
2876 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2877 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2879 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2881 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2883 } catch (Exception ex) {
2884 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2885 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2886 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2888 LOG.debug("dissociateNetworks returns..");
2893 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2896 // TODO Clean up the exception handling
2897 @SuppressWarnings("checkstyle:IllegalCatch")
2898 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2900 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2902 LOG.debug("dissociateRouter {}", input);
2903 StringBuilder returnMsg = new StringBuilder();
2904 Uuid vpnId = input.getVpnId();
2905 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2906 .RouterIds> routerIdList = input.getRouterIds();
2907 String routerIdsString = "";
2908 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2909 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2910 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2911 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2912 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2913 .RouterIds routerId : routerIdList) {
2915 if (routerId != null) {
2916 routerIdsString += routerId.getRouterId() + ", ";
2917 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2919 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2920 if (routerVpnId == null) {
2921 returnMsg.append("input router ").append(routerId.getRouterId())
2922 .append(" not associated to any vpn yet");
2923 } else if (vpnId.equals(routerVpnId)) {
2924 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2926 returnMsg.append("input router ").append(routerId.getRouterId())
2927 .append(" associated to vpn ")
2928 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2931 returnMsg.append("router not found : ").append(routerId.getRouterId());
2934 if (returnMsg.length() != 0) {
2935 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2936 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2937 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2938 returnMsg)).build());
2940 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2942 } catch (Exception ex) {
2943 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2944 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2945 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2949 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2952 LOG.debug("dissociateRouter returns..");
2956 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2957 // check if the router is associated to some VPN
2958 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2959 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2960 if (vpnId != null) {
2961 // remove existing external vpn interfaces
2962 for (Uuid subnetId : routerSubnetIds) {
2963 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2965 clearFromVpnMaps(vpnId, routerId, null);
2967 // remove existing internal vpn interfaces
2968 for (Uuid subnetId : routerSubnetIds) {
2969 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2972 // delete entire vpnMaps node for internal VPN
2973 deleteVpnMapsNode(routerId);
2975 // delete vpn-instance for internal VPN
2976 deleteVpnInstance(routerId);
2979 protected Subnet getNeutronSubnet(Uuid subnetId) {
2980 return neutronvpnUtils.getNeutronSubnet(subnetId);
2984 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2985 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2987 return sn.getGatewayIp();
2993 protected Network getNeutronNetwork(Uuid networkId) {
2994 return neutronvpnUtils.getNeutronNetwork(networkId);
2997 protected Port getNeutronPort(String name) {
2998 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3001 protected Port getNeutronPort(Uuid portId) {
3002 return neutronvpnUtils.getNeutronPort(portId);
3005 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3006 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3009 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3010 return neutronvpnUtils.getNetworksForVpn(vpnId);
3014 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3016 * @return a List of String to be printed on screen
3017 * @throws ReadFailedException if there was a problem reading from the data store
3019 public List<String> showNeutronPortsCLI() throws ReadFailedException {
3020 List<String> result = new ArrayList<>();
3021 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3023 result.add("-------------------------------------------------------------------------------------------");
3024 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3026 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3027 if (ports.isPresent() && ports.get().getPort() != null) {
3028 for (Port port : ports.get().nonnullPort()) {
3029 List<FixedIps> fixedIPs = port.getFixedIps();
3030 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3031 List<String> ipList = new ArrayList<>();
3032 for (FixedIps fixedIp : fixedIPs) {
3033 IpAddress ipAddress = fixedIp.getIpAddress();
3034 if (ipAddress.getIpv4Address() != null) {
3035 ipList.add(ipAddress.getIpv4Address().getValue());
3037 ipList.add(ipAddress.getIpv6Address().getValue());
3040 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3041 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3042 ipList.toString()));
3044 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3045 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3054 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3056 * @param vpnuuid Uuid of the VPN whose config must be shown
3057 * @return formatted output list
3058 * @throws InterruptedException if there was a thread related problem getting the data to display
3059 * @throws ExecutionException if there was any other problem getting the data to display
3061 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3062 List<String> result = new ArrayList<>();
3063 if (vpnuuid == null) {
3065 result.add("Displaying VPN config for all VPNs");
3066 result.add("To display VPN config for a particular VPN, use the following syntax");
3067 result.add(getshowVpnConfigCLIHelp());
3069 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3070 if (rpcResult.isSuccessful()) {
3072 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3074 result.add(String.format(" %-80s ", "Import-RTs"));
3076 result.add(String.format(" %-80s ", "Export-RTs"));
3078 result.add(String.format(" %-76s ", "Subnet IDs"));
3080 result.add("------------------------------------------------------------------------------------");
3082 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3083 rpcResult.getResult().nonnullL3vpnInstances()) {
3084 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3086 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3087 vpn.getRouteDistinguisher()));
3089 result.add(String.format(" %-80s ", vpn.getImportRT()));
3091 result.add(String.format(" %-80s ", vpn.getExportRT()));
3094 Uuid vpnid = vpn.getId();
3095 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3096 if (!subnetList.isEmpty()) {
3097 for (Uuid subnetuuid : subnetList) {
3098 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3101 result.add(String.format(" %-76s ", "\" \""));
3104 result.add("----------------------------------------");
3108 String errortag = rpcResult.getErrors().iterator().next().getTag();
3109 if (Objects.equals(errortag, "")) {
3111 result.add("No VPN has been configured yet");
3112 } else if (Objects.equals(errortag, "invalid-value")) {
3114 result.add("VPN " + vpnuuid.getValue() + " is not present");
3116 result.add("error getting VPN info : " + rpcResult.getErrors());
3117 result.add(getshowVpnConfigCLIHelp());
3123 protected void createExternalVpnInterfaces(Uuid extNetId) {
3124 if (extNetId == null) {
3125 LOG.error("createExternalVpnInterfaces: external network is null");
3129 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3130 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3131 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3135 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3136 for (String elanInterface : extElanInterfaces) {
3137 createExternalVpnInterface(extNetId, elanInterface, tx);
3139 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3142 // TODO Clean up the exception handling
3143 @SuppressWarnings("checkstyle:IllegalCatch")
3144 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3145 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3146 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3147 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3150 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3151 for (String elanInterface : extElanInterfaces) {
3152 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3153 .buildVpnInterfaceIdentifier(elanInterface);
3154 LOG.info("Removing vpn interface {}", elanInterface);
3155 tx.delete(vpnIfIdentifier);
3157 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3160 private void createExternalVpnInterface(Uuid vpnId, String infName,
3161 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3162 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3163 false /* not a router iface */, wrtConfigTxn);
3166 // TODO Clean up the exception handling
3167 @SuppressWarnings("checkstyle:IllegalCatch")
3168 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3169 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3170 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3171 if (vpnIdList.isEmpty() || infName == null) {
3172 LOG.error("vpnid is empty or interface({}) is null", infName);
3175 if (wrtConfigTxn == null) {
3176 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3177 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3178 "Error writing VPN interface");
3181 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3182 for (Uuid vpnId: vpnIdList) {
3183 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3184 AssociatedSubnetType.V4AndV6Subnets);
3185 vpnIdListStruct.add(vpnInstance);
3188 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3189 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3191 .setVpnInstanceNames(vpnIdListStruct)
3192 .setRouterInterface(isRouterInterface);
3193 LOG.info("Network Id is {}", networkUuid);
3194 if (networkUuid != null) {
3195 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3196 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3197 NetworkAttributes.NetworkType networkType = providerType != null
3198 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3199 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3200 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3201 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3204 if (adjacencies != null) {
3205 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3207 VpnInterface vpnIf = vpnb.build();
3209 LOG.info("Creating vpn interface {}", vpnIf);
3210 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3211 } catch (Exception ex) {
3212 LOG.error("Creation of vpninterface {} failed", infName, ex);
3216 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3217 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3218 if (vpnId == null || infName == null) {
3219 LOG.error("vpn id or interface is null");
3222 if (wrtConfigTxn == null) {
3223 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3224 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3225 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3226 }), LOG, "Error updating VPN interface with adjacencies");
3230 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3232 try (AcquireResult lock = tryInterfaceLock(infName)) {
3233 if (!lock.wasAcquired()) {
3234 // FIXME: why do we even bother with locking if we do not honor it?!
3235 logTryLockFailure(infName);
3239 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3240 .syncReadOptional(dataBroker, LogicalDatastoreType
3241 .CONFIGURATION, vpnIfIdentifier);
3242 if (optionalVpnInterface.isPresent()) {
3243 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3244 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3246 if (adjacencies == null) {
3249 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3250 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3251 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3252 optionalVpnInterface.get().getVpnInstanceNames());
3253 if (listVpnInstances.isEmpty()
3254 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3255 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3256 AssociatedSubnetType.V4AndV6Subnets);
3257 listVpnInstances.add(vpnInstance);
3258 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3261 VpnInstanceNames vpnInstance = VpnHelper
3262 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3263 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3264 listVpnInstances.add(vpnInstance);
3265 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3267 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3268 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3270 } catch (IllegalStateException | ReadFailedException ex) {
3271 // FIXME: why are we catching IllegalStateException here?
3272 LOG.error("Update of vpninterface {} failed", infName, ex);
3277 private String getshowVpnConfigCLIHelp() {
3278 StringBuilder help = new StringBuilder("Usage:");
3279 help.append("display vpn-config [-vid/--vpnid <id>]");
3280 return help.toString();
3283 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3284 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3288 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3289 return neutronEvpnManager.createEVPN(input);
3293 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3294 return neutronEvpnManager.getEVPN(input);
3298 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3299 return neutronEvpnManager.deleteEVPN(input);
3302 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3303 Uuid extNetId = extNet.getUuid();
3304 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3305 .child(Networks.class, new NetworksKey(extNetId)).build();
3308 Optional<Networks> optionalExtNets =
3309 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3311 if (!optionalExtNets.isPresent()) {
3312 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3313 extNetId.getValue());
3316 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3317 builder.setVpnid(vpnId);
3318 Networks networks = builder.build();
3319 // Add Networks object to the ExternalNetworks list
3320 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3321 extNetId.getValue());
3322 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3325 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3326 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3327 extNetId.getValue(), ex);
3332 private boolean removeExternalNetworkFromVpn(Network extNet) {
3333 Uuid extNetId = extNet.getUuid();
3334 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3335 .child(Networks.class, new NetworksKey(extNetId)).build();
3337 Optional<Networks> optionalNets =
3338 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3340 NetworksBuilder builder = null;
3341 if (optionalNets.isPresent()) {
3342 builder = new NetworksBuilder(optionalNets.get());
3344 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3345 extNetId.getValue());
3348 builder.setVpnid(null);
3349 Networks networks = builder.build();
3350 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3351 extNetId.getValue());
3352 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3354 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3355 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3356 extNetId.getValue(), ex);
3361 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3362 Optional<String> existingVpnName = Optional.of(primaryRd);
3363 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3365 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3366 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3367 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3368 } catch (ReadFailedException e) {
3369 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3371 /*Read failed. We don't know if a VPN exists or not.
3372 * Return primaryRd to halt caller execution, to be safe.*/
3373 return existingVpnName;
3375 if (vpnInstanceOpDataOptional.isPresent()) {
3376 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3378 existingVpnName = Optional.absent();
3380 return existingVpnName;
3383 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3384 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3387 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3388 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3391 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3392 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3395 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3396 String message = tuple.getMessage();
3397 logger.accept(message);
3401 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3402 @NonNull Subnetmap subnetMap) {
3403 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3404 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3405 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3406 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3407 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3408 subnetMap.getId().getValue(), internetVpnId.getValue());
3412 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3413 @NonNull Subnetmap subnetMap) {
3414 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3415 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3418 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3419 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3420 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3421 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3422 internetVpnId.getValue(), routerId.getValue());
3423 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3429 private AcquireResult tryInterfaceLock(final String infName) {
3430 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3434 private AcquireResult tryVpnLock(final Uuid vpnId) {
3435 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3438 private static ReentrantLock lockForUuid(Uuid uuid) {
3439 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3440 return JvmGlobalLocks.getLockForString(uuid.getValue());
3443 private static void logTryLockFailure(Object objectId) {
3444 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());