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 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
833 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
834 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
836 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
837 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
838 //Create Neutron port adjacency if VPN presence is existing for subnet
839 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
840 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
841 .setSubnetId(ip.getSubnetId()).build();
842 if (!adjList.contains(vmAdj)) {
846 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
847 if (snTemp != null && snTemp.getInternetVpnId() != null) {
848 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
849 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
851 if (routerId != null) {
852 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
853 if (rtr != null && rtr.getRoutes() != null) {
854 List<Routes> routeList = rtr.getRoutes();
855 // create extraroute Adjacence for each ipValue,
856 // because router can have IPv4 and IPv6 subnet ports, or can have
857 // more that one IPv4 subnet port or more than one IPv6 subnet port
858 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
859 if (!erAdjList.isEmpty()) {
860 adjList.addAll(erAdjList);
865 return new AdjacenciesBuilder().setAdjacency(adjList).build();
868 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
869 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
870 boolean isRouterInterface = false;
871 if (port.getDeviceOwner() != null) {
872 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
874 String infName = port.getUuid().getValue();
875 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
876 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
877 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, vpnIface);
878 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
879 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
882 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
883 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
884 String infName = port.getUuid().getValue();
885 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
886 Optional<VpnInterface> optionalVpnInterface = null;
887 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
888 vpnId, internetVpnId, infName);
890 optionalVpnInterface = SingleTransactionDataBroker
891 .syncReadOptional(dataBroker, LogicalDatastoreType
892 .CONFIGURATION, vpnIfIdentifier);
893 } catch (ReadFailedException e) {
894 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
897 if (!optionalVpnInterface.isPresent()) {
900 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
901 sn != null ? sn.getSubnetIp() : "null");
902 List<Adjacency> vpnAdjsList =
903 requireNonNullElse(optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency(),
904 Collections.emptyList());
905 List<Adjacency> updatedAdjsList = new ArrayList<>();
906 boolean isIpFromAnotherSubnet = false;
907 for (Adjacency adj : vpnAdjsList) {
908 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
909 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
910 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
911 isIpFromAnotherSubnet = true;
913 updatedAdjsList.add(adj);
916 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
917 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
920 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
921 String.valueOf(adjString), wrtConfigTxn);
923 if (internetVpnId != null) {
924 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
925 String.valueOf(adjString), wrtConfigTxn);
928 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
929 && sn.getRouterId() != null) {
930 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
931 if (rtr != null && rtr.getRoutes() != null) {
932 List<Routes> extraRoutesToRemove = new ArrayList<>();
933 for (Routes rt: rtr.getRoutes()) {
934 if (rt.getNexthop().toString().equals(adjString)) {
935 extraRoutesToRemove.add(rt);
939 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
940 extraRoutesToRemove, vpnId);
941 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
943 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
948 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
950 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
952 if (!isIpFromAnotherSubnet) {
953 // no more subnetworks for neutron port
954 if (sn != null && sn.getRouterId() != null) {
955 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
957 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
963 // TODO Clean up the exception handling
964 @SuppressWarnings("checkstyle:IllegalCatch")
965 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
966 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
967 if (wrtConfigTxn == null) {
968 ListenableFutures.addErrorLogging(
969 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
970 tx -> deleteVpnInterface(infName, vpnId, tx)),
971 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
975 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
976 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
977 Optional<VpnInterface> optionalVpnInterface;
979 optionalVpnInterface =
980 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
982 } catch (ReadFailedException ex) {
983 LOG.error("Error during deletion of vpninterface {}", infName, ex);
986 if (!optionalVpnInterface.isPresent()) {
987 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
991 VpnInterface vpnInterface = optionalVpnInterface.get();
992 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
994 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
995 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
996 if (!vpnList.isEmpty()) {
997 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
998 + "List not empty", infName);
1001 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1002 .setVpnInstanceNames(vpnList);
1003 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1007 LOG.debug("Deleting vpn interface {}", infName);
1008 wrtConfigTxn.delete(vpnIfIdentifier);
1011 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1012 TypedWriteTransaction<Configuration> writeConfigTxn,
1014 if (vpnId == null || port == null) {
1017 String infName = port.getUuid().getValue();
1018 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1020 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1021 .syncReadOptional(dataBroker, LogicalDatastoreType
1022 .CONFIGURATION, vpnIfIdentifier);
1023 if (optionalVpnInterface.isPresent()) {
1024 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1026 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1027 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1029 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1030 .setVpnInstanceNames(listVpn);
1031 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1032 LOG.debug("Updating vpn interface {}", infName);
1033 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1034 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1035 while (adjacencyIter.hasNext()) {
1036 Adjacency adjacency = adjacencyIter.next();
1037 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1040 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1041 InstanceIdentifier<LearntVpnVipToPort> id =
1042 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1043 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1044 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1045 LogicalDatastoreType.OPERATIONAL, id);
1046 if (optionalVpnVipToPort.isPresent()) {
1047 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1049 if (listVpn == null || listVpn.isEmpty()) {
1050 adjacencyIter.remove();
1052 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1053 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1054 mipToQuery, infName, vpnId.getValue());
1057 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1058 String ipValue = ip.getIpAddress().stringValue();
1060 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1063 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1064 ipValue, writeConfigTxn);
1066 if (listVpn == null || listVpn.isEmpty()) {
1067 if (sm != null && sm.getRouterId() != null) {
1068 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1070 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1072 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1075 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1077 } catch (ReadFailedException ex) {
1078 LOG.error("Update of vpninterface {} failed", infName, ex);
1082 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1084 TypedWriteTransaction<Configuration> writeConfigTxn,
1085 boolean isInternetVpn) {
1086 if (vpnId == null || port == null) {
1089 boolean isLockAcquired = false;
1090 String infName = port.getUuid().getValue();
1091 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1094 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1095 Optional<VpnInterface> optionalVpnInterface =
1096 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1098 if (optionalVpnInterface.isPresent()) {
1099 VpnInstanceNames vpnInstance = VpnHelper
1100 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1101 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1102 .get().getVpnInstanceNames());
1103 if (oldVpnId != null
1104 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1105 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1107 if (vpnId.getValue() != null
1108 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1109 listVpn.add(vpnInstance);
1111 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1112 .setVpnInstanceNames(listVpn);
1113 LOG.debug("Updating vpn interface {}", infName);
1114 if (!isBeingAssociated) {
1115 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1116 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1117 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1118 while (adjacencyIter.hasNext()) {
1119 Adjacency adjacency = adjacencyIter.next();
1120 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1121 InstanceIdentifier<LearntVpnVipToPort> id =
1122 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1123 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1124 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1125 LogicalDatastoreType.OPERATIONAL, id);
1126 if (optionalVpnVipToPort.isPresent()) {
1127 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1128 + "from VPN {}", infName, vpnId, oldVpnId);
1129 adjacencyIter.remove();
1130 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1132 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1133 mipToQuery, infName, vpnId.getValue());
1136 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1137 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1139 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1140 String ipValue = ip.getIpAddress().stringValue();
1141 if (oldVpnId != null) {
1142 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1143 ipValue, writeConfigTxn);
1145 if ((NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6)
1146 && (isInternetVpn == true)) {
1150 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1151 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1153 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1155 LOG.error("VPN Interface {} not found", infName);
1157 } catch (ReadFailedException ex) {
1158 LOG.error("Updation of vpninterface {} failed", infName, ex);
1160 if (isLockAcquired) {
1161 interfaceLock.unlock(infName);
1166 public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List<String> rd,
1167 @Nullable List<String> irt, @Nullable List<String> ert, @Nullable Uuid router,
1168 @Nullable List<Uuid> networks) {
1170 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1172 // Update VPN Instance node
1173 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1175 // Update local vpn-subnet DS
1176 updateVpnMaps(vpn, name, router, tenant, networks);
1178 if (router != null) {
1179 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1180 if (existingVpn != null) {
1181 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1182 // if before reboot, router was already associated to VPN, should not proceed associating router to
1183 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1184 // preserved upon reboot.
1185 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1186 // RouterInterfacesMap via #createVPNInterface call.
1187 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1188 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1191 associateRouterToInternalVpn(vpn, router);
1196 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1197 * specified Neutron Networks and Routers.
1199 * @param vpnId Uuid of the VPN tp be created
1200 * @param name Representative name of the new VPN
1201 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1202 * @param rdList Route-distinguisher for the VPN
1203 * @param irtList A list of Import Route Targets
1204 * @param ertList A list of Export Route Targets
1205 * @param routerIdsList ist of neutron router Id to associate with created VPN
1206 * @param networkList UUID of the neutron network the VPN may be associated to
1207 * @param type Type of the VPN Instance
1208 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1209 * @throws Exception if association of L3VPN failed
1211 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1212 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1213 VpnInstance.Type type, long l3vni) throws Exception {
1215 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1217 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1218 for (Uuid routerId : routerIdsList) {
1219 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1220 ipVersChoices = ipVersChoices.addVersion(vers);
1223 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1225 // Please note that router and networks will be filled into VPNMaps
1226 // by subsequent calls here to associateRouterToVpn and
1227 // associateNetworksToVpn
1228 updateVpnMaps(vpnId, name, null, tenantId, null);
1229 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1230 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1233 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1234 for (Uuid routerId : routerIdsList) {
1235 associateRouterToVpn(vpnId, routerId);
1238 if (networkList != null) {
1239 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1240 if (!failStrings.isEmpty()) {
1241 LOG.error("VPN {} association to networks failed for networks: {}. ",
1242 vpnId.getValue(), failStrings.toString());
1243 throw new Exception(failStrings.toString());
1249 * It handles the invocations to the createVPN RPC method.
1252 // TODO Clean up the exception handling
1253 @SuppressWarnings("checkstyle:IllegalCatch")
1254 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1256 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1257 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1258 List<RpcError> errorList = new ArrayList<>();
1259 int failurecount = 0;
1260 int warningcount = 0;
1262 List<L3vpn> vpns = input.getL3vpn();
1264 vpns = Collections.emptyList();
1266 for (L3vpn vpn : vpns) {
1267 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1268 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1269 formatAndLog(LOG::warn,
1270 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1271 vpn.getId().getValue())));
1275 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1276 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1277 formatAndLog(LOG::warn,
1278 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1279 vpn.getId().getValue())));
1283 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1285 if (vpn.getL3vni() != null) {
1286 l3vni = vpn.getL3vni();
1289 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1290 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1291 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1292 formatAndLog(LOG::warn,
1293 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1294 + "is already configured",
1295 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1299 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1300 if (operationalVpn.isPresent()) {
1301 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1302 formatAndLog(LOG::error,
1303 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1304 + "is still available. Please retry creation of a new vpn with the same RD"
1305 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1306 vpn.getRouteDistinguisher().get(0))));
1310 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1311 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1312 routerIdsList = vpn.getRouterIds();
1313 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1314 routerId : routerIdsList) {
1315 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1316 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1317 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1318 + "{}", vpn.getId(), routerId.getRouterId())));
1322 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1323 if (vpnId != null) {
1324 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1325 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1326 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1327 vpnId.getValue())));
1333 if (vpn.getNetworkIds() != null) {
1334 int initialWarningCount = warningcount;
1335 for (Uuid nw : vpn.getNetworkIds()) {
1336 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1337 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1338 if (network == null) {
1339 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1340 formatAndLog(LOG::warn,
1341 "Creation of L3VPN failed for VPN {} due to network not found {}",
1342 vpn.getId().getValue(), nw.getValue())));
1344 } else if (vpnId != null) {
1345 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1346 formatAndLog(LOG::warn,
1347 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1348 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1349 vpnId.getValue())));
1353 if (warningcount != initialWarningCount) {
1357 List<Uuid> rtrIdsList = new ArrayList<>();
1358 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1359 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1360 rtrId : vpn.getRouterIds()) {
1361 rtrIdsList.add(rtrId.getRouterId());
1365 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1366 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1367 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1368 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1369 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1370 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1371 vpnInstanceType, l3vni);
1372 } catch (Exception ex) {
1373 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1374 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1379 // if at least one succeeds; result is success
1380 // if none succeeds; result is failure
1381 if (failurecount + warningcount == vpns.size()) {
1382 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1384 List<String> errorResponseList = new ArrayList<>();
1385 if (!errorList.isEmpty()) {
1386 for (RpcError rpcError : errorList) {
1387 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1388 + ", ErrorMessage: " + rpcError.getMessage());
1391 errorResponseList.add("Operation successful with no errors");
1393 opBuilder.setResponse(errorResponseList);
1394 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1400 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1403 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1405 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1406 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1407 Uuid inputVpnId = input.getId();
1408 List<VpnInstance> vpns = new ArrayList<>();
1409 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1412 if (inputVpnId == null) {
1414 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1416 Optional<VpnInstances> optionalVpns =
1417 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1419 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1420 for (VpnInstance vpn : requireNonNullElse(optionalVpns.get().getVpnInstance(),
1421 Collections.<VpnInstance>emptyList())) {
1422 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1423 // from getL3VPN output
1424 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1427 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1433 opBuilder.setL3vpnInstances(l3vpnList);
1434 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1438 String name = inputVpnId.getValue();
1439 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1440 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1441 // read VpnInstance Info
1442 Optional<VpnInstance> optionalVpn =
1443 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1445 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1447 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1448 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1449 vpns.add(optionalVpn.get());
1452 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1453 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1457 for (VpnInstance vpnInstance : vpns) {
1458 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1459 // create VpnMaps id
1460 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1461 List<String> rd = Collections.EMPTY_LIST;
1462 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1463 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1464 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1465 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1467 List<String> ertList = new ArrayList<>();
1468 List<String> irtList = new ArrayList<>();
1470 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1471 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1472 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1473 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1474 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1475 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1476 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1478 if (!vpnTargetList.isEmpty()) {
1479 for (VpnTarget vpnTarget : vpnTargetList) {
1480 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1481 ertList.add(vpnTarget.getVrfRTValue());
1483 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1484 irtList.add(vpnTarget.getVrfRTValue());
1486 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1487 ertList.add(vpnTarget.getVrfRTValue());
1488 irtList.add(vpnTarget.getVrfRTValue());
1494 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1496 if (vpnInstance.getL3vni() != null) {
1497 l3vpn.setL3vni(vpnInstance.getL3vni());
1499 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1500 .class, new VpnMapKey(vpnId)).build();
1501 Optional<VpnMap> optionalVpnMap =
1502 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1504 if (optionalVpnMap.isPresent()) {
1505 VpnMap vpnMap = optionalVpnMap.get();
1506 List<Uuid> rtrIds = new ArrayList<>();
1507 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1508 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1509 rtrIds.add(rtrId.getRouterId());
1512 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1513 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1514 .setName(vpnMap.getName());
1517 l3vpnList.add(l3vpn.build());
1520 opBuilder.setL3vpnInstances(l3vpnList);
1521 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1523 } catch (ReadFailedException ex) {
1524 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1525 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1531 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1534 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1536 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1537 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1538 List<RpcError> errorList = new ArrayList<>();
1540 int failurecount = 0;
1541 int warningcount = 0;
1542 List<Uuid> vpns = requireNonNullElse(input.getId(), Collections.emptyList());
1543 for (Uuid vpn : vpns) {
1545 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1546 InstanceIdentifier<VpnInstance> vpnIdentifier =
1547 InstanceIdentifier.builder(VpnInstances.class)
1548 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1549 Optional<VpnInstance> optionalVpn =
1550 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1552 if (optionalVpn.isPresent()) {
1555 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1556 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1559 } catch (ReadFailedException ex) {
1560 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1561 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1566 // if at least one succeeds; result is success
1567 // if none succeeds; result is failure
1568 if (failurecount + warningcount == vpns.size()) {
1569 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1571 List<String> errorResponseList = new ArrayList<>();
1572 if (!errorList.isEmpty()) {
1573 for (RpcError rpcError : errorList) {
1574 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1575 + ", ErrorMessage: " + rpcError.getMessage());
1578 errorResponseList.add("Operation successful with no errors");
1580 opBuilder.setResponse(errorResponseList);
1581 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1586 public void createVpnInstanceForSubnet(Uuid subnetId) {
1587 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1588 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1591 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1592 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1593 removeVpn(subnetId);
1596 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1597 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1598 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1599 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1601 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1602 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1605 if (vpnId != null) {
1606 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1607 if (vpnMap == null) {
1608 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1609 + " cannot add subnet {} to VPN", vpnId.getValue(),
1613 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1614 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1615 if (isVpnOfTypeL2(vpnInstance)) {
1616 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1617 NeutronEvpnUtils.Operation.ADD);
1620 if (internetVpnId != null) {
1621 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1622 if (vpnMap == null) {
1623 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1624 + "subnet {} to VPN", internetVpnId.getValue(),
1629 final Uuid internetId = internetVpnId;
1630 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1631 List<Uuid> portList = sn.getPortList();
1632 if (portList != null) {
1633 for (final Uuid portId : portList) {
1634 String vpnInfName = portId.getValue();
1635 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1636 Port port = neutronvpnUtils.getNeutronPort(portId);
1638 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1639 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1642 final Boolean isRouterInterface = port.getDeviceOwner()
1643 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1644 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1645 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1646 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1648 if (vpnIface == null) {
1649 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1650 Set<Uuid> listVpn = new HashSet<>();
1651 if (vpnId != null) {
1654 if (internetId != null) {
1655 listVpn.add(internetId);
1657 writeVpnInterfaceToDs(listVpn,
1658 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1659 if (sn.getRouterId() != null) {
1660 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1663 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1664 if (vpnId != null) {
1665 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1667 if (internetId != null) {
1668 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1677 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1678 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1679 "removeSubnetFromVpn: at least one VPN must be not null");
1680 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1681 vpnId, internetVpnId);
1682 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1684 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1687 VpnMap vpnMap = null;
1688 VpnInstance vpnInstance = null;
1689 if (vpnId != null) {
1690 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1691 if (vpnMap == null) {
1692 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1693 vpnId.getValue(), subnet.getValue());
1696 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1698 if (internetVpnId == null) {
1699 internetVpnId = sn.getInternetVpnId();
1701 if (internetVpnId != null) {
1702 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1703 if (vpnMap == null) {
1704 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1705 + " from Internet VPN",
1706 internetVpnId.getValue(), subnet.getValue());
1710 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1711 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1712 NeutronEvpnUtils.Operation.DELETE);
1714 boolean subnetVpnAssociation = false;
1715 if (vpnId != null && sn.getVpnId() != null
1716 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1717 subnetVpnAssociation = true;
1718 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1719 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1720 subnetVpnAssociation = true;
1722 if (subnetVpnAssociation == false) {
1723 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1724 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1727 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1728 List<Uuid> portList = sn.getPortList();
1729 final Uuid internetId = internetVpnId;
1730 if (portList != null) {
1731 for (final Uuid portId : portList) {
1732 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1733 final Port port = neutronvpnUtils.getNeutronPort(portId);
1734 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1735 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1736 CONFIGURATION, tx -> {
1738 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1741 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1742 + "port is absent in Neutron config DS", portId.getValue(),
1748 //update subnet-vpn association
1749 removeFromSubnetNode(subnet, null, null, vpnId, null);
1752 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1753 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1754 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1756 Uuid internalVpnId = sm.getVpnId();
1757 if (internalVpnId == null) {
1758 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1759 sm.getId().getValue());
1762 if (isBeingAssociated) {
1763 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1765 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1768 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1769 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1770 if (isBeingAssociated) {
1771 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1772 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1774 removeInternetVpnFromVpnInterface(vpn,
1775 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1780 // Check for ports on this subnet and update association of
1781 // corresponding vpn-interfaces to internet vpn
1782 List<Uuid> portList = sm.getPortList();
1783 if (portList != null) {
1784 for (Uuid port : portList) {
1785 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1786 port.getValue(), isBeingAssociated);
1787 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1788 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1790 if (isBeingAssociated) {
1791 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1792 true, false, tx, true);
1794 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1802 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1803 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1804 oldVpnId.getValue(), newVpnId.getValue());
1805 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1806 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1807 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1808 Uuid vpnExtUuid = netIsExternal ? null
1809 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1810 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1812 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1815 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1816 * associated with internet BGP-VPN.
1818 if (vpnExtUuid != null) {
1819 /* Update V6 Internet default route match with new VPN metadata.
1820 * isBeingAssociated = true means oldVpnId is same as routerId
1821 * isBeingAssociated = false means newVpnId is same as routerId
1823 if (isBeingAssociated) {
1824 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1826 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1829 //Update Router Interface first synchronously.
1830 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1831 ListenableFuture<Void> future =
1832 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1833 tx -> updateVpnInterface(newVpnId, oldVpnId,
1834 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1835 isBeingAssociated, true, tx, false));
1836 Futures.addCallback(future, new FutureCallback<Void>() {
1838 public void onSuccess(Void result) {
1839 // Check for ports on this subnet and update association of
1840 // corresponding vpn-interfaces to external vpn
1841 List<Uuid> portList = sn.getPortList();
1842 if (portList != null) {
1843 for (Uuid port : portList) {
1844 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1845 port.getValue(), isBeingAssociated);
1846 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1847 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1848 tx -> updateVpnInterface(newVpnId, oldVpnId,
1849 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1856 public void onFailure(Throwable throwable) {
1858 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1860 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1862 }, MoreExecutors.directExecutor());
1867 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1868 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1869 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1872 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1873 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1874 final ReentrantLock lock = lockForUuid(routerId);
1877 Optional<RouterInterfaces> optRouterInterfaces =
1878 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1879 routerInterfacesId);
1880 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1881 .setInterfaceId(interfaceName).build();
1882 if (optRouterInterfaces.isPresent()) {
1883 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1884 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1886 // TODO Shouldn't we be doing something with builder and interfaces?
1887 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1888 // List<Interfaces> interfaces = new ArrayList<>();
1889 // interfaces.add(routerInterface);
1891 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1892 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1894 } catch (ReadFailedException | TransactionCommitFailedException e) {
1895 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1901 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1902 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1903 final ReentrantLock lock = lockForUuid(routerId);
1906 Optional<RouterInterfaces> optRouterInterfaces =
1907 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1908 routerInterfacesId);
1909 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1910 .setInterfaceId(interfaceName).build();
1911 if (optRouterInterfaces.isPresent()) {
1912 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1913 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1914 if (interfaces != null && interfaces.remove(routerInterface)) {
1915 if (interfaces.isEmpty()) {
1916 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1917 routerInterfacesId);
1919 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1920 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1924 } catch (ReadFailedException | TransactionCommitFailedException e) {
1925 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1932 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1933 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1934 * route will be ignored.
1936 * @param vpnName the VPN identifier
1937 * @param interVpnLinkRoutes The list of static routes
1938 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1940 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1941 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1942 for (Routes route : interVpnLinkRoutes) {
1943 String nexthop = route.getNexthop().stringValue();
1944 String destination = route.getDestination().stringValue();
1945 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1946 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1947 AddStaticRouteInput rpcInput =
1948 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1949 .setVpnInstanceName(vpnName.getValue())
1951 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1952 RpcResult<AddStaticRouteOutput> rpcResult;
1954 rpcResult = labelOuputFtr.get();
1955 if (rpcResult.isSuccessful()) {
1956 LOG.debug("Label generated for destination {} is: {}",
1957 destination, rpcResult.getResult().getLabel());
1959 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1960 destination, nexthop, rpcResult.getErrors());
1962 } catch (InterruptedException | ExecutionException e) {
1963 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1964 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1967 // Any other case is a fault.
1968 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1969 route.getDestination().stringValue(), nexthop);
1976 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1977 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1979 * @param vpnName the VPN identifier
1980 * @param interVpnLinkRoutes The list of static routes
1981 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1983 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1984 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1985 for (Routes route : interVpnLinkRoutes) {
1986 String nexthop = route.getNexthop().stringValue();
1987 String destination = route.getDestination().stringValue();
1988 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1989 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1990 RemoveStaticRouteInput rpcInput =
1991 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1992 .setVpnInstanceName(vpnName.getValue())
1995 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1996 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1998 // Any other case is a fault.
1999 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2000 route.getDestination().stringValue(), nexthop);
2007 * Returns true if the specified nexthop is the other endpoint in an
2008 * InterVpnLink, regarding one of the VPN's point of view.
2010 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
2012 interVpnLink != null
2013 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2014 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2015 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2016 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2020 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2021 List<Adjacency> adjList = new ArrayList<>();
2022 Map<String, List<String>> adjMap = new HashMap<>();
2023 for (Routes route : routeList) {
2024 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2025 LOG.error("Incorrect input received for extra route. {}", route);
2027 String nextHop = route.getNexthop().stringValue();
2028 String destination = route.getDestination().stringValue();
2029 if (!nextHop.equals(fixedIp)) {
2030 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2033 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2035 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2036 if (!hops.contains(nextHop)) {
2042 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2043 final String destination = entry.getKey();
2044 final List<String> ipList = entry.getValue();
2045 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2046 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2047 .withKey(new AdjacencyKey(destination)).build();
2053 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2054 checkAlarmExtraRoutes(vpnId, routeList);
2056 for (Routes route : routeList) {
2057 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2058 LOG.error("Incorrect input received for extra route. {}", route);
2060 String nextHop = route.getNexthop().stringValue();
2061 String destination = route.getDestination().stringValue();
2062 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2064 if (infName != null) {
2065 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2066 destination, vpnId.getValue(), nextHop, infName);
2067 boolean isLockAcquired = false;
2069 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2070 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2071 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2072 .child(Adjacency.class, new AdjacencyKey(destination));
2073 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2074 LogicalDatastoreType.CONFIGURATION, path);
2075 if (existingAdjacency.isPresent()
2076 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2077 LOG.error("The route with destination {} nextHop {} is already present as"
2078 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2079 destination, nextHop, infName);
2082 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2083 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2084 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2085 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2086 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2088 } catch (TransactionCommitFailedException e) {
2089 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2090 destination, nextHop, e);
2091 } catch (ReadFailedException e) {
2092 LOG.error("Exception on reading data-store ", e);
2094 if (isLockAcquired) {
2095 interfaceLock.unlock(infName);
2099 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2100 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2107 * This method setup or down an alarm about extra route fault.
2108 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2109 * available RDs, then an alarm and an error is generated.<br>
2110 * <b>Be careful</b> the routeList could be changed.
2112 * @param vpnId the vpnId of vpn to control.
2113 * @param routeList the list of router to check, it could be modified.
2115 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2116 if (!neutronvpnAlarm.isAlarmEnabled()) {
2117 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2120 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2121 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2122 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2126 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2127 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2128 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2132 for (Routes route : routeList) {
2133 // count the number of nexthops for each same route.getDestingation().getValue()
2134 String destination = route.getDestination().stringValue();
2135 String nextHop = route.getNexthop().stringValue();
2136 List<String> nextHopList = new ArrayList<>();
2137 nextHopList.add(nextHop);
2139 for (Routes routeTmp : routeList) {
2140 String routeDest = routeTmp.getDestination().stringValue();
2141 if (!destination.equals(routeDest)) {
2144 String routeNextH = routeTmp.getNexthop().stringValue();
2145 if (nextHop.equals(routeNextH)) {
2149 nextHopList.add(routeTmp.getNexthop().stringValue());
2151 final List<String> rdList = new ArrayList<>();
2152 if (vpnInstance.getIpv4Family() != null
2153 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2154 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2160 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2161 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2162 if (rd != null && !rdList.contains(rd)) {
2167 // 1. VPN Instance Name
2168 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2171 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2172 Uuid routerUuid = routerUuidList.get(0);
2173 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2174 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2176 // 3. List of RDs associated with the VPN
2177 detailsAlarm.append(" List of RDs associated with the VPN: ");
2178 for (String s : rdList) {
2179 detailsAlarm.append(s);
2180 detailsAlarm.append(", ");
2183 // 4. Prefix in question
2184 detailsAlarm.append(" for prefix: ");
2185 detailsAlarm.append(route.getDestination().stringValue());
2187 // 5. List of NHs for the prefix
2188 detailsAlarm.append(" for nextHops: ");
2189 for (String s : nextHopList) {
2190 detailsAlarm.append(s);
2191 detailsAlarm.append(", ");
2194 if (rdList.size() < nbNextHops) {
2195 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2197 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2202 // TODO Clean up the exception handling
2203 @SuppressWarnings("checkstyle:IllegalCatch")
2204 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2205 for (Routes route : routeList) {
2206 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2207 boolean isLockAcquired = false;
2208 String nextHop = route.getNexthop().stringValue();
2209 String destination = route.getDestination().stringValue();
2210 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2212 if (infName == null) {
2213 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2214 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2215 // Proceed to remove the next extra-route
2218 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2219 destination, vpnId.getValue(), nextHop, infName);
2221 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2222 InstanceIdentifier.builder(VpnInterfaces.class)
2223 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2224 .augmentation(Adjacencies.class)
2225 .child(Adjacency.class, new AdjacencyKey(destination))
2229 // Looking for existing prefix in MDSAL database
2230 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2231 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2232 boolean updateNextHops = false;
2233 List<String> nextHopList = new ArrayList<>();
2234 if (adjacency.isPresent()) {
2235 List<String> nhListRead = adjacency.get().getNextHopIpList();
2236 if (nhListRead.size() > 1) { // ECMP case
2237 for (String nextHopRead : nhListRead) {
2238 if (nextHopRead.equals(nextHop)) {
2239 updateNextHops = true;
2241 nextHopList.add(nextHopRead);
2247 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2248 if (updateNextHops) {
2249 // An update must be done, not including the current next hop
2250 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2251 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2252 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2253 .setNextHopIpList(nextHopList)
2254 .withKey(new AdjacencyKey(destination))
2256 Adjacencies erAdjs =
2257 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2258 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2259 .addAugmentation(Adjacencies.class, erAdjs).build();
2260 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2261 vpnIfIdentifier, vpnIf);
2263 // Remove the whole route
2264 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2265 adjacencyIdentifier);
2266 LOG.trace("extra route {} deleted successfully", route);
2268 } catch (TransactionCommitFailedException | ReadFailedException e) {
2269 LOG.error("exception in deleting extra route with destination {} for interface {}",
2270 destination, infName, e);
2272 if (isLockAcquired) {
2273 interfaceLock.unlock(infName);
2277 LOG.error("Incorrect input received for extra route: {}", route);
2282 public void removeVpn(Uuid vpnId) {
2284 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2285 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2286 List<Uuid> routerUuidList = new ArrayList<>();
2287 // dissociate router
2288 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2289 for (RouterIds router : routerIdsList) {
2290 Uuid routerId = router.getRouterId();
2291 routerUuidList.add(routerId);
2292 dissociateRouterFromVpn(vpnId, routerId);
2295 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2296 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2298 // remove entire vpnMaps node
2299 deleteVpnMapsNode(vpnId);
2301 // remove vpn-instance
2302 deleteVpnInstance(vpnId);
2303 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2306 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2307 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2310 // TODO Clean up the exception handling
2311 @SuppressWarnings("checkstyle:IllegalCatch")
2312 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2313 updateVpnMaps(vpnId, null, routerId, null, null);
2314 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2315 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2316 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2317 for (Subnetmap sn : subMapList) {
2318 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2319 if (!ipVersion.isIpVersionChosen(ipVers)) {
2320 ipVersion = ipVersion.addVersion(ipVers);
2323 if (ipVersion != IpVersionChoice.UNDEFINED) {
2324 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2326 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2328 for (Subnetmap sn : subMapList) {
2329 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2333 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2334 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2335 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2336 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2337 for (Uuid subnet : routerSubnets) {
2338 IpVersionChoice version = NeutronvpnUtils
2339 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2340 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2341 addSubnetToVpn(vpnId, subnet, null);
2343 addSubnetToVpn(vpnId, subnet, internetVpnId);
2348 // TODO Clean up the exception handling
2349 @SuppressWarnings("checkstyle:IllegalCatch")
2350 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2352 clearFromVpnMaps(vpnId, routerId, null);
2353 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2354 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2355 for (Subnetmap sn : subMapList) {
2356 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2357 if (ipVersion.isIpVersionChosen(ipVers)) {
2358 ipVersion = ipVersion.addVersion(ipVers);
2360 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2361 routerId.getValue());
2362 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2364 if (ipVersion != IpVersionChoice.UNDEFINED) {
2365 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2367 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2373 * Parses and associates networks list with given VPN.
2375 * @param vpnId Uuid of given VPN.
2376 * @param networkList List list of network Ids (Uuid), which will be associated.
2377 * @return list of formatted strings with detailed error messages.
2380 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2381 List<String> failedNwList = new ArrayList<>();
2382 HashSet<Uuid> passedNwList = new HashSet<>();
2383 boolean isExternalNetwork = false;
2384 if (networkList.isEmpty()) {
2385 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2386 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2388 return failedNwList;
2390 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2391 if (vpnInstance == null) {
2392 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2393 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2394 + "in ConfigDS", vpnId.getValue()));
2395 return failedNwList;
2398 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2399 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2401 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2402 + "associated with", vpnId.getValue()));
2403 return failedNwList;
2405 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2406 for (Uuid nw : networkList) {
2407 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2408 if (network == null) {
2409 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2410 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2414 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2415 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2416 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2417 nw.getValue(), vpnId.getValue());
2418 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2419 nw.getValue(), vpnId.getValue()));
2422 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2423 if (networkVpnId != null) {
2424 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2425 nw.getValue(), networkVpnId.getValue());
2426 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2427 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2430 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2431 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2432 nw.getValue(), vpnId.getValue());
2433 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2434 nw.getValue(), vpnId.getValue()));
2437 if (NeutronvpnUtils.getIsExternal(network)) {
2438 isExternalNetwork = true;
2440 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2441 if (subnetmapList == null || subnetmapList.isEmpty()) {
2442 passedNwList.add(nw);
2445 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2448 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2449 for (Subnetmap subnetmap : subnetmapList) {
2450 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2451 if (!ipVersion.isIpVersionChosen(ipVers)) {
2452 ipVersion = ipVersion.addVersion(ipVers);
2455 if (ipVersion != IpVersionChoice.UNDEFINED) {
2456 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2457 + " for VPN {} ", ipVersion, vpnId);
2458 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2460 for (Subnetmap subnetmap : subnetmapList) {
2461 Uuid subnetId = subnetmap.getId();
2462 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2463 if (subnetVpnId != null) {
2464 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2465 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2466 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2467 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2470 if (!NeutronvpnUtils.getIsExternal(network)) {
2471 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2473 addSubnetToVpn(vpnId, subnetId, null);
2474 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2476 passedNwList.add(nw);
2479 passedNwList.add(nw);
2481 } catch (ReadFailedException e) {
2482 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2484 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2487 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2488 if (!isExternalNetwork) {
2489 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2491 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2492 return failedNwList;
2495 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2496 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2499 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2500 if (vpnOpDataEntry == null) {
2501 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2504 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2505 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2506 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2508 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2509 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2510 updateVpnMaps(vpnId, null, null, null, extNwList);
2511 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2512 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2513 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2515 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2518 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2519 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2522 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2523 updateVpnInternetForSubnet(sm, vpnId, true);
2525 if (!ipVersion.isIpVersionChosen(ipVers)) {
2526 ipVersion = ipVersion.addVersion(ipVers);
2529 if (ipVersion != IpVersionChoice.UNDEFINED) {
2530 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2531 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2532 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2538 * Parses and disassociates networks list from given VPN.
2540 * @param vpnId Uuid of given VPN.
2541 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2542 * @return list of formatted strings with detailed error messages.
2545 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2546 List<String> failedNwList = new ArrayList<>();
2547 HashSet<Uuid> passedNwList = new HashSet<>();
2548 if (networkList.isEmpty()) {
2549 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2550 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2552 return failedNwList;
2554 for (Uuid nw : networkList) {
2555 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2556 if (networkSubnets == null) {
2557 passedNwList.add(nw);
2560 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2561 if (network == null) {
2562 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2563 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2567 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2568 if (networkVpnId == null) {
2569 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2570 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2574 if (!vpnId.equals(networkVpnId)) {
2575 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2576 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2577 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2578 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2582 if (NeutronvpnUtils.getIsExternal(network)) {
2583 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2584 passedNwList.add(nw);
2586 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2587 nw.getValue(), vpnId.getValue());
2588 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2593 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2594 for (Uuid subnet : networkSubnets) {
2595 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2596 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2597 if (!ipVersion.isIpVersionChosen(ipVers)) {
2598 ipVersion = ipVersion.addVersion(ipVers);
2600 if (!NeutronvpnUtils.getIsExternal(network)) {
2601 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2603 removeSubnetFromVpn(vpnId, subnet, null);
2604 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2605 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2607 passedNwList.add(nw);
2610 if (ipVersion != IpVersionChoice.UNDEFINED) {
2611 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2612 + " for VPN {}", ipVersion, vpnId);
2613 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2616 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2617 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2618 passedNwList.toString(), vpnId.getValue());
2619 return failedNwList;
2622 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2623 if (!removeExternalNetworkFromVpn(extNet)) {
2626 // check, if there is another Provider Networks associated with given VPN
2627 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2628 if (vpnNets != null) {
2629 //Remove currently disassociated network from the list
2630 vpnNets.remove(extNet.getUuid());
2631 for (Uuid netId : vpnNets) {
2632 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2633 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2634 + "{}", vpnId.getValue(), netId.getValue());
2639 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2640 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2641 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2642 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2643 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2644 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2645 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2647 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2650 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2651 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2654 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2655 updateVpnInternetForSubnet(sm, vpnId, false);
2657 if (!ipVersion.isIpVersionChosen(ipVers)) {
2658 ipVersion = ipVersion.addVersion(ipVers);
2661 if (ipVersion != IpVersionChoice.UNDEFINED) {
2662 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2663 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2665 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2671 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2674 // TODO Clean up the exception handling
2675 @SuppressWarnings("checkstyle:IllegalCatch")
2676 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2678 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2679 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2680 StringBuilder returnMsg = new StringBuilder();
2681 Uuid vpnId = input.getVpnId();
2684 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2685 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2686 input.getNetworkId().toString());
2687 List<Uuid> netIds = input.getNetworkId();
2688 if (netIds != null && !netIds.isEmpty()) {
2689 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2690 if (!failed.isEmpty()) {
2691 returnMsg.append(failed);
2695 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2697 if (returnMsg.length() != 0) {
2698 opBuilder.setResponse(
2699 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2700 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2701 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2703 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2705 } catch (Exception ex) {
2706 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2707 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2708 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2710 LOG.debug("associateNetworks returns..");
2715 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2718 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2720 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2721 LOG.debug("associateRouter {}", input);
2722 StringBuilder returnMsg = new StringBuilder();
2723 Uuid vpnId = input.getVpnId();
2724 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2725 routerIds = input.getRouterIds();
2726 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2727 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2728 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2729 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2730 .RouterIds routerId : routerIds) {
2731 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2732 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2733 if (vpnMap != null) {
2735 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2736 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2737 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2738 .append(routerId.getRouterId());
2739 } else if (extVpnId != null) {
2740 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2741 + "another VPN ").append(extVpnId.getValue());
2743 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2744 routerId.getRouterId());
2745 associateRouterToVpn(vpnId, routerId.getRouterId());
2748 returnMsg.append("router not found : ").append(routerId.getRouterId());
2751 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2753 if (returnMsg.length() != 0) {
2754 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2755 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2756 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2758 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2761 LOG.debug("associateRouter returns..");
2766 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2769 // TODO Clean up the exception handling
2770 @SuppressWarnings("checkstyle:IllegalCatch")
2771 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2772 GetFixedIPsForNeutronPortInput input) {
2773 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2774 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2775 Uuid portId = input.getPortId();
2776 StringBuilder returnMsg = new StringBuilder();
2778 List<String> fixedIPList = new ArrayList<>();
2779 Port port = neutronvpnUtils.getNeutronPort(portId);
2781 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
2782 fixedIPList.add(ip.getIpAddress().stringValue());
2785 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2787 if (returnMsg.length() != 0) {
2788 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2790 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2791 returnMsg)).build());
2793 opBuilder.setFixedIPs(fixedIPList);
2794 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2796 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2798 } catch (Exception ex) {
2799 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2800 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2801 portId.getValue(), ex.getMessage(), ex)).build());
2807 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2810 // TODO Clean up the exception handling
2811 @SuppressWarnings("checkstyle:IllegalCatch")
2812 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2814 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2815 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2817 LOG.debug("dissociateNetworks {}", input);
2818 StringBuilder returnMsg = new StringBuilder();
2819 Uuid vpnId = input.getVpnId();
2822 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2823 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2824 input.getNetworkId().toString());
2825 List<Uuid> netIds = input.getNetworkId();
2826 if (netIds != null && !netIds.isEmpty()) {
2827 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2828 if (!failed.isEmpty()) {
2829 returnMsg.append(failed);
2833 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2835 if (returnMsg.length() != 0) {
2836 opBuilder.setResponse(
2837 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2838 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2840 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2842 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2844 } catch (Exception ex) {
2845 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2846 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2847 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2849 LOG.debug("dissociateNetworks returns..");
2854 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2857 // TODO Clean up the exception handling
2858 @SuppressWarnings("checkstyle:IllegalCatch")
2859 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2861 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2863 LOG.debug("dissociateRouter {}", input);
2864 StringBuilder returnMsg = new StringBuilder();
2865 Uuid vpnId = input.getVpnId();
2866 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2867 .RouterIds> routerIdList = input.getRouterIds();
2868 String routerIdsString = "";
2869 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2870 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2871 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2872 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2873 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2874 .RouterIds routerId : routerIdList) {
2876 if (routerId != null) {
2877 routerIdsString += routerId.getRouterId() + ", ";
2878 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2880 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2881 if (routerVpnId == null) {
2882 returnMsg.append("input router ").append(routerId.getRouterId())
2883 .append(" not associated to any vpn yet");
2884 } else if (vpnId.equals(routerVpnId)) {
2885 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2887 returnMsg.append("input router ").append(routerId.getRouterId())
2888 .append(" associated to vpn ")
2889 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2892 returnMsg.append("router not found : ").append(routerId.getRouterId());
2895 if (returnMsg.length() != 0) {
2896 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2897 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2898 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2899 returnMsg)).build());
2901 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2903 } catch (Exception ex) {
2904 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2905 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2906 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2910 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2913 LOG.debug("dissociateRouter returns..");
2917 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2918 // check if the router is associated to some VPN
2919 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2920 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2921 if (vpnId != null) {
2922 // remove existing external vpn interfaces
2923 for (Uuid subnetId : routerSubnetIds) {
2924 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2926 clearFromVpnMaps(vpnId, routerId, null);
2928 // remove existing internal vpn interfaces
2929 for (Uuid subnetId : routerSubnetIds) {
2930 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2933 // delete entire vpnMaps node for internal VPN
2934 deleteVpnMapsNode(routerId);
2936 // delete vpn-instance for internal VPN
2937 deleteVpnInstance(routerId);
2940 protected Subnet getNeutronSubnet(Uuid subnetId) {
2941 return neutronvpnUtils.getNeutronSubnet(subnetId);
2945 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2946 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2948 return sn.getGatewayIp();
2954 protected Network getNeutronNetwork(Uuid networkId) {
2955 return neutronvpnUtils.getNeutronNetwork(networkId);
2958 protected Port getNeutronPort(String name) {
2959 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2962 protected Port getNeutronPort(Uuid portId) {
2963 return neutronvpnUtils.getNeutronPort(portId);
2966 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2967 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2970 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2971 return neutronvpnUtils.getNetworksForVpn(vpnId);
2975 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2977 * @return a List of String to be printed on screen
2978 * @throws ReadFailedException if there was a problem reading from the data store
2980 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2981 List<String> result = new ArrayList<>();
2982 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2984 result.add("-------------------------------------------------------------------------------------------");
2985 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2987 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2988 if (ports.isPresent() && ports.get().getPort() != null) {
2989 for (Port port : requireNonNullElse(ports.get().getPort(), Collections.<Port>emptyList())) {
2990 List<FixedIps> fixedIPs = port.getFixedIps();
2991 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2992 List<String> ipList = new ArrayList<>();
2993 for (FixedIps fixedIp : fixedIPs) {
2994 IpAddress ipAddress = fixedIp.getIpAddress();
2995 if (ipAddress.getIpv4Address() != null) {
2996 ipList.add(ipAddress.getIpv4Address().getValue());
2998 ipList.add(ipAddress.getIpv6Address().getValue());
3001 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3002 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3003 ipList.toString()));
3005 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3006 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3015 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3017 * @param vpnuuid Uuid of the VPN whose config must be shown
3018 * @return formatted output list
3019 * @throws InterruptedException if there was a thread related problem getting the data to display
3020 * @throws ExecutionException if there was any other problem getting the data to display
3022 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3023 List<String> result = new ArrayList<>();
3024 if (vpnuuid == null) {
3026 result.add("Displaying VPN config for all VPNs");
3027 result.add("To display VPN config for a particular VPN, use the following syntax");
3028 result.add(getshowVpnConfigCLIHelp());
3030 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3031 if (rpcResult.isSuccessful()) {
3033 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3035 result.add(String.format(" %-80s ", "Import-RTs"));
3037 result.add(String.format(" %-80s ", "Export-RTs"));
3039 result.add(String.format(" %-76s ", "Subnet IDs"));
3041 result.add("------------------------------------------------------------------------------------");
3043 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3044 requireNonNullElse(rpcResult.getResult().getL3vpnInstances(),
3045 Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
3046 .VpnInstance>emptyList())) {
3047 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3049 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3050 vpn.getRouteDistinguisher()));
3052 result.add(String.format(" %-80s ", vpn.getImportRT()));
3054 result.add(String.format(" %-80s ", vpn.getExportRT()));
3057 Uuid vpnid = vpn.getId();
3058 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3059 if (!subnetList.isEmpty()) {
3060 for (Uuid subnetuuid : subnetList) {
3061 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3064 result.add(String.format(" %-76s ", "\" \""));
3067 result.add("----------------------------------------");
3071 String errortag = rpcResult.getErrors().iterator().next().getTag();
3072 if (Objects.equals(errortag, "")) {
3074 result.add("No VPN has been configured yet");
3075 } else if (Objects.equals(errortag, "invalid-value")) {
3077 result.add("VPN " + vpnuuid.getValue() + " is not present");
3079 result.add("error getting VPN info : " + rpcResult.getErrors());
3080 result.add(getshowVpnConfigCLIHelp());
3086 protected void createExternalVpnInterfaces(Uuid extNetId) {
3087 if (extNetId == null) {
3088 LOG.error("createExternalVpnInterfaces: external network is null");
3092 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3093 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3094 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3098 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3099 for (String elanInterface : extElanInterfaces) {
3100 createExternalVpnInterface(extNetId, elanInterface, tx);
3102 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3105 // TODO Clean up the exception handling
3106 @SuppressWarnings("checkstyle:IllegalCatch")
3107 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3108 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3109 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3110 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3113 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3114 for (String elanInterface : extElanInterfaces) {
3115 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3116 .buildVpnInterfaceIdentifier(elanInterface);
3117 LOG.info("Removing vpn interface {}", elanInterface);
3118 tx.delete(vpnIfIdentifier);
3120 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3123 private void createExternalVpnInterface(Uuid vpnId, String infName,
3124 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3125 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3126 false /* not a router iface */, wrtConfigTxn);
3129 // TODO Clean up the exception handling
3130 @SuppressWarnings("checkstyle:IllegalCatch")
3131 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName,
3132 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3133 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3134 if (vpnIdList.isEmpty() || infName == null) {
3135 LOG.error("vpnid is empty or interface({}) is null", infName);
3138 if (wrtConfigTxn == null) {
3139 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3140 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3141 "Error writing VPN interface");
3144 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3145 for (Uuid vpnId: vpnIdList) {
3146 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3147 AssociatedSubnetType.V4AndV6Subnets);
3148 vpnIdListStruct.add(vpnInstance);
3151 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3152 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3154 .setVpnInstanceNames(vpnIdListStruct)
3155 .setRouterInterface(isRouterInterface);
3156 LOG.info("Network Id is {}", networkUuid);
3157 if (networkUuid != null) {
3158 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3159 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3160 NetworkAttributes.NetworkType networkType = providerType != null
3161 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3162 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3163 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3164 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3167 if (adjacencies != null) {
3168 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3170 VpnInterface vpnIf = vpnb.build();
3172 LOG.info("Creating vpn interface {}", vpnIf);
3173 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3174 } catch (Exception ex) {
3175 LOG.error("Creation of vpninterface {} failed", infName, ex);
3179 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3180 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3181 if (vpnId == null || infName == null) {
3182 LOG.error("vpn id or interface is null");
3185 if (wrtConfigTxn == null) {
3186 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3187 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3188 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3189 }), LOG, "Error updating VPN interface with adjacencies");
3193 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3194 boolean isLockAcquired = false;
3196 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3197 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3198 .syncReadOptional(dataBroker, LogicalDatastoreType
3199 .CONFIGURATION, vpnIfIdentifier);
3200 if (optionalVpnInterface.isPresent()) {
3201 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3202 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3204 if (adjacencies == null) {
3205 if (isLockAcquired) {
3206 interfaceLock.unlock(infName);
3210 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3211 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3212 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3213 optionalVpnInterface.get().getVpnInstanceNames());
3214 if (listVpnInstances.isEmpty() || !VpnHelper
3215 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3216 VpnInstanceNames vpnInstance = VpnHelper
3217 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3218 listVpnInstances.add(vpnInstance);
3219 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3222 VpnInstanceNames vpnInstance = VpnHelper
3223 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3224 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3225 listVpnInstances.add(vpnInstance);
3226 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3228 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3229 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3231 } catch (IllegalStateException | ReadFailedException ex) {
3232 LOG.error("Update of vpninterface {} failed", infName, ex);
3234 if (isLockAcquired) {
3235 interfaceLock.unlock(infName);
3240 private String getshowVpnConfigCLIHelp() {
3241 StringBuilder help = new StringBuilder("Usage:");
3242 help.append("display vpn-config [-vid/--vpnid <id>]");
3243 return help.toString();
3246 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3247 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3251 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3252 return neutronEvpnManager.createEVPN(input);
3256 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3257 return neutronEvpnManager.getEVPN(input);
3261 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3262 return neutronEvpnManager.deleteEVPN(input);
3265 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3266 Uuid extNetId = extNet.getUuid();
3267 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3268 .child(Networks.class, new NetworksKey(extNetId)).build();
3271 Optional<Networks> optionalExtNets =
3272 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3274 if (!optionalExtNets.isPresent()) {
3275 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3276 extNetId.getValue());
3279 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3280 builder.setVpnid(vpnId);
3281 Networks networks = builder.build();
3282 // Add Networks object to the ExternalNetworks list
3283 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3284 extNetId.getValue());
3285 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3288 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3289 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3290 extNetId.getValue(), ex);
3295 private boolean removeExternalNetworkFromVpn(Network extNet) {
3296 Uuid extNetId = extNet.getUuid();
3297 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3298 .child(Networks.class, new NetworksKey(extNetId)).build();
3300 Optional<Networks> optionalNets =
3301 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3303 NetworksBuilder builder = null;
3304 if (optionalNets.isPresent()) {
3305 builder = new NetworksBuilder(optionalNets.get());
3307 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3308 extNetId.getValue());
3311 builder.setVpnid(null);
3312 Networks networks = builder.build();
3313 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3314 extNetId.getValue());
3315 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3317 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3318 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3319 extNetId.getValue(), ex);
3324 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3325 Optional<String> existingVpnName = Optional.of(primaryRd);
3326 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3328 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3329 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3330 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3331 } catch (ReadFailedException e) {
3332 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3334 /*Read failed. We don't know if a VPN exists or not.
3335 * Return primaryRd to halt caller execution, to be safe.*/
3336 return existingVpnName;
3338 if (vpnInstanceOpDataOptional.isPresent()) {
3339 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3341 existingVpnName = Optional.absent();
3343 return existingVpnName;
3346 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3347 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3350 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3351 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3354 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3355 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3358 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3359 String message = tuple.getMessage();
3360 logger.accept(message);
3364 protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3365 @Nonnull Subnetmap subnetMap) {
3366 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3367 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3368 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3369 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3370 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3371 subnetMap.getId().getValue(), internetVpnId.getValue());
3375 protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3376 @Nonnull Subnetmap subnetMap) {
3377 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3378 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3381 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3382 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3383 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3384 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3385 internetVpnId.getValue(), routerId.getValue());
3386 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3391 private static ReentrantLock lockForUuid(Uuid uuid) {
3392 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3393 return JvmGlobalLocks.getLockForString(uuid.getValue());