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;
13 import static org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils.requireNonNullElse;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.JdkFutureAdapters;
20 import com.google.common.util.concurrent.ListenableFuture;
21 import com.google.common.util.concurrent.MoreExecutors;
22 import com.google.common.util.concurrent.SettableFuture;
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.Nonnull;
42 import javax.annotation.Nullable;
43 import javax.annotation.PreDestroy;
44 import javax.inject.Inject;
45 import javax.inject.Singleton;
46 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
47 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
48 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
49 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
50 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
51 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
52 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
53 import org.opendaylight.genius.infra.Datastore.Configuration;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
55 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
56 import org.opendaylight.genius.infra.TypedWriteTransaction;
57 import org.opendaylight.genius.mdsalutil.NwConstants;
58 import org.opendaylight.genius.utils.JvmGlobalLocks;
59 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
60 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
61 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
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.router.interfaces.map.RouterInterfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
179 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
180 import org.opendaylight.yangtools.yang.common.RpcError;
181 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
182 import org.opendaylight.yangtools.yang.common.RpcResult;
183 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
184 import org.slf4j.Logger;
185 import org.slf4j.LoggerFactory;
186 import org.slf4j.helpers.FormattingTuple;
187 import org.slf4j.helpers.MessageFormatter;
190 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
192 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
193 private static long LOCK_WAIT_TIME = 10L;
195 private final DataBroker dataBroker;
196 private final ManagedNewTransactionRunner txRunner;
197 private final NotificationPublishService notificationPublishService;
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 KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
210 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
213 public NeutronvpnManager(
214 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
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 notificationPublishService = notiPublishService;
223 vpnRpcService = vpnRpcSrv;
224 this.elanService = elanService;
225 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
226 this.neutronvpnConfig = neutronvpnConfig;
227 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
228 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
229 this.jobCoordinator = jobCoordinator;
230 this.neutronvpnUtils = neutronvpnUtils;
231 this.vpnManager = vpnManager;
238 public void close() {
239 LOG.info("{} close", getClass().getSimpleName());
242 private void configureFeatures() throws TransactionCommitFailedException {
243 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
244 Neutron.class).child(Features.class).child(
245 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
246 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
248 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
249 } catch (OptimisticLockFailedException e) {
250 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
252 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
253 Neutron.class).child(Features.class).child(
254 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
255 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
257 SingleTransactionDataBroker.syncWrite(
258 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
259 } catch (OptimisticLockFailedException e) {
260 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
264 public String getOpenDaylightVniRangesConfig() {
265 return neutronvpnConfig.getOpendaylightVniRanges();
268 // TODO Clean up the exception handling
269 @SuppressWarnings("checkstyle:IllegalCatch")
270 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
271 @Nullable NetworkAttributes.NetworkType networkType, long segmentationId) {
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);
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> portList = builder.getPortList();
399 if (null == portList) {
400 portList = new ArrayList<>();
402 portList.add(portId);
403 builder.setPortList(portList);
404 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
405 subnetId.getValue(), portId.getValue());
407 if (null != directPortId) {
408 List<Uuid> directPortList = builder.getDirectPortList();
409 if (null == directPortList) {
410 directPortList = new ArrayList<>();
412 directPortList.add(directPortId);
413 builder.setDirectPortList(directPortList);
414 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
415 directPortId.getValue());
417 subnetmap = builder.build();
418 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
421 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
422 + "cache ", subnetId.getValue(), portId.getValue());
423 unprocessedPortsMap.put(portId, subnetId);
425 } catch (ReadFailedException | TransactionCommitFailedException e) {
426 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
433 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
434 Uuid vpnId, @Nullable Uuid portId) {
435 Subnetmap subnetmap = null;
436 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
437 .child(Subnetmap.class, new SubnetmapKey(subnetId))
439 final ReentrantLock lock = lockForUuid(subnetId);
442 Optional<Subnetmap> sn =
443 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
445 if (sn.isPresent()) {
446 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
447 if (routerId != null) {
448 builder.setRouterId(null);
450 if (networkId != null) {
451 builder.setNetworkId(null);
454 builder.setVpnId(null);
456 builder.setInternetVpnId(null);
457 if (portId != null && builder.getPortList() != null) {
458 List<Uuid> portList = builder.getPortList();
459 portList.remove(portId);
460 builder.setPortList(portList);
463 subnetmap = builder.build();
464 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
465 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
468 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
470 } catch (ReadFailedException | TransactionCommitFailedException e) {
471 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
479 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
480 @Nullable Uuid directPortId) {
481 Subnetmap subnetmap = null;
482 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
483 new SubnetmapKey(subnetId)).build();
484 final ReentrantLock lock = lockForUuid(subnetId);
487 Optional<Subnetmap> sn =
488 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
490 if (sn.isPresent()) {
491 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
492 if (null != portId && null != builder.getPortList()) {
493 List<Uuid> portList = builder.getPortList();
494 portList.remove(portId);
495 builder.setPortList(portList);
496 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
497 subnetId.getValue());
499 if (null != directPortId && null != builder.getDirectPortList()) {
500 List<Uuid> directPortList = builder.getDirectPortList();
501 directPortList.remove(directPortId);
502 builder.setDirectPortList(directPortList);
503 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
504 .getValue(), subnetId.getValue());
506 subnetmap = builder.build();
507 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
510 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
512 } catch (ReadFailedException | TransactionCommitFailedException e) {
513 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
514 subnetId.getValue(), e);
521 // TODO Clean up the exception handling
522 @SuppressWarnings("checkstyle:IllegalCatch")
523 protected void deleteSubnetMapNode(Uuid subnetId) {
524 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
525 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
526 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
527 final ReentrantLock lock = lockForUuid(subnetId);
530 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
531 } catch (TransactionCommitFailedException e) {
532 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
538 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
539 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
540 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
542 Optional<VpnInstance> vpnInstanceConfig =
543 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
545 if (!vpnInstanceConfig.isPresent()) {
546 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
549 VpnInstance vpnInstance = vpnInstanceConfig.get();
550 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
551 if (vpnInstance.getIpv4Family() != null) {
552 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
553 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
555 if (vpnInstance.getIpv6Family() != null) {
556 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
557 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
559 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
560 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
561 updateVpnInstanceBuilder.build());
562 } catch (ReadFailedException | TransactionCommitFailedException ex) {
563 LOG.warn("Error configuring feature ", ex);
567 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
568 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
569 String vpnName = vpnId.getValue();
570 VpnInstanceBuilder builder = null;
571 List<VpnTarget> vpnTargetList = new ArrayList<>();
572 boolean isLockAcquired = false;
573 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
574 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
576 Optional<VpnInstance> optionalVpn =
577 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
579 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
580 if (optionalVpn.isPresent()) {
581 builder = new VpnInstanceBuilder(optionalVpn.get());
582 LOG.debug("updating existing vpninstance node");
584 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
585 .setType(type).setL3vni(l3vni);
587 if (irt != null && !irt.isEmpty()) {
588 if (ert != null && !ert.isEmpty()) {
589 List<String> commonRT = new ArrayList<>(irt);
590 commonRT.retainAll(ert);
592 for (String common : commonRT) {
595 VpnTarget vpnTarget =
596 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
597 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
598 vpnTargetList.add(vpnTarget);
601 for (String importRT : irt) {
602 VpnTarget vpnTarget =
603 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
604 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
605 vpnTargetList.add(vpnTarget);
609 if (ert != null && !ert.isEmpty()) {
610 for (String exportRT : ert) {
611 VpnTarget vpnTarget =
612 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
613 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
614 vpnTargetList.add(vpnTarget);
618 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
620 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
621 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
623 if (rd != null && !rd.isEmpty()) {
624 ipv4vpnBuilder.setRouteDistinguisher(rd);
625 ipv6vpnBuilder.setRouteDistinguisher(rd);
628 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
629 builder.setIpv4Family(ipv4vpnBuilder.build());
631 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
632 builder.setIpv6Family(ipv6vpnBuilder.build());
634 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
635 builder.setIpv4Family(ipv4vpnBuilder.build());
637 VpnInstance newVpn = builder.build();
638 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
639 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
640 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
642 } catch (ReadFailedException | TransactionCommitFailedException e) {
643 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
645 if (isLockAcquired) {
646 vpnLock.unlock(vpnId);
651 private void deleteVpnMapsNode(Uuid vpnId) {
652 boolean isLockAcquired = false;
653 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
654 .child(VpnMap.class, new VpnMapKey(vpnId))
656 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
658 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
659 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
660 } catch (TransactionCommitFailedException e) {
661 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
663 if (isLockAcquired) {
664 vpnLock.unlock(vpnId);
669 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
670 @Nullable List<Uuid> networks) {
671 VpnMapBuilder builder;
672 boolean isLockAcquired = false;
673 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
674 .child(VpnMap.class, new VpnMapKey(vpnId))
677 Optional<VpnMap> optionalVpnMap =
678 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
680 if (optionalVpnMap.isPresent()) {
681 builder = new VpnMapBuilder(optionalVpnMap.get());
683 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
687 builder.setName(name);
689 if (tenantId != null) {
690 builder.setTenantId(tenantId);
692 if (router != null) {
693 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
694 List<RouterIds> rtrIds = builder.getRouterIds();
695 if (rtrIds == null) {
696 rtrIds = Collections.singletonList(vpnRouterId);
698 rtrIds.add(vpnRouterId);
700 builder.setRouterIds(rtrIds);
702 if (networks != null) {
703 List<Uuid> nwList = builder.getNetworkIds();
704 if (nwList == null) {
705 nwList = new ArrayList<>();
707 nwList.addAll(networks);
708 builder.setNetworkIds(nwList);
711 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
712 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
713 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
715 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
716 } catch (ReadFailedException | TransactionCommitFailedException e) {
717 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
719 if (isLockAcquired) {
720 vpnLock.unlock(vpnId);
725 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
726 boolean isLockAcquired = false;
727 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
728 .child(VpnMap.class, new VpnMapKey(vpnId))
730 Optional<VpnMap> optionalVpnMap;
733 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
735 } catch (ReadFailedException e) {
736 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
739 if (optionalVpnMap.isPresent()) {
740 VpnMap vpnMap = optionalVpnMap.get();
741 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
742 List<RouterIds> rtrIds = vpnMap.getRouterIds();
743 if (rtrIds == null) {
744 rtrIds = new ArrayList<>();
746 if (routerId != null) {
747 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
748 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
749 vpnMapBuilder.setRouterIds(rtrIds);
751 // remove entire node in case of internal VPN
752 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
753 LOG.debug("removing vpnMaps node: {} ", vpnId);
754 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
756 } catch (TransactionCommitFailedException e) {
757 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
759 if (isLockAcquired) {
760 vpnLock.unlock(vpnId);
764 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
765 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
766 vpnMapBuilder.setRouterIds(rtrIds);
767 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
770 if (networkIds != null) {
771 List<Uuid> vpnNw = vpnMap.getNetworkIds();
772 vpnNw.removeAll(networkIds);
773 if (vpnNw.isEmpty()) {
774 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
775 vpnMapBuilder.setNetworkIds(null);
777 vpnMapBuilder.setNetworkIds(vpnNw);
782 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
783 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
784 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
785 vpnMapBuilder.build());
786 } catch (TransactionCommitFailedException e) {
787 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
789 if (isLockAcquired) {
790 vpnLock.unlock(vpnId);
794 LOG.error("VPN : {} not found", vpnId.getValue());
796 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
799 private void deleteVpnInstance(Uuid vpnId) {
800 boolean isLockAcquired = false;
801 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
802 .child(VpnInstance.class,
803 new VpnInstanceKey(vpnId.getValue()))
806 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
807 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
808 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
809 } catch (TransactionCommitFailedException e) {
810 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
812 if (isLockAcquired) {
813 vpnLock.unlock(vpnId);
818 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
819 TypedWriteTransaction<Configuration> wrtConfigTxn,
820 @Nullable Subnetmap sn, @Nullable VpnInterface vpnIface) {
821 List<Adjacency> adjList = new ArrayList<>();
822 if (vpnIface != null) {
823 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
825 String infName = port.getUuid().getValue();
826 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
827 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
828 String ipValue = ip.getIpAddress().stringValue();
829 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
830 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
831 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
832 snTemp.getSubnetIp(), false)) {
835 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
837 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
838 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
839 //Create Neutron port adjacency if VPN presence is existing for subnet
840 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
841 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
842 .setSubnetId(ip.getSubnetId()).build();
843 if (!adjList.contains(vmAdj)) {
847 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
848 if (snTemp != null && snTemp.getInternetVpnId() != null) {
849 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
850 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
852 if (routerId != null) {
853 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
854 if (rtr != null && rtr.getRoutes() != null) {
855 List<Routes> routeList = rtr.getRoutes();
856 // create extraroute Adjacence for each ipValue,
857 // because router can have IPv4 and IPv6 subnet ports, or can have
858 // more that one IPv4 subnet port or more than one IPv6 subnet port
859 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
860 if (!erAdjList.isEmpty()) {
861 adjList.addAll(erAdjList);
866 return new AdjacenciesBuilder().setAdjacency(adjList).build();
869 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
870 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
871 boolean isRouterInterface = false;
872 if (port.getDeviceOwner() != null) {
873 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
875 String infName = port.getUuid().getValue();
876 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
877 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
878 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, vpnIface);
879 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
880 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
883 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
884 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
885 String infName = port.getUuid().getValue();
886 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
887 Optional<VpnInterface> optionalVpnInterface = null;
888 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
889 vpnId, internetVpnId, infName);
891 optionalVpnInterface = SingleTransactionDataBroker
892 .syncReadOptional(dataBroker, LogicalDatastoreType
893 .CONFIGURATION, vpnIfIdentifier);
894 } catch (ReadFailedException e) {
895 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
898 if (!optionalVpnInterface.isPresent()) {
901 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
902 sn != null ? sn.getSubnetIp() : "null");
903 List<Adjacency> vpnAdjsList =
904 requireNonNullElse(optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency(),
905 Collections.emptyList());
906 List<Adjacency> updatedAdjsList = new ArrayList<>();
907 boolean isIpFromAnotherSubnet = false;
908 for (Adjacency adj : vpnAdjsList) {
909 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
910 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
911 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
912 isIpFromAnotherSubnet = true;
914 updatedAdjsList.add(adj);
917 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
918 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
921 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
922 String.valueOf(adjString), wrtConfigTxn);
924 if (internetVpnId != null) {
925 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
926 String.valueOf(adjString), wrtConfigTxn);
929 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
930 && sn.getRouterId() != null) {
931 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
932 if (rtr != null && rtr.getRoutes() != null) {
933 List<Routes> extraRoutesToRemove = new ArrayList<>();
934 for (Routes rt: rtr.getRoutes()) {
935 if (rt.getNexthop().toString().equals(adjString)) {
936 extraRoutesToRemove.add(rt);
940 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
941 extraRoutesToRemove, vpnId);
942 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
944 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
949 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
951 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
953 if (!isIpFromAnotherSubnet) {
954 // no more subnetworks for neutron port
955 if (sn != null && sn.getRouterId() != null) {
956 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
958 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
964 // TODO Clean up the exception handling
965 @SuppressWarnings("checkstyle:IllegalCatch")
966 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
967 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
968 if (wrtConfigTxn == null) {
969 ListenableFutures.addErrorLogging(
970 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
971 tx -> deleteVpnInterface(infName, vpnId, tx)),
972 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
976 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
977 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
978 Optional<VpnInterface> optionalVpnInterface;
980 optionalVpnInterface =
981 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
983 } catch (ReadFailedException ex) {
984 LOG.error("Error during deletion of vpninterface {}", infName, ex);
987 if (!optionalVpnInterface.isPresent()) {
988 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
992 VpnInterface vpnInterface = optionalVpnInterface.get();
993 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
995 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
996 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
997 if (!vpnList.isEmpty()) {
998 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
999 + "List not empty", infName);
1002 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1003 .setVpnInstanceNames(vpnList);
1004 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1008 LOG.debug("Deleting vpn interface {}", infName);
1009 wrtConfigTxn.delete(vpnIfIdentifier);
1012 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1013 TypedWriteTransaction<Configuration> writeConfigTxn,
1015 if (vpnId == null || port == null) {
1018 String infName = port.getUuid().getValue();
1019 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1021 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1022 .syncReadOptional(dataBroker, LogicalDatastoreType
1023 .CONFIGURATION, vpnIfIdentifier);
1024 if (optionalVpnInterface.isPresent()) {
1025 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1027 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1028 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1030 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1031 .setVpnInstanceNames(listVpn);
1032 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1033 LOG.debug("Updating vpn interface {}", infName);
1034 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1035 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1036 while (adjacencyIter.hasNext()) {
1037 Adjacency adjacency = adjacencyIter.next();
1038 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1041 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1042 InstanceIdentifier<LearntVpnVipToPort> id =
1043 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1044 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1045 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1046 LogicalDatastoreType.OPERATIONAL, id);
1047 if (optionalVpnVipToPort.isPresent()) {
1048 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1050 if (listVpn == null || listVpn.isEmpty()) {
1051 adjacencyIter.remove();
1053 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1054 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1055 mipToQuery, infName, vpnId.getValue());
1058 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1059 String ipValue = ip.getIpAddress().stringValue();
1061 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1064 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1065 ipValue, writeConfigTxn);
1067 if (listVpn == null || listVpn.isEmpty()) {
1068 if (sm != null && sm.getRouterId() != null) {
1069 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1071 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1073 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1076 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1078 } catch (ReadFailedException ex) {
1079 LOG.error("Update of vpninterface {} failed", infName, ex);
1083 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1085 TypedWriteTransaction<Configuration> writeConfigTxn,
1086 boolean isInternetVpn) {
1087 if (vpnId == null || port == null) {
1090 boolean isLockAcquired = false;
1091 String infName = port.getUuid().getValue();
1092 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1095 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1096 Optional<VpnInterface> optionalVpnInterface =
1097 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1099 if (optionalVpnInterface.isPresent()) {
1100 VpnInstanceNames vpnInstance = VpnHelper
1101 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1102 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1103 .get().getVpnInstanceNames());
1104 if (oldVpnId != null
1105 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1106 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1108 if (vpnId.getValue() != null
1109 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1110 listVpn.add(vpnInstance);
1112 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1113 .setVpnInstanceNames(listVpn);
1114 LOG.debug("Updating vpn interface {}", infName);
1115 if (!isBeingAssociated) {
1116 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1117 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1118 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1119 while (adjacencyIter.hasNext()) {
1120 Adjacency adjacency = adjacencyIter.next();
1121 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1122 InstanceIdentifier<LearntVpnVipToPort> id =
1123 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1124 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1125 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1126 LogicalDatastoreType.OPERATIONAL, id);
1127 if (optionalVpnVipToPort.isPresent()) {
1128 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1129 + "from VPN {}", infName, vpnId, oldVpnId);
1130 adjacencyIter.remove();
1131 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1133 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1134 mipToQuery, infName, vpnId.getValue());
1137 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1138 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1140 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1141 String ipValue = ip.getIpAddress().stringValue();
1142 if (oldVpnId != null) {
1143 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1144 ipValue, writeConfigTxn);
1146 if ((NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6)
1147 && (isInternetVpn == true)) {
1151 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1152 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1154 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1156 LOG.error("VPN Interface {} not found", infName);
1158 } catch (ReadFailedException ex) {
1159 LOG.error("Updation of vpninterface {} failed", infName, ex);
1161 if (isLockAcquired) {
1162 interfaceLock.unlock(infName);
1167 public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List<String> rd,
1168 @Nullable List<String> irt, @Nullable List<String> ert, @Nullable Uuid router,
1169 @Nullable List<Uuid> networks) {
1171 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1173 // Update VPN Instance node
1174 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1176 // Update local vpn-subnet DS
1177 updateVpnMaps(vpn, name, router, tenant, networks);
1179 if (router != null) {
1180 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1181 if (existingVpn != null) {
1182 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1183 // if before reboot, router was already associated to VPN, should not proceed associating router to
1184 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1185 // preserved upon reboot.
1186 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1187 // RouterInterfacesMap via #createVPNInterface call.
1188 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1189 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1192 associateRouterToInternalVpn(vpn, router);
1197 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1198 * specified Neutron Networks and Routers.
1200 * @param vpnId Uuid of the VPN tp be created
1201 * @param name Representative name of the new VPN
1202 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1203 * @param rdList Route-distinguisher for the VPN
1204 * @param irtList A list of Import Route Targets
1205 * @param ertList A list of Export Route Targets
1206 * @param routerIdsList ist of neutron router Id to associate with created VPN
1207 * @param networkList UUID of the neutron network the VPN may be associated to
1208 * @param type Type of the VPN Instance
1209 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1210 * @throws Exception if association of L3VPN failed
1212 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1213 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1214 VpnInstance.Type type, long l3vni) throws Exception {
1216 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1218 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1219 for (Uuid routerId : routerIdsList) {
1220 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1221 ipVersChoices = ipVersChoices.addVersion(vers);
1224 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1226 // Please note that router and networks will be filled into VPNMaps
1227 // by subsequent calls here to associateRouterToVpn and
1228 // associateNetworksToVpn
1229 updateVpnMaps(vpnId, name, null, tenantId, null);
1230 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1231 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1234 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1235 for (Uuid routerId : routerIdsList) {
1236 associateRouterToVpn(vpnId, routerId);
1239 if (networkList != null) {
1240 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1241 if (!failStrings.isEmpty()) {
1242 LOG.error("VPN {} association to networks failed for networks: {}. ",
1243 vpnId.getValue(), failStrings.toString());
1244 throw new Exception(failStrings.toString());
1250 * It handles the invocations to the createVPN RPC method.
1253 // TODO Clean up the exception handling
1254 @SuppressWarnings("checkstyle:IllegalCatch")
1255 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1257 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1258 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1259 List<RpcError> errorList = new ArrayList<>();
1260 int failurecount = 0;
1261 int warningcount = 0;
1263 List<L3vpn> vpns = input.getL3vpn();
1265 vpns = Collections.emptyList();
1267 for (L3vpn vpn : vpns) {
1268 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1269 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1270 formatAndLog(LOG::warn,
1271 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1272 vpn.getId().getValue())));
1276 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1277 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1278 formatAndLog(LOG::warn,
1279 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1280 vpn.getId().getValue())));
1284 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1286 if (vpn.getL3vni() != null) {
1287 l3vni = vpn.getL3vni();
1290 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1291 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1292 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1293 formatAndLog(LOG::warn,
1294 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1295 + "is already configured",
1296 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1300 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1301 if (operationalVpn.isPresent()) {
1302 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1303 formatAndLog(LOG::error,
1304 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1305 + "is still available. Please retry creation of a new vpn with the same RD"
1306 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1307 vpn.getRouteDistinguisher().get(0))));
1311 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1312 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1313 routerIdsList = vpn.getRouterIds();
1314 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1315 routerId : routerIdsList) {
1316 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1317 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1318 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1319 + "{}", vpn.getId(), routerId.getRouterId())));
1323 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1324 if (vpnId != null) {
1325 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1326 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1327 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1328 vpnId.getValue())));
1334 if (vpn.getNetworkIds() != null) {
1335 int initialWarningCount = warningcount;
1336 for (Uuid nw : vpn.getNetworkIds()) {
1337 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1338 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1339 if (network == null) {
1340 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1341 formatAndLog(LOG::warn,
1342 "Creation of L3VPN failed for VPN {} due to network not found {}",
1343 vpn.getId().getValue(), nw.getValue())));
1345 } else if (vpnId != null) {
1346 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1347 formatAndLog(LOG::warn,
1348 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1349 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1350 vpnId.getValue())));
1354 if (warningcount != initialWarningCount) {
1358 List<Uuid> rtrIdsList = new ArrayList<>();
1359 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1360 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1361 rtrId : vpn.getRouterIds()) {
1362 rtrIdsList.add(rtrId.getRouterId());
1366 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1367 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1368 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1369 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1370 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1371 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1372 vpnInstanceType, l3vni);
1373 } catch (Exception ex) {
1374 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1375 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1380 // if at least one succeeds; result is success
1381 // if none succeeds; result is failure
1382 if (failurecount + warningcount == vpns.size()) {
1383 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1385 List<String> errorResponseList = new ArrayList<>();
1386 if (!errorList.isEmpty()) {
1387 for (RpcError rpcError : errorList) {
1388 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1389 + ", ErrorMessage: " + rpcError.getMessage());
1392 errorResponseList.add("Operation successful with no errors");
1394 opBuilder.setResponse(errorResponseList);
1395 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1401 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1404 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1406 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1407 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1408 Uuid inputVpnId = input.getId();
1409 List<VpnInstance> vpns = new ArrayList<>();
1410 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1413 if (inputVpnId == null) {
1415 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1417 Optional<VpnInstances> optionalVpns =
1418 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1420 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1421 for (VpnInstance vpn : requireNonNullElse(optionalVpns.get().getVpnInstance(),
1422 Collections.<VpnInstance>emptyList())) {
1423 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1424 // from getL3VPN output
1425 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1428 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1434 opBuilder.setL3vpnInstances(l3vpnList);
1435 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1439 String name = inputVpnId.getValue();
1440 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1441 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1442 // read VpnInstance Info
1443 Optional<VpnInstance> optionalVpn =
1444 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1446 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1448 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1449 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1450 vpns.add(optionalVpn.get());
1453 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1454 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1458 for (VpnInstance vpnInstance : vpns) {
1459 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1460 // create VpnMaps id
1461 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1462 List<String> rd = Collections.EMPTY_LIST;
1463 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1464 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1465 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1466 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1468 List<String> ertList = new ArrayList<>();
1469 List<String> irtList = new ArrayList<>();
1471 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1472 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1473 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1474 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1475 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1476 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1477 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1479 if (!vpnTargetList.isEmpty()) {
1480 for (VpnTarget vpnTarget : vpnTargetList) {
1481 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1482 ertList.add(vpnTarget.getVrfRTValue());
1484 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1485 irtList.add(vpnTarget.getVrfRTValue());
1487 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1488 ertList.add(vpnTarget.getVrfRTValue());
1489 irtList.add(vpnTarget.getVrfRTValue());
1495 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1497 if (vpnInstance.getL3vni() != null) {
1498 l3vpn.setL3vni(vpnInstance.getL3vni());
1500 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1501 .class, new VpnMapKey(vpnId)).build();
1502 Optional<VpnMap> optionalVpnMap =
1503 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1505 if (optionalVpnMap.isPresent()) {
1506 VpnMap vpnMap = optionalVpnMap.get();
1507 List<Uuid> rtrIds = new ArrayList<>();
1508 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1509 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1510 rtrIds.add(rtrId.getRouterId());
1513 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1514 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1515 .setName(vpnMap.getName());
1518 l3vpnList.add(l3vpn.build());
1521 opBuilder.setL3vpnInstances(l3vpnList);
1522 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1524 } catch (ReadFailedException ex) {
1525 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1526 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1532 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1535 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1537 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1538 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1539 List<RpcError> errorList = new ArrayList<>();
1541 int failurecount = 0;
1542 int warningcount = 0;
1543 List<Uuid> vpns = requireNonNullElse(input.getId(), Collections.emptyList());
1544 for (Uuid vpn : vpns) {
1546 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1547 InstanceIdentifier<VpnInstance> vpnIdentifier =
1548 InstanceIdentifier.builder(VpnInstances.class)
1549 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1550 Optional<VpnInstance> optionalVpn =
1551 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1553 if (optionalVpn.isPresent()) {
1556 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1557 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1560 } catch (ReadFailedException ex) {
1561 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1562 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1567 // if at least one succeeds; result is success
1568 // if none succeeds; result is failure
1569 if (failurecount + warningcount == vpns.size()) {
1570 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1572 List<String> errorResponseList = new ArrayList<>();
1573 if (!errorList.isEmpty()) {
1574 for (RpcError rpcError : errorList) {
1575 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1576 + ", ErrorMessage: " + rpcError.getMessage());
1579 errorResponseList.add("Operation successful with no errors");
1581 opBuilder.setResponse(errorResponseList);
1582 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1587 public void createVpnInstanceForSubnet(Uuid subnetId) {
1588 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1589 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1592 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1593 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1594 removeVpn(subnetId);
1597 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1598 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1599 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1600 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1602 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1603 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1606 if (vpnId != null) {
1607 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1608 if (vpnMap == null) {
1609 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1610 + " cannot add subnet {} to VPN", vpnId.getValue(),
1614 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1615 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1616 if (isVpnOfTypeL2(vpnInstance)) {
1617 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1618 NeutronEvpnUtils.Operation.ADD);
1621 if (internetVpnId != null) {
1622 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1623 if (vpnMap == null) {
1624 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1625 + "subnet {} to VPN", internetVpnId.getValue(),
1630 final Uuid internetId = internetVpnId;
1631 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1632 List<Uuid> portList = sn.getPortList();
1633 if (portList != null) {
1634 for (final Uuid portId : portList) {
1635 String vpnInfName = portId.getValue();
1636 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1637 Port port = neutronvpnUtils.getNeutronPort(portId);
1639 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1640 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1643 final Boolean isRouterInterface = port.getDeviceOwner()
1644 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1645 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1646 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1647 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1649 if (vpnIface == null) {
1650 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1651 Set<Uuid> listVpn = new HashSet<>();
1652 if (vpnId != null) {
1655 if (internetId != null) {
1656 listVpn.add(internetId);
1658 writeVpnInterfaceToDs(listVpn,
1659 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1660 if (sn.getRouterId() != null) {
1661 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1664 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1665 if (vpnId != null) {
1666 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1668 if (internetId != null) {
1669 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1678 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1679 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1680 "removeSubnetFromVpn: at least one VPN must be not null");
1681 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1682 vpnId, internetVpnId);
1683 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1685 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1688 VpnMap vpnMap = null;
1689 VpnInstance vpnInstance = null;
1690 if (vpnId != null) {
1691 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1692 if (vpnMap == null) {
1693 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1694 vpnId.getValue(), subnet.getValue());
1697 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1699 if (internetVpnId == null) {
1700 internetVpnId = sn.getInternetVpnId();
1702 if (internetVpnId != null) {
1703 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1704 if (vpnMap == null) {
1705 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1706 + " from Internet VPN",
1707 internetVpnId.getValue(), subnet.getValue());
1711 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1712 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1713 NeutronEvpnUtils.Operation.DELETE);
1715 boolean subnetVpnAssociation = false;
1716 if (vpnId != null && sn.getVpnId() != null
1717 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1718 subnetVpnAssociation = true;
1719 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1720 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1721 subnetVpnAssociation = true;
1723 if (subnetVpnAssociation == false) {
1724 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1725 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1728 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1729 List<Uuid> portList = sn.getPortList();
1730 final Uuid internetId = internetVpnId;
1731 if (portList != null) {
1732 for (final Uuid portId : portList) {
1733 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1734 final Port port = neutronvpnUtils.getNeutronPort(portId);
1735 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1736 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1737 CONFIGURATION, tx -> {
1739 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1742 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1743 + "port is absent in Neutron config DS", portId.getValue(),
1749 //update subnet-vpn association
1750 removeFromSubnetNode(subnet, null, null, vpnId, null);
1753 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1754 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1755 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1757 Uuid internalVpnId = sm.getVpnId();
1758 if (internalVpnId == null) {
1759 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1760 sm.getId().getValue());
1763 if (isBeingAssociated) {
1764 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1766 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1769 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1770 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1771 if (isBeingAssociated) {
1772 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1773 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1775 removeInternetVpnFromVpnInterface(vpn,
1776 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1781 // Check for ports on this subnet and update association of
1782 // corresponding vpn-interfaces to internet vpn
1783 List<Uuid> portList = sm.getPortList();
1784 if (portList != null) {
1785 for (Uuid port : portList) {
1786 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1787 port.getValue(), isBeingAssociated);
1788 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1789 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1791 if (isBeingAssociated) {
1792 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1793 true, false, tx, true);
1795 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1803 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1804 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1805 oldVpnId.getValue(), newVpnId.getValue());
1806 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1807 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1808 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1809 Uuid vpnExtUuid = netIsExternal ? null
1810 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1811 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1813 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1816 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1817 * associated with internet BGP-VPN.
1819 if (vpnExtUuid != null) {
1820 /* Update V6 Internet default route match with new VPN metadata.
1821 * isBeingAssociated = true means oldVpnId is same as routerId
1822 * isBeingAssociated = false means newVpnId is same as routerId
1824 if (isBeingAssociated) {
1825 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1827 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1830 //Update Router Interface first synchronously.
1831 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1832 ListenableFuture<Void> future =
1833 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1834 tx -> updateVpnInterface(newVpnId, oldVpnId,
1835 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1836 isBeingAssociated, true, tx, false));
1837 Futures.addCallback(future, new FutureCallback<Void>() {
1839 public void onSuccess(Void result) {
1840 // Check for ports on this subnet and update association of
1841 // corresponding vpn-interfaces to external vpn
1842 List<Uuid> portList = sn.getPortList();
1843 if (portList != null) {
1844 for (Uuid port : portList) {
1845 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1846 port.getValue(), isBeingAssociated);
1847 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1848 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1849 tx -> updateVpnInterface(newVpnId, oldVpnId,
1850 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1857 public void onFailure(Throwable throwable) {
1859 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1861 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1863 }, MoreExecutors.directExecutor());
1868 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1869 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1870 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1873 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1874 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1875 final ReentrantLock lock = lockForUuid(routerId);
1878 Optional<RouterInterfaces> optRouterInterfaces =
1879 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1880 routerInterfacesId);
1881 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1882 .setInterfaceId(interfaceName).build();
1883 if (optRouterInterfaces.isPresent()) {
1884 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1885 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1887 // TODO Shouldn't we be doing something with builder and interfaces?
1888 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1889 // List<Interfaces> interfaces = new ArrayList<>();
1890 // interfaces.add(routerInterface);
1892 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1893 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1895 } catch (ReadFailedException | TransactionCommitFailedException e) {
1896 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1902 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1903 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1904 final ReentrantLock lock = lockForUuid(routerId);
1907 Optional<RouterInterfaces> optRouterInterfaces =
1908 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1909 routerInterfacesId);
1910 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1911 .setInterfaceId(interfaceName).build();
1912 if (optRouterInterfaces.isPresent()) {
1913 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1914 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1915 if (interfaces != null && interfaces.remove(routerInterface)) {
1916 if (interfaces.isEmpty()) {
1917 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1918 routerInterfacesId);
1920 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1921 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1925 } catch (ReadFailedException | TransactionCommitFailedException e) {
1926 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1933 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1934 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1935 * route will be ignored.
1937 * @param vpnName the VPN identifier
1938 * @param interVpnLinkRoutes The list of static routes
1939 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1941 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1942 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1943 for (Routes route : interVpnLinkRoutes) {
1944 String nexthop = route.getNexthop().stringValue();
1945 String destination = route.getDestination().stringValue();
1946 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1947 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1948 AddStaticRouteInput rpcInput =
1949 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1950 .setVpnInstanceName(vpnName.getValue())
1952 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1953 RpcResult<AddStaticRouteOutput> rpcResult;
1955 rpcResult = labelOuputFtr.get();
1956 if (rpcResult.isSuccessful()) {
1957 LOG.debug("Label generated for destination {} is: {}",
1958 destination, rpcResult.getResult().getLabel());
1960 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1961 destination, nexthop, rpcResult.getErrors());
1963 } catch (InterruptedException | ExecutionException e) {
1964 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1965 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1968 // Any other case is a fault.
1969 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1970 route.getDestination().stringValue(), nexthop);
1977 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1978 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1980 * @param vpnName the VPN identifier
1981 * @param interVpnLinkRoutes The list of static routes
1982 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1984 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1985 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1986 for (Routes route : interVpnLinkRoutes) {
1987 String nexthop = route.getNexthop().stringValue();
1988 String destination = route.getDestination().stringValue();
1989 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1990 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1991 RemoveStaticRouteInput rpcInput =
1992 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1993 .setVpnInstanceName(vpnName.getValue())
1996 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1997 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1999 // Any other case is a fault.
2000 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2001 route.getDestination().stringValue(), nexthop);
2008 * Returns true if the specified nexthop is the other endpoint in an
2009 * InterVpnLink, regarding one of the VPN's point of view.
2011 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
2013 interVpnLink != null
2014 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2015 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2016 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2017 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2021 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2022 List<Adjacency> adjList = new ArrayList<>();
2023 Map<String, List<String>> adjMap = new HashMap<>();
2024 for (Routes route : routeList) {
2025 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2026 LOG.error("Incorrect input received for extra route. {}", route);
2028 String nextHop = route.getNexthop().stringValue();
2029 String destination = route.getDestination().stringValue();
2030 if (!nextHop.equals(fixedIp)) {
2031 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2034 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2036 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2037 if (!hops.contains(nextHop)) {
2043 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2044 final String destination = entry.getKey();
2045 final List<String> ipList = entry.getValue();
2046 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2047 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2048 .withKey(new AdjacencyKey(destination)).build();
2054 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2055 checkAlarmExtraRoutes(vpnId, routeList);
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 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2065 if (infName != null) {
2066 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2067 destination, vpnId.getValue(), nextHop, infName);
2068 boolean isLockAcquired = false;
2070 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2071 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2072 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2073 .child(Adjacency.class, new AdjacencyKey(destination));
2074 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2075 LogicalDatastoreType.CONFIGURATION, path);
2076 if (existingAdjacency.isPresent()
2077 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2078 LOG.error("The route with destination {} nextHop {} is already present as"
2079 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2080 destination, nextHop, infName);
2083 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2084 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2085 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2086 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2087 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2089 } catch (TransactionCommitFailedException e) {
2090 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2091 destination, nextHop, e);
2092 } catch (ReadFailedException e) {
2093 LOG.error("Exception on reading data-store ", e);
2095 if (isLockAcquired) {
2096 interfaceLock.unlock(infName);
2100 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2101 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2108 * This method setup or down an alarm about extra route fault.
2109 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2110 * available RDs, then an alarm and an error is generated.<br>
2111 * <b>Be careful</b> the routeList could be changed.
2113 * @param vpnId the vpnId of vpn to control.
2114 * @param routeList the list of router to check, it could be modified.
2116 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2117 if (!neutronvpnAlarm.isAlarmEnabled()) {
2118 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2121 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2122 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2123 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2127 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2128 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2129 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2133 for (Routes route : routeList) {
2134 // count the number of nexthops for each same route.getDestingation().getValue()
2135 String destination = route.getDestination().stringValue();
2136 String nextHop = route.getNexthop().stringValue();
2137 List<String> nextHopList = new ArrayList<>();
2138 nextHopList.add(nextHop);
2140 for (Routes routeTmp : routeList) {
2141 String routeDest = routeTmp.getDestination().stringValue();
2142 if (!destination.equals(routeDest)) {
2145 String routeNextH = routeTmp.getNexthop().stringValue();
2146 if (nextHop.equals(routeNextH)) {
2150 nextHopList.add(routeTmp.getNexthop().stringValue());
2152 final List<String> rdList = new ArrayList<>();
2153 if (vpnInstance.getIpv4Family() != null
2154 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2155 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2161 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2162 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2163 if (rd != null && !rdList.contains(rd)) {
2168 // 1. VPN Instance Name
2169 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2172 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2173 Uuid routerUuid = routerUuidList.get(0);
2174 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2175 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2177 // 3. List of RDs associated with the VPN
2178 detailsAlarm.append(" List of RDs associated with the VPN: ");
2179 for (String s : rdList) {
2180 detailsAlarm.append(s);
2181 detailsAlarm.append(", ");
2184 // 4. Prefix in question
2185 detailsAlarm.append(" for prefix: ");
2186 detailsAlarm.append(route.getDestination().stringValue());
2188 // 5. List of NHs for the prefix
2189 detailsAlarm.append(" for nextHops: ");
2190 for (String s : nextHopList) {
2191 detailsAlarm.append(s);
2192 detailsAlarm.append(", ");
2195 if (rdList.size() < nbNextHops) {
2196 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2198 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2203 // TODO Clean up the exception handling
2204 @SuppressWarnings("checkstyle:IllegalCatch")
2205 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2206 for (Routes route : routeList) {
2207 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2208 boolean isLockAcquired = false;
2209 String nextHop = route.getNexthop().stringValue();
2210 String destination = route.getDestination().stringValue();
2211 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2213 if (infName == null) {
2214 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2215 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2216 // Proceed to remove the next extra-route
2219 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2220 destination, vpnId.getValue(), nextHop, infName);
2222 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2223 InstanceIdentifier.builder(VpnInterfaces.class)
2224 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2225 .augmentation(Adjacencies.class)
2226 .child(Adjacency.class, new AdjacencyKey(destination))
2230 // Looking for existing prefix in MDSAL database
2231 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2232 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2233 boolean updateNextHops = false;
2234 List<String> nextHopList = new ArrayList<>();
2235 if (adjacency.isPresent()) {
2236 List<String> nhListRead = adjacency.get().getNextHopIpList();
2237 if (nhListRead.size() > 1) { // ECMP case
2238 for (String nextHopRead : nhListRead) {
2239 if (nextHopRead.equals(nextHop)) {
2240 updateNextHops = true;
2242 nextHopList.add(nextHopRead);
2248 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2249 if (updateNextHops) {
2250 // An update must be done, not including the current next hop
2251 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2252 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2253 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2254 .setNextHopIpList(nextHopList)
2255 .withKey(new AdjacencyKey(destination))
2257 Adjacencies erAdjs =
2258 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2259 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2260 .addAugmentation(Adjacencies.class, erAdjs).build();
2261 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2262 vpnIfIdentifier, vpnIf);
2264 // Remove the whole route
2265 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2266 adjacencyIdentifier);
2267 LOG.trace("extra route {} deleted successfully", route);
2269 } catch (TransactionCommitFailedException | ReadFailedException e) {
2270 LOG.error("exception in deleting extra route with destination {} for interface {}",
2271 destination, infName, e);
2273 if (isLockAcquired) {
2274 interfaceLock.unlock(infName);
2278 LOG.error("Incorrect input received for extra route: {}", route);
2283 public void removeVpn(Uuid vpnId) {
2285 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2286 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2287 List<Uuid> routerUuidList = new ArrayList<>();
2288 // dissociate router
2289 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2290 for (RouterIds router : routerIdsList) {
2291 Uuid routerId = router.getRouterId();
2292 routerUuidList.add(routerId);
2293 dissociateRouterFromVpn(vpnId, routerId);
2296 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2297 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2299 // remove entire vpnMaps node
2300 deleteVpnMapsNode(vpnId);
2302 // remove vpn-instance
2303 deleteVpnInstance(vpnId);
2304 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2307 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2308 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2311 // TODO Clean up the exception handling
2312 @SuppressWarnings("checkstyle:IllegalCatch")
2313 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2314 updateVpnMaps(vpnId, null, routerId, null, null);
2315 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2316 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2317 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2318 for (Subnetmap sn : subMapList) {
2319 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2320 if (!ipVersion.isIpVersionChosen(ipVers)) {
2321 ipVersion = ipVersion.addVersion(ipVers);
2324 if (ipVersion != IpVersionChoice.UNDEFINED) {
2325 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2327 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2329 for (Subnetmap sn : subMapList) {
2330 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2334 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2335 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2336 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2337 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2338 for (Uuid subnet : routerSubnets) {
2339 IpVersionChoice version = NeutronvpnUtils
2340 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2341 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2342 addSubnetToVpn(vpnId, subnet, null);
2344 addSubnetToVpn(vpnId, subnet, internetVpnId);
2349 // TODO Clean up the exception handling
2350 @SuppressWarnings("checkstyle:IllegalCatch")
2351 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2353 clearFromVpnMaps(vpnId, routerId, null);
2354 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2355 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2356 for (Subnetmap sn : subMapList) {
2357 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2358 if (ipVersion.isIpVersionChosen(ipVers)) {
2359 ipVersion = ipVersion.addVersion(ipVers);
2361 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2362 routerId.getValue());
2363 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2365 if (ipVersion != IpVersionChoice.UNDEFINED) {
2366 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2368 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2374 * Parses and associates networks list with given VPN.
2376 * @param vpnId Uuid of given VPN.
2377 * @param networkList List list of network Ids (Uuid), which will be associated.
2378 * @return list of formatted strings with detailed error messages.
2381 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2382 List<String> failedNwList = new ArrayList<>();
2383 HashSet<Uuid> passedNwList = new HashSet<>();
2384 boolean isExternalNetwork = false;
2385 if (networkList.isEmpty()) {
2386 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2387 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2389 return failedNwList;
2391 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2392 if (vpnInstance == null) {
2393 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2394 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2395 + "in ConfigDS", vpnId.getValue()));
2396 return failedNwList;
2399 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2400 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2402 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2403 + "associated with", vpnId.getValue()));
2404 return failedNwList;
2406 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2407 for (Uuid nw : networkList) {
2408 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2409 if (network == null) {
2410 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2411 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2415 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2416 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2417 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2418 nw.getValue(), vpnId.getValue());
2419 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2420 nw.getValue(), vpnId.getValue()));
2423 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2424 if (networkVpnId != null) {
2425 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2426 nw.getValue(), networkVpnId.getValue());
2427 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2428 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2431 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2432 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2433 nw.getValue(), vpnId.getValue());
2434 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2435 nw.getValue(), vpnId.getValue()));
2438 if (NeutronvpnUtils.getIsExternal(network)) {
2439 isExternalNetwork = true;
2441 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2442 if (subnetmapList == null || subnetmapList.isEmpty()) {
2443 passedNwList.add(nw);
2446 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2449 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2450 for (Subnetmap subnetmap : subnetmapList) {
2451 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2452 if (!ipVersion.isIpVersionChosen(ipVers)) {
2453 ipVersion = ipVersion.addVersion(ipVers);
2456 if (ipVersion != IpVersionChoice.UNDEFINED) {
2457 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2458 + " for VPN {} ", ipVersion, vpnId);
2459 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2461 for (Subnetmap subnetmap : subnetmapList) {
2462 Uuid subnetId = subnetmap.getId();
2463 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2464 if (subnetVpnId != null) {
2465 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2466 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2467 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2468 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2471 if (!NeutronvpnUtils.getIsExternal(network)) {
2472 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2474 addSubnetToVpn(vpnId, subnetId, null);
2475 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2477 passedNwList.add(nw);
2480 passedNwList.add(nw);
2482 } catch (ReadFailedException e) {
2483 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2485 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2488 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2489 if (!isExternalNetwork) {
2490 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2492 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2493 return failedNwList;
2496 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2497 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2500 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2501 if (vpnOpDataEntry == null) {
2502 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2505 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2506 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2507 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2509 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2510 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2511 updateVpnMaps(vpnId, null, null, null, extNwList);
2512 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2513 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2514 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2516 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2519 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2520 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2523 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2524 updateVpnInternetForSubnet(sm, vpnId, true);
2526 if (!ipVersion.isIpVersionChosen(ipVers)) {
2527 ipVersion = ipVersion.addVersion(ipVers);
2530 if (ipVersion != IpVersionChoice.UNDEFINED) {
2531 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2532 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2533 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2539 * Parses and disassociates networks list from given VPN.
2541 * @param vpnId Uuid of given VPN.
2542 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2543 * @return list of formatted strings with detailed error messages.
2546 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2547 List<String> failedNwList = new ArrayList<>();
2548 HashSet<Uuid> passedNwList = new HashSet<>();
2549 if (networkList.isEmpty()) {
2550 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2551 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2553 return failedNwList;
2555 for (Uuid nw : networkList) {
2556 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2557 if (networkSubnets == null) {
2558 passedNwList.add(nw);
2561 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2562 if (network == null) {
2563 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2564 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2568 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2569 if (networkVpnId == null) {
2570 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2571 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2575 if (!vpnId.equals(networkVpnId)) {
2576 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2577 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2578 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2579 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2583 if (NeutronvpnUtils.getIsExternal(network)) {
2584 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2585 passedNwList.add(nw);
2587 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2588 nw.getValue(), vpnId.getValue());
2589 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2594 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2595 for (Uuid subnet : networkSubnets) {
2596 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2597 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2598 if (!ipVersion.isIpVersionChosen(ipVers)) {
2599 ipVersion = ipVersion.addVersion(ipVers);
2601 if (!NeutronvpnUtils.getIsExternal(network)) {
2602 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2604 removeSubnetFromVpn(vpnId, subnet, null);
2605 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2606 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2608 passedNwList.add(nw);
2611 if (ipVersion != IpVersionChoice.UNDEFINED) {
2612 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2613 + " for VPN {}", ipVersion, vpnId);
2614 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2617 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2618 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2619 passedNwList.toString(), vpnId.getValue());
2620 return failedNwList;
2623 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2624 if (!removeExternalNetworkFromVpn(extNet)) {
2627 // check, if there is another Provider Networks associated with given VPN
2628 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2629 if (vpnNets != null) {
2630 //Remove currently disassociated network from the list
2631 vpnNets.remove(extNet.getUuid());
2632 for (Uuid netId : vpnNets) {
2633 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2634 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2635 + "{}", vpnId.getValue(), netId.getValue());
2640 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2641 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2642 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2643 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2644 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2645 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2646 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2648 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2651 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2652 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2655 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2656 updateVpnInternetForSubnet(sm, vpnId, false);
2658 if (!ipVersion.isIpVersionChosen(ipVers)) {
2659 ipVersion = ipVersion.addVersion(ipVers);
2662 if (ipVersion != IpVersionChoice.UNDEFINED) {
2663 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2664 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2666 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2672 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2675 // TODO Clean up the exception handling
2676 @SuppressWarnings("checkstyle:IllegalCatch")
2677 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2679 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2680 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2681 StringBuilder returnMsg = new StringBuilder();
2682 Uuid vpnId = input.getVpnId();
2685 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2686 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2687 input.getNetworkId().toString());
2688 List<Uuid> netIds = input.getNetworkId();
2689 if (netIds != null && !netIds.isEmpty()) {
2690 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2691 if (!failed.isEmpty()) {
2692 returnMsg.append(failed);
2696 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2698 if (returnMsg.length() != 0) {
2699 opBuilder.setResponse(
2700 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2701 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2702 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2704 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2706 } catch (Exception ex) {
2707 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2708 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2709 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2711 LOG.debug("associateNetworks returns..");
2716 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2719 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2721 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2722 LOG.debug("associateRouter {}", input);
2723 StringBuilder returnMsg = new StringBuilder();
2724 Uuid vpnId = input.getVpnId();
2725 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2726 routerIds = input.getRouterIds();
2727 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2728 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2729 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2730 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2731 .RouterIds routerId : routerIds) {
2732 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2733 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2734 if (vpnMap != null) {
2736 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2737 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2738 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2739 .append(routerId.getRouterId());
2740 } else if (extVpnId != null) {
2741 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2742 + "another VPN ").append(extVpnId.getValue());
2744 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2745 routerId.getRouterId());
2746 associateRouterToVpn(vpnId, routerId.getRouterId());
2749 returnMsg.append("router not found : ").append(routerId.getRouterId());
2752 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2754 if (returnMsg.length() != 0) {
2755 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2756 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2757 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2759 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2762 LOG.debug("associateRouter returns..");
2767 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2770 // TODO Clean up the exception handling
2771 @SuppressWarnings("checkstyle:IllegalCatch")
2772 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2773 GetFixedIPsForNeutronPortInput input) {
2774 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2775 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2776 Uuid portId = input.getPortId();
2777 StringBuilder returnMsg = new StringBuilder();
2779 List<String> fixedIPList = new ArrayList<>();
2780 Port port = neutronvpnUtils.getNeutronPort(portId);
2782 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
2783 fixedIPList.add(ip.getIpAddress().stringValue());
2786 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2788 if (returnMsg.length() != 0) {
2789 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2791 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2792 returnMsg)).build());
2794 opBuilder.setFixedIPs(fixedIPList);
2795 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2797 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2799 } catch (Exception ex) {
2800 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2801 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2802 portId.getValue(), ex.getMessage(), ex)).build());
2808 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2811 // TODO Clean up the exception handling
2812 @SuppressWarnings("checkstyle:IllegalCatch")
2813 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2815 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2816 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2818 LOG.debug("dissociateNetworks {}", input);
2819 StringBuilder returnMsg = new StringBuilder();
2820 Uuid vpnId = input.getVpnId();
2823 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2824 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2825 input.getNetworkId().toString());
2826 List<Uuid> netIds = input.getNetworkId();
2827 if (netIds != null && !netIds.isEmpty()) {
2828 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2829 if (!failed.isEmpty()) {
2830 returnMsg.append(failed);
2834 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2836 if (returnMsg.length() != 0) {
2837 opBuilder.setResponse(
2838 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2839 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2841 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2843 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2845 } catch (Exception ex) {
2846 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2847 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2848 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2850 LOG.debug("dissociateNetworks returns..");
2855 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2858 // TODO Clean up the exception handling
2859 @SuppressWarnings("checkstyle:IllegalCatch")
2860 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2862 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2864 LOG.debug("dissociateRouter {}", input);
2865 StringBuilder returnMsg = new StringBuilder();
2866 Uuid vpnId = input.getVpnId();
2867 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2868 .RouterIds> routerIdList = input.getRouterIds();
2869 String routerIdsString = "";
2870 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2871 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2872 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2873 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2874 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2875 .RouterIds routerId : routerIdList) {
2877 if (routerId != null) {
2878 routerIdsString += routerId.getRouterId() + ", ";
2879 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2881 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2882 if (routerVpnId == null) {
2883 returnMsg.append("input router ").append(routerId.getRouterId())
2884 .append(" not associated to any vpn yet");
2885 } else if (vpnId.equals(routerVpnId)) {
2886 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2888 returnMsg.append("input router ").append(routerId.getRouterId())
2889 .append(" associated to vpn ")
2890 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2893 returnMsg.append("router not found : ").append(routerId.getRouterId());
2896 if (returnMsg.length() != 0) {
2897 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2898 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2899 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2900 returnMsg)).build());
2902 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2904 } catch (Exception ex) {
2905 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2906 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2907 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2911 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2914 LOG.debug("dissociateRouter returns..");
2918 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2919 // check if the router is associated to some VPN
2920 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2921 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2922 if (vpnId != null) {
2923 // remove existing external vpn interfaces
2924 for (Uuid subnetId : routerSubnetIds) {
2925 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2927 clearFromVpnMaps(vpnId, routerId, null);
2929 // remove existing internal vpn interfaces
2930 for (Uuid subnetId : routerSubnetIds) {
2931 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2934 // delete entire vpnMaps node for internal VPN
2935 deleteVpnMapsNode(routerId);
2937 // delete vpn-instance for internal VPN
2938 deleteVpnInstance(routerId);
2941 protected Subnet getNeutronSubnet(Uuid subnetId) {
2942 return neutronvpnUtils.getNeutronSubnet(subnetId);
2946 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2947 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2949 return sn.getGatewayIp();
2955 protected Network getNeutronNetwork(Uuid networkId) {
2956 return neutronvpnUtils.getNeutronNetwork(networkId);
2959 protected Port getNeutronPort(String name) {
2960 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2963 protected Port getNeutronPort(Uuid portId) {
2964 return neutronvpnUtils.getNeutronPort(portId);
2967 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2968 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2971 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2972 return neutronvpnUtils.getNetworksForVpn(vpnId);
2976 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2978 * @return a List of String to be printed on screen
2979 * @throws ReadFailedException if there was a problem reading from the data store
2981 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2982 List<String> result = new ArrayList<>();
2983 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2985 result.add("-------------------------------------------------------------------------------------------");
2986 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2988 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2989 if (ports.isPresent() && ports.get().getPort() != null) {
2990 for (Port port : requireNonNullElse(ports.get().getPort(), Collections.<Port>emptyList())) {
2991 List<FixedIps> fixedIPs = port.getFixedIps();
2992 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2993 List<String> ipList = new ArrayList<>();
2994 for (FixedIps fixedIp : fixedIPs) {
2995 IpAddress ipAddress = fixedIp.getIpAddress();
2996 if (ipAddress.getIpv4Address() != null) {
2997 ipList.add(ipAddress.getIpv4Address().getValue());
2999 ipList.add(ipAddress.getIpv6Address().getValue());
3002 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3003 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3004 ipList.toString()));
3006 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3007 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3016 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3018 * @param vpnuuid Uuid of the VPN whose config must be shown
3019 * @return formatted output list
3020 * @throws InterruptedException if there was a thread related problem getting the data to display
3021 * @throws ExecutionException if there was any other problem getting the data to display
3023 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3024 List<String> result = new ArrayList<>();
3025 if (vpnuuid == null) {
3027 result.add("Displaying VPN config for all VPNs");
3028 result.add("To display VPN config for a particular VPN, use the following syntax");
3029 result.add(getshowVpnConfigCLIHelp());
3031 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3032 if (rpcResult.isSuccessful()) {
3034 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3036 result.add(String.format(" %-80s ", "Import-RTs"));
3038 result.add(String.format(" %-80s ", "Export-RTs"));
3040 result.add(String.format(" %-76s ", "Subnet IDs"));
3042 result.add("------------------------------------------------------------------------------------");
3044 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3045 requireNonNullElse(rpcResult.getResult().getL3vpnInstances(),
3046 Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
3047 .VpnInstance>emptyList())) {
3048 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3050 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3051 vpn.getRouteDistinguisher()));
3053 result.add(String.format(" %-80s ", vpn.getImportRT()));
3055 result.add(String.format(" %-80s ", vpn.getExportRT()));
3058 Uuid vpnid = vpn.getId();
3059 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3060 if (!subnetList.isEmpty()) {
3061 for (Uuid subnetuuid : subnetList) {
3062 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3065 result.add(String.format(" %-76s ", "\" \""));
3068 result.add("----------------------------------------");
3072 String errortag = rpcResult.getErrors().iterator().next().getTag();
3073 if (Objects.equals(errortag, "")) {
3075 result.add("No VPN has been configured yet");
3076 } else if (Objects.equals(errortag, "invalid-value")) {
3078 result.add("VPN " + vpnuuid.getValue() + " is not present");
3080 result.add("error getting VPN info : " + rpcResult.getErrors());
3081 result.add(getshowVpnConfigCLIHelp());
3087 protected void createExternalVpnInterfaces(Uuid extNetId) {
3088 if (extNetId == null) {
3089 LOG.error("createExternalVpnInterfaces: external network is null");
3093 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3094 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3095 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3099 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3100 for (String elanInterface : extElanInterfaces) {
3101 createExternalVpnInterface(extNetId, elanInterface, tx);
3103 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3106 // TODO Clean up the exception handling
3107 @SuppressWarnings("checkstyle:IllegalCatch")
3108 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3109 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3110 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3111 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3114 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3115 for (String elanInterface : extElanInterfaces) {
3116 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3117 .buildVpnInterfaceIdentifier(elanInterface);
3118 LOG.info("Removing vpn interface {}", elanInterface);
3119 tx.delete(vpnIfIdentifier);
3121 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3124 private void createExternalVpnInterface(Uuid vpnId, String infName,
3125 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3126 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3127 false /* not a router iface */, wrtConfigTxn);
3130 // TODO Clean up the exception handling
3131 @SuppressWarnings("checkstyle:IllegalCatch")
3132 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName,
3133 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3134 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3135 if (vpnIdList.isEmpty() || infName == null) {
3136 LOG.error("vpnid is empty or interface({}) is null", infName);
3139 if (wrtConfigTxn == null) {
3140 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3141 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3142 "Error writing VPN interface");
3145 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3146 for (Uuid vpnId: vpnIdList) {
3147 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3148 AssociatedSubnetType.V4AndV6Subnets);
3149 vpnIdListStruct.add(vpnInstance);
3152 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3153 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3155 .setVpnInstanceNames(vpnIdListStruct)
3156 .setRouterInterface(isRouterInterface);
3157 LOG.info("Network Id is {}", networkUuid);
3158 if (networkUuid != null) {
3159 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3160 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3161 NetworkAttributes.NetworkType networkType = providerType != null
3162 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3163 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3164 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3165 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3168 if (adjacencies != null) {
3169 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3171 VpnInterface vpnIf = vpnb.build();
3173 LOG.info("Creating vpn interface {}", vpnIf);
3174 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3175 } catch (Exception ex) {
3176 LOG.error("Creation of vpninterface {} failed", infName, ex);
3180 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3181 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3182 if (vpnId == null || infName == null) {
3183 LOG.error("vpn id or interface is null");
3186 if (wrtConfigTxn == null) {
3187 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3188 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3189 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3190 }), LOG, "Error updating VPN interface with adjacencies");
3194 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3195 boolean isLockAcquired = false;
3197 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3198 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3199 .syncReadOptional(dataBroker, LogicalDatastoreType
3200 .CONFIGURATION, vpnIfIdentifier);
3201 if (optionalVpnInterface.isPresent()) {
3202 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3203 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3205 if (adjacencies == null) {
3206 if (isLockAcquired) {
3207 interfaceLock.unlock(infName);
3211 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3212 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3213 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3214 optionalVpnInterface.get().getVpnInstanceNames());
3215 if (listVpnInstances.isEmpty() || !VpnHelper
3216 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3217 VpnInstanceNames vpnInstance = VpnHelper
3218 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3219 listVpnInstances.add(vpnInstance);
3220 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3223 VpnInstanceNames vpnInstance = VpnHelper
3224 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3225 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3226 listVpnInstances.add(vpnInstance);
3227 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3229 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3230 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3232 } catch (IllegalStateException | ReadFailedException ex) {
3233 LOG.error("Update of vpninterface {} failed", infName, ex);
3235 if (isLockAcquired) {
3236 interfaceLock.unlock(infName);
3241 private String getshowVpnConfigCLIHelp() {
3242 StringBuilder help = new StringBuilder("Usage:");
3243 help.append("display vpn-config [-vid/--vpnid <id>]");
3244 return help.toString();
3247 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3248 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3252 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3253 return neutronEvpnManager.createEVPN(input);
3257 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3258 return neutronEvpnManager.getEVPN(input);
3262 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3263 return neutronEvpnManager.deleteEVPN(input);
3266 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3267 Uuid extNetId = extNet.getUuid();
3268 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3269 .child(Networks.class, new NetworksKey(extNetId)).build();
3272 Optional<Networks> optionalExtNets =
3273 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3275 if (!optionalExtNets.isPresent()) {
3276 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3277 extNetId.getValue());
3280 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3281 builder.setVpnid(vpnId);
3282 Networks networks = builder.build();
3283 // Add Networks object to the ExternalNetworks list
3284 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3285 extNetId.getValue());
3286 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3289 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3290 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3291 extNetId.getValue(), ex);
3296 private boolean removeExternalNetworkFromVpn(Network extNet) {
3297 Uuid extNetId = extNet.getUuid();
3298 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3299 .child(Networks.class, new NetworksKey(extNetId)).build();
3301 Optional<Networks> optionalNets =
3302 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3304 NetworksBuilder builder = null;
3305 if (optionalNets.isPresent()) {
3306 builder = new NetworksBuilder(optionalNets.get());
3308 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3309 extNetId.getValue());
3312 builder.setVpnid(null);
3313 Networks networks = builder.build();
3314 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3315 extNetId.getValue());
3316 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3318 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3319 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3320 extNetId.getValue(), ex);
3325 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3326 Optional<String> existingVpnName = Optional.of(primaryRd);
3327 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3329 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3330 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3331 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3332 } catch (ReadFailedException e) {
3333 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3335 /*Read failed. We don't know if a VPN exists or not.
3336 * Return primaryRd to halt caller execution, to be safe.*/
3337 return existingVpnName;
3339 if (vpnInstanceOpDataOptional.isPresent()) {
3340 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3342 existingVpnName = Optional.absent();
3344 return existingVpnName;
3347 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3348 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3351 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3352 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3355 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3356 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3359 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3360 String message = tuple.getMessage();
3361 logger.accept(message);
3365 protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3366 @Nonnull Subnetmap subnetMap) {
3367 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3368 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3369 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3370 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3371 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3372 subnetMap.getId().getValue(), internetVpnId.getValue());
3376 protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3377 @Nonnull Subnetmap subnetMap) {
3378 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3379 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3382 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3383 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3384 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3385 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3386 internetVpnId.getValue(), routerId.getValue());
3387 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3392 private static ReentrantLock lockForUuid(Uuid uuid) {
3393 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3394 return JvmGlobalLocks.getLockForString(uuid.getValue());