2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.JdkFutureAdapters;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.ExecutionException;
36 import java.util.concurrent.Future;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.locks.ReentrantLock;
39 import java.util.function.Consumer;
40 import javax.annotation.PreDestroy;
41 import javax.inject.Inject;
42 import javax.inject.Singleton;
43 import org.eclipse.jdt.annotation.NonNull;
44 import org.eclipse.jdt.annotation.Nullable;
45 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
46 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
50 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
51 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
52 import org.opendaylight.genius.infra.Datastore.Configuration;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
55 import org.opendaylight.genius.infra.TypedWriteTransaction;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.genius.utils.JvmGlobalLocks;
58 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
59 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
60 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
61 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
62 import org.opendaylight.netvirt.elanmanager.api.IElanService;
63 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
64 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
65 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
66 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
67 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
68 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
69 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
86 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
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 NetworkAttributes.@Nullable 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 : port.nonnullFixedIps()) {
828 String ipValue = ip.getIpAddress().stringValue();
829 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
830 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
831 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
832 snTemp.getSubnetIp(), false)) {
835 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
837 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
838 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
839 //Create Neutron port adjacency if VPN presence is existing for subnet
840 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
841 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
842 .setSubnetId(ip.getSubnetId()).build();
843 if (!adjList.contains(vmAdj)) {
847 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
848 if (snTemp != null && snTemp.getInternetVpnId() != null) {
849 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
850 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
852 if (routerId != null) {
853 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
854 if (rtr != null && rtr.getRoutes() != null) {
855 List<Routes> routeList = rtr.getRoutes();
856 // create extraroute Adjacence for each ipValue,
857 // because router can have IPv4 and IPv6 subnet ports, or can have
858 // more that one IPv4 subnet port or more than one IPv6 subnet port
859 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
860 if (!erAdjList.isEmpty()) {
861 adjList.addAll(erAdjList);
866 return new AdjacenciesBuilder().setAdjacency(adjList).build();
869 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
870 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
871 boolean isRouterInterface = false;
872 if (port.getDeviceOwner() != null) {
873 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
875 String infName = port.getUuid().getValue();
876 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
877 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
878 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, vpnIface);
879 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
880 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
883 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
884 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
885 String infName = port.getUuid().getValue();
886 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
887 Optional<VpnInterface> optionalVpnInterface = null;
888 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
889 vpnId, internetVpnId, infName);
891 optionalVpnInterface = SingleTransactionDataBroker
892 .syncReadOptional(dataBroker, LogicalDatastoreType
893 .CONFIGURATION, vpnIfIdentifier);
894 } catch (ReadFailedException e) {
895 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
898 if (!optionalVpnInterface.isPresent()) {
901 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
902 sn != null ? sn.getSubnetIp() : "null");
903 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
904 List<Adjacency> updatedAdjsList = new ArrayList<>();
905 boolean isIpFromAnotherSubnet = false;
906 for (Adjacency adj : vpnAdjsList) {
907 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
908 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
909 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
910 isIpFromAnotherSubnet = true;
912 updatedAdjsList.add(adj);
915 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
916 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
919 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
920 String.valueOf(adjString), wrtConfigTxn);
922 if (internetVpnId != null) {
923 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
924 String.valueOf(adjString), wrtConfigTxn);
927 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
928 && sn.getRouterId() != null) {
929 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
930 if (rtr != null && rtr.getRoutes() != null) {
931 List<Routes> extraRoutesToRemove = new ArrayList<>();
932 for (Routes rt: rtr.getRoutes()) {
933 if (rt.getNexthop().toString().equals(adjString)) {
934 extraRoutesToRemove.add(rt);
938 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
939 extraRoutesToRemove, vpnId);
940 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
942 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
947 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
949 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
951 if (!isIpFromAnotherSubnet) {
952 // no more subnetworks for neutron port
953 if (sn != null && sn.getRouterId() != null) {
954 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
956 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
962 // TODO Clean up the exception handling
963 @SuppressWarnings("checkstyle:IllegalCatch")
964 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
965 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
966 if (wrtConfigTxn == null) {
967 ListenableFutures.addErrorLogging(
968 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
969 tx -> deleteVpnInterface(infName, vpnId, tx)),
970 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
974 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
975 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
976 Optional<VpnInterface> optionalVpnInterface;
978 optionalVpnInterface =
979 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
981 } catch (ReadFailedException ex) {
982 LOG.error("Error during deletion of vpninterface {}", infName, ex);
985 if (!optionalVpnInterface.isPresent()) {
986 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
990 VpnInterface vpnInterface = optionalVpnInterface.get();
991 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
993 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
994 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
995 if (!vpnList.isEmpty()) {
996 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
997 + "List not empty", infName);
1000 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1001 .setVpnInstanceNames(vpnList);
1002 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1006 LOG.debug("Deleting vpn interface {}", infName);
1007 wrtConfigTxn.delete(vpnIfIdentifier);
1010 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1011 TypedWriteTransaction<Configuration> writeConfigTxn,
1013 if (vpnId == null || port == null) {
1016 String infName = port.getUuid().getValue();
1017 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1019 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1020 .syncReadOptional(dataBroker, LogicalDatastoreType
1021 .CONFIGURATION, vpnIfIdentifier);
1022 if (optionalVpnInterface.isPresent()) {
1023 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1025 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1026 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1028 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1029 .setVpnInstanceNames(listVpn);
1030 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1031 LOG.debug("Updating vpn interface {}", infName);
1032 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1033 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1034 while (adjacencyIter.hasNext()) {
1035 Adjacency adjacency = adjacencyIter.next();
1036 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1039 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1040 InstanceIdentifier<LearntVpnVipToPort> id =
1041 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1042 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1043 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1044 LogicalDatastoreType.OPERATIONAL, id);
1045 if (optionalVpnVipToPort.isPresent()) {
1046 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1048 if (listVpn == null || listVpn.isEmpty()) {
1049 adjacencyIter.remove();
1051 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1052 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1053 mipToQuery, infName, vpnId.getValue());
1056 for (FixedIps ip : port.nonnullFixedIps()) {
1057 String ipValue = ip.getIpAddress().stringValue();
1059 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1062 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1063 ipValue, writeConfigTxn);
1065 if (listVpn == null || listVpn.isEmpty()) {
1066 if (sm != null && sm.getRouterId() != null) {
1067 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1069 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1071 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1074 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1076 } catch (ReadFailedException ex) {
1077 LOG.error("Update of vpninterface {} failed", infName, ex);
1081 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1083 TypedWriteTransaction<Configuration> writeConfigTxn,
1084 boolean isInternetVpn) {
1085 if (vpnId == null || port == null) {
1088 boolean isLockAcquired = false;
1089 String infName = port.getUuid().getValue();
1090 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1093 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1094 Optional<VpnInterface> optionalVpnInterface =
1095 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1097 if (optionalVpnInterface.isPresent()) {
1098 VpnInstanceNames vpnInstance = VpnHelper
1099 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1100 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1101 .get().getVpnInstanceNames());
1102 if (oldVpnId != null
1103 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1104 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1106 if (vpnId.getValue() != null
1107 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1108 listVpn.add(vpnInstance);
1110 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1111 .setVpnInstanceNames(listVpn);
1112 LOG.debug("Updating vpn interface {}", infName);
1113 if (!isBeingAssociated) {
1114 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1115 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1116 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1117 while (adjacencyIter.hasNext()) {
1118 Adjacency adjacency = adjacencyIter.next();
1119 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1120 InstanceIdentifier<LearntVpnVipToPort> id =
1121 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1122 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1123 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1124 LogicalDatastoreType.OPERATIONAL, id);
1125 if (optionalVpnVipToPort.isPresent()
1126 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
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 LearntVpnVipToPort",
1133 mipToQuery, infName, vpnId.getValue());
1135 InstanceIdentifier<VpnPortipToPort> build =
1136 neutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1137 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1138 LogicalDatastoreType.OPERATIONAL, build);
1139 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1140 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1141 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1142 mipToQuery, infName, vpnId.getValue());
1145 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1146 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1148 for (FixedIps ip : port.nonnullFixedIps()) {
1149 String ipValue = ip.getIpAddress().stringValue();
1150 if (oldVpnId != null) {
1151 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1152 ipValue, writeConfigTxn);
1154 if ((NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6)
1155 && (isInternetVpn == true)) {
1159 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1160 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1162 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1164 LOG.error("VPN Interface {} not found", infName);
1166 } catch (ReadFailedException ex) {
1167 LOG.error("Updation of vpninterface {} failed", infName, ex);
1169 if (isLockAcquired) {
1170 interfaceLock.unlock(infName);
1175 public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List<String> rd,
1176 @Nullable List<String> irt, @Nullable List<String> ert, @Nullable Uuid router,
1177 @Nullable List<Uuid> networks) {
1179 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1181 // Update VPN Instance node
1182 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1184 // Update local vpn-subnet DS
1185 updateVpnMaps(vpn, name, router, tenant, networks);
1187 if (router != null) {
1188 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1189 if (existingVpn != null) {
1190 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1191 // if before reboot, router was already associated to VPN, should not proceed associating router to
1192 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1193 // preserved upon reboot.
1194 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1195 // RouterInterfacesMap via #createVPNInterface call.
1196 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1197 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1200 associateRouterToInternalVpn(vpn, router);
1205 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1206 * specified Neutron Networks and Routers.
1208 * @param vpnId Uuid of the VPN tp be created
1209 * @param name Representative name of the new VPN
1210 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1211 * @param rdList Route-distinguisher for the VPN
1212 * @param irtList A list of Import Route Targets
1213 * @param ertList A list of Export Route Targets
1214 * @param routerIdsList ist of neutron router Id to associate with created VPN
1215 * @param networkList UUID of the neutron network the VPN may be associated to
1216 * @param type Type of the VPN Instance
1217 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1218 * @throws Exception if association of L3VPN failed
1220 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1221 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1222 VpnInstance.Type type, long l3vni) throws Exception {
1224 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1226 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1227 for (Uuid routerId : routerIdsList) {
1228 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1229 ipVersChoices = ipVersChoices.addVersion(vers);
1232 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1234 // Please note that router and networks will be filled into VPNMaps
1235 // by subsequent calls here to associateRouterToVpn and
1236 // associateNetworksToVpn
1237 updateVpnMaps(vpnId, name, null, tenantId, null);
1238 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1239 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1242 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1243 for (Uuid routerId : routerIdsList) {
1244 associateRouterToVpn(vpnId, routerId);
1247 if (networkList != null) {
1248 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1249 if (!failStrings.isEmpty()) {
1250 LOG.error("VPN {} association to networks failed for networks: {}. ",
1251 vpnId.getValue(), failStrings.toString());
1252 throw new Exception(failStrings.toString());
1258 * It handles the invocations to the createVPN RPC method.
1261 // TODO Clean up the exception handling
1262 @SuppressWarnings("checkstyle:IllegalCatch")
1263 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1265 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1266 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1267 List<RpcError> errorList = new ArrayList<>();
1268 int failurecount = 0;
1269 int warningcount = 0;
1271 List<L3vpn> vpns = input.getL3vpn();
1273 vpns = Collections.emptyList();
1275 for (L3vpn vpn : vpns) {
1276 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1277 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1278 formatAndLog(LOG::warn,
1279 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1280 vpn.getId().getValue())));
1284 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1285 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1286 formatAndLog(LOG::warn,
1287 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1288 vpn.getId().getValue())));
1292 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1294 if (vpn.getL3vni() != null) {
1295 l3vni = vpn.getL3vni();
1298 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1299 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1300 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1301 formatAndLog(LOG::warn,
1302 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1303 + "is already configured",
1304 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1308 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1309 if (operationalVpn.isPresent()) {
1310 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1311 formatAndLog(LOG::error,
1312 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1313 + "is still available. Please retry creation of a new vpn with the same RD"
1314 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1315 vpn.getRouteDistinguisher().get(0))));
1319 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1320 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1321 routerIdsList = vpn.getRouterIds();
1322 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1323 routerId : routerIdsList) {
1324 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1325 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1326 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1327 + "{}", vpn.getId(), routerId.getRouterId())));
1331 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1332 if (vpnId != null) {
1333 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1334 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1335 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1336 vpnId.getValue())));
1342 if (vpn.getNetworkIds() != null) {
1343 int initialWarningCount = warningcount;
1344 for (Uuid nw : vpn.getNetworkIds()) {
1345 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1346 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1347 if (network == null) {
1348 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1349 formatAndLog(LOG::warn,
1350 "Creation of L3VPN failed for VPN {} due to network not found {}",
1351 vpn.getId().getValue(), nw.getValue())));
1353 } else if (vpnId != null) {
1354 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1355 formatAndLog(LOG::warn,
1356 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1357 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1358 vpnId.getValue())));
1362 if (warningcount != initialWarningCount) {
1366 List<Uuid> rtrIdsList = new ArrayList<>();
1367 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1368 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1369 rtrId : vpn.getRouterIds()) {
1370 rtrIdsList.add(rtrId.getRouterId());
1374 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1375 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1376 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1377 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1378 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1379 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1380 vpnInstanceType, l3vni);
1381 } catch (Exception ex) {
1382 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1383 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1388 // if at least one succeeds; result is success
1389 // if none succeeds; result is failure
1390 if (failurecount + warningcount == vpns.size()) {
1391 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1393 List<String> errorResponseList = new ArrayList<>();
1394 if (!errorList.isEmpty()) {
1395 for (RpcError rpcError : errorList) {
1396 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1397 + ", ErrorMessage: " + rpcError.getMessage());
1400 errorResponseList.add("Operation successful with no errors");
1402 opBuilder.setResponse(errorResponseList);
1403 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1409 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1412 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1414 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1415 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1416 Uuid inputVpnId = input.getId();
1417 List<VpnInstance> vpns = new ArrayList<>();
1418 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1421 if (inputVpnId == null) {
1423 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1425 Optional<VpnInstances> optionalVpns =
1426 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1428 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1429 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance()) {
1430 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1431 // from getL3VPN output
1432 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1435 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1441 opBuilder.setL3vpnInstances(l3vpnList);
1442 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1446 String name = inputVpnId.getValue();
1447 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1448 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1449 // read VpnInstance Info
1450 Optional<VpnInstance> optionalVpn =
1451 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1453 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1455 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1456 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1457 vpns.add(optionalVpn.get());
1460 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1461 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1465 for (VpnInstance vpnInstance : vpns) {
1466 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1467 // create VpnMaps id
1468 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1469 List<String> rd = Collections.EMPTY_LIST;
1470 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1471 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1472 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1473 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1475 List<String> ertList = new ArrayList<>();
1476 List<String> irtList = new ArrayList<>();
1478 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1479 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1480 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1481 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1482 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1483 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1484 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1486 if (!vpnTargetList.isEmpty()) {
1487 for (VpnTarget vpnTarget : vpnTargetList) {
1488 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1489 ertList.add(vpnTarget.getVrfRTValue());
1491 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1492 irtList.add(vpnTarget.getVrfRTValue());
1494 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1495 ertList.add(vpnTarget.getVrfRTValue());
1496 irtList.add(vpnTarget.getVrfRTValue());
1502 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1504 if (vpnInstance.getL3vni() != null) {
1505 l3vpn.setL3vni(vpnInstance.getL3vni());
1507 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1508 .class, new VpnMapKey(vpnId)).build();
1509 Optional<VpnMap> optionalVpnMap =
1510 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1512 if (optionalVpnMap.isPresent()) {
1513 VpnMap vpnMap = optionalVpnMap.get();
1514 List<Uuid> rtrIds = new ArrayList<>();
1515 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1516 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1517 rtrIds.add(rtrId.getRouterId());
1520 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1521 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1522 .setName(vpnMap.getName());
1525 l3vpnList.add(l3vpn.build());
1528 opBuilder.setL3vpnInstances(l3vpnList);
1529 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1531 } catch (ReadFailedException ex) {
1532 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1533 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1539 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1542 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1544 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1545 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1546 List<RpcError> errorList = new ArrayList<>();
1548 int failurecount = 0;
1549 int warningcount = 0;
1550 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1551 for (Uuid vpn : vpns) {
1553 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1554 InstanceIdentifier<VpnInstance> vpnIdentifier =
1555 InstanceIdentifier.builder(VpnInstances.class)
1556 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1557 Optional<VpnInstance> optionalVpn =
1558 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1560 if (optionalVpn.isPresent()) {
1563 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1564 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1567 } catch (ReadFailedException ex) {
1568 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1569 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1574 // if at least one succeeds; result is success
1575 // if none succeeds; result is failure
1576 if (failurecount + warningcount == vpns.size()) {
1577 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1579 List<String> errorResponseList = new ArrayList<>();
1580 if (!errorList.isEmpty()) {
1581 for (RpcError rpcError : errorList) {
1582 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1583 + ", ErrorMessage: " + rpcError.getMessage());
1586 errorResponseList.add("Operation successful with no errors");
1588 opBuilder.setResponse(errorResponseList);
1589 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1594 public void createVpnInstanceForSubnet(Uuid subnetId) {
1595 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1596 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1599 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1600 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1601 removeVpn(subnetId);
1604 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1605 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1606 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1607 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1609 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1610 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1613 if (vpnId != null) {
1614 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1615 if (vpnMap == null) {
1616 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1617 + " cannot add subnet {} to VPN", vpnId.getValue(),
1621 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1622 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1623 if (isVpnOfTypeL2(vpnInstance)) {
1624 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1625 NeutronEvpnUtils.Operation.ADD);
1628 if (internetVpnId != null) {
1629 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1630 if (vpnMap == null) {
1631 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1632 + "subnet {} to VPN", internetVpnId.getValue(),
1637 final Uuid internetId = internetVpnId;
1638 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1639 List<Uuid> portList = sn.getPortList();
1640 if (portList != null) {
1641 for (final Uuid portId : portList) {
1642 String vpnInfName = portId.getValue();
1643 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1644 Port port = neutronvpnUtils.getNeutronPort(portId);
1646 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1647 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1650 final Boolean isRouterInterface = port.getDeviceOwner()
1651 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1652 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1653 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1654 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1656 if (vpnIface == null) {
1657 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1658 Set<Uuid> listVpn = new HashSet<>();
1659 if (vpnId != null) {
1662 if (internetId != null) {
1663 listVpn.add(internetId);
1665 writeVpnInterfaceToDs(listVpn,
1666 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1667 if (sn.getRouterId() != null) {
1668 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1671 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1672 if (vpnId != null) {
1673 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1675 if (internetId != null) {
1676 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1685 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1686 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1687 "removeSubnetFromVpn: at least one VPN must be not null");
1688 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1689 vpnId, internetVpnId);
1690 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1692 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1695 VpnMap vpnMap = null;
1696 VpnInstance vpnInstance = null;
1697 if (vpnId != null) {
1698 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1699 if (vpnMap == null) {
1700 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1701 vpnId.getValue(), subnet.getValue());
1704 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1706 if (internetVpnId == null) {
1707 internetVpnId = sn.getInternetVpnId();
1709 if (internetVpnId != null) {
1710 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1711 if (vpnMap == null) {
1712 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1713 + " from Internet VPN",
1714 internetVpnId.getValue(), subnet.getValue());
1718 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1719 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1720 NeutronEvpnUtils.Operation.DELETE);
1722 boolean subnetVpnAssociation = false;
1723 if (vpnId != null && sn.getVpnId() != null
1724 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1725 subnetVpnAssociation = true;
1726 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1727 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1728 subnetVpnAssociation = true;
1730 if (subnetVpnAssociation == false) {
1731 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1732 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1735 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1736 List<Uuid> portList = sn.getPortList();
1737 final Uuid internetId = internetVpnId;
1738 if (portList != null) {
1739 for (final Uuid portId : portList) {
1740 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1741 final Port port = neutronvpnUtils.getNeutronPort(portId);
1742 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1743 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1744 CONFIGURATION, tx -> {
1746 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1749 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1750 + "port is absent in Neutron config DS", portId.getValue(),
1756 //update subnet-vpn association
1757 removeFromSubnetNode(subnet, null, null, vpnId, null);
1760 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1761 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1762 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1764 Uuid internalVpnId = sm.getVpnId();
1765 if (internalVpnId == null) {
1766 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1767 sm.getId().getValue());
1770 if (isBeingAssociated) {
1771 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1773 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1776 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1777 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1778 if (isBeingAssociated) {
1779 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1780 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1782 removeInternetVpnFromVpnInterface(vpn,
1783 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1788 // Check for ports on this subnet and update association of
1789 // corresponding vpn-interfaces to internet vpn
1790 List<Uuid> portList = sm.getPortList();
1791 if (portList != null) {
1792 for (Uuid port : portList) {
1793 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1794 port.getValue(), isBeingAssociated);
1795 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1796 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1798 if (isBeingAssociated) {
1799 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1800 true, false, tx, true);
1802 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1810 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1811 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1812 oldVpnId.getValue(), newVpnId.getValue());
1813 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1814 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1815 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1816 Uuid vpnExtUuid = netIsExternal ? null
1817 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1818 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1820 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1823 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1824 * associated with internet BGP-VPN.
1826 if (vpnExtUuid != null) {
1827 /* Update V6 Internet default route match with new VPN metadata.
1828 * isBeingAssociated = true means oldVpnId is same as routerId
1829 * isBeingAssociated = false means newVpnId is same as routerId
1831 if (isBeingAssociated) {
1832 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1834 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1837 //Update Router Interface first synchronously.
1838 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1839 ListenableFuture<Void> future =
1840 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1841 tx -> updateVpnInterface(newVpnId, oldVpnId,
1842 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1843 isBeingAssociated, true, tx, false));
1844 Futures.addCallback(future, new FutureCallback<Void>() {
1846 public void onSuccess(Void result) {
1847 // Check for ports on this subnet and update association of
1848 // corresponding vpn-interfaces to external vpn
1849 List<Uuid> portList = sn.getPortList();
1850 if (portList != null) {
1851 for (Uuid port : portList) {
1852 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1853 port.getValue(), isBeingAssociated);
1854 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1855 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1856 tx -> updateVpnInterface(newVpnId, oldVpnId,
1857 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1864 public void onFailure(Throwable throwable) {
1866 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1868 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1870 }, MoreExecutors.directExecutor());
1875 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1876 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1877 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1880 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1881 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1882 final ReentrantLock lock = lockForUuid(routerId);
1885 Optional<RouterInterfaces> optRouterInterfaces =
1886 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1887 routerInterfacesId);
1888 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1889 .setInterfaceId(interfaceName).build();
1890 if (optRouterInterfaces.isPresent()) {
1891 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1892 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1894 // TODO Shouldn't we be doing something with builder and interfaces?
1895 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1896 // List<Interfaces> interfaces = new ArrayList<>();
1897 // interfaces.add(routerInterface);
1899 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1900 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1902 } catch (ReadFailedException | TransactionCommitFailedException e) {
1903 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1909 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1910 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1911 final ReentrantLock lock = lockForUuid(routerId);
1914 Optional<RouterInterfaces> optRouterInterfaces =
1915 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1916 routerInterfacesId);
1917 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1918 .setInterfaceId(interfaceName).build();
1919 if (optRouterInterfaces.isPresent()) {
1920 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1921 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1922 if (interfaces != null && interfaces.remove(routerInterface)) {
1923 if (interfaces.isEmpty()) {
1924 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1925 routerInterfacesId);
1927 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1928 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1932 } catch (ReadFailedException | TransactionCommitFailedException e) {
1933 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1940 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1941 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1942 * route will be ignored.
1944 * @param vpnName the VPN identifier
1945 * @param interVpnLinkRoutes The list of static routes
1946 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1948 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1949 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1950 for (Routes route : interVpnLinkRoutes) {
1951 String nexthop = route.getNexthop().stringValue();
1952 String destination = route.getDestination().stringValue();
1953 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1954 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1955 AddStaticRouteInput rpcInput =
1956 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1957 .setVpnInstanceName(vpnName.getValue())
1959 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1960 RpcResult<AddStaticRouteOutput> rpcResult;
1962 rpcResult = labelOuputFtr.get();
1963 if (rpcResult.isSuccessful()) {
1964 LOG.debug("Label generated for destination {} is: {}",
1965 destination, rpcResult.getResult().getLabel());
1967 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1968 destination, nexthop, rpcResult.getErrors());
1970 } catch (InterruptedException | ExecutionException e) {
1971 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1972 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1975 // Any other case is a fault.
1976 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1977 route.getDestination().stringValue(), nexthop);
1984 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1985 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1987 * @param vpnName the VPN identifier
1988 * @param interVpnLinkRoutes The list of static routes
1989 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1991 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1992 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1993 for (Routes route : interVpnLinkRoutes) {
1994 String nexthop = route.getNexthop().stringValue();
1995 String destination = route.getDestination().stringValue();
1996 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1997 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1998 RemoveStaticRouteInput rpcInput =
1999 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2000 .setVpnInstanceName(vpnName.getValue())
2003 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2004 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2006 // Any other case is a fault.
2007 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2008 route.getDestination().stringValue(), nexthop);
2015 * Returns true if the specified nexthop is the other endpoint in an
2016 * InterVpnLink, regarding one of the VPN's point of view.
2018 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
2020 interVpnLink != null
2021 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2022 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2023 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2024 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2028 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2029 List<Adjacency> adjList = new ArrayList<>();
2030 Map<String, List<String>> adjMap = new HashMap<>();
2031 for (Routes route : routeList) {
2032 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2033 LOG.error("Incorrect input received for extra route. {}", route);
2035 String nextHop = route.getNexthop().stringValue();
2036 String destination = route.getDestination().stringValue();
2037 if (!nextHop.equals(fixedIp)) {
2038 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2041 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2043 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2044 if (!hops.contains(nextHop)) {
2050 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2051 final String destination = entry.getKey();
2052 final List<String> ipList = entry.getValue();
2053 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2054 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2055 .withKey(new AdjacencyKey(destination)).build();
2061 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2062 checkAlarmExtraRoutes(vpnId, routeList);
2064 for (Routes route : routeList) {
2065 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2066 LOG.error("Incorrect input received for extra route. {}", route);
2068 String nextHop = route.getNexthop().stringValue();
2069 String destination = route.getDestination().stringValue();
2070 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2072 if (infName != null) {
2073 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2074 destination, vpnId.getValue(), nextHop, infName);
2075 boolean isLockAcquired = false;
2077 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2078 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2079 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2080 .child(Adjacency.class, new AdjacencyKey(destination));
2081 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2082 LogicalDatastoreType.CONFIGURATION, path);
2083 if (existingAdjacency.isPresent()
2084 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2085 LOG.error("The route with destination {} nextHop {} is already present as"
2086 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2087 destination, nextHop, infName);
2090 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2091 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2092 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2093 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2094 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2096 } catch (TransactionCommitFailedException e) {
2097 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2098 destination, nextHop, e);
2099 } catch (ReadFailedException e) {
2100 LOG.error("Exception on reading data-store ", e);
2102 if (isLockAcquired) {
2103 interfaceLock.unlock(infName);
2107 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2108 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2115 * This method setup or down an alarm about extra route fault.
2116 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2117 * available RDs, then an alarm and an error is generated.<br>
2118 * <b>Be careful</b> the routeList could be changed.
2120 * @param vpnId the vpnId of vpn to control.
2121 * @param routeList the list of router to check, it could be modified.
2123 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2124 if (!neutronvpnAlarm.isAlarmEnabled()) {
2125 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2128 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2129 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2130 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2134 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2135 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2136 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2140 for (Routes route : routeList) {
2141 // count the number of nexthops for each same route.getDestingation().getValue()
2142 String destination = route.getDestination().stringValue();
2143 String nextHop = route.getNexthop().stringValue();
2144 List<String> nextHopList = new ArrayList<>();
2145 nextHopList.add(nextHop);
2147 for (Routes routeTmp : routeList) {
2148 String routeDest = routeTmp.getDestination().stringValue();
2149 if (!destination.equals(routeDest)) {
2152 String routeNextH = routeTmp.getNexthop().stringValue();
2153 if (nextHop.equals(routeNextH)) {
2157 nextHopList.add(routeTmp.getNexthop().stringValue());
2159 final List<String> rdList = new ArrayList<>();
2160 if (vpnInstance.getIpv4Family() != null
2161 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2162 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2168 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2169 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2170 if (rd != null && !rdList.contains(rd)) {
2175 // 1. VPN Instance Name
2176 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2179 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2180 Uuid routerUuid = routerUuidList.get(0);
2181 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2182 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2184 // 3. List of RDs associated with the VPN
2185 detailsAlarm.append(" List of RDs associated with the VPN: ");
2186 for (String s : rdList) {
2187 detailsAlarm.append(s);
2188 detailsAlarm.append(", ");
2191 // 4. Prefix in question
2192 detailsAlarm.append(" for prefix: ");
2193 detailsAlarm.append(route.getDestination().stringValue());
2195 // 5. List of NHs for the prefix
2196 detailsAlarm.append(" for nextHops: ");
2197 for (String s : nextHopList) {
2198 detailsAlarm.append(s);
2199 detailsAlarm.append(", ");
2202 if (rdList.size() < nbNextHops) {
2203 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2205 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2210 // TODO Clean up the exception handling
2211 @SuppressWarnings("checkstyle:IllegalCatch")
2212 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2213 for (Routes route : routeList) {
2214 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2215 boolean isLockAcquired = false;
2216 String nextHop = route.getNexthop().stringValue();
2217 String destination = route.getDestination().stringValue();
2218 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2220 if (infName == null) {
2221 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2222 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2223 // Proceed to remove the next extra-route
2226 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2227 destination, vpnId.getValue(), nextHop, infName);
2229 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2230 InstanceIdentifier.builder(VpnInterfaces.class)
2231 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2232 .augmentation(Adjacencies.class)
2233 .child(Adjacency.class, new AdjacencyKey(destination))
2237 // Looking for existing prefix in MDSAL database
2238 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2239 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2240 boolean updateNextHops = false;
2241 List<String> nextHopList = new ArrayList<>();
2242 if (adjacency.isPresent()) {
2243 List<String> nhListRead = adjacency.get().getNextHopIpList();
2244 if (nhListRead.size() > 1) { // ECMP case
2245 for (String nextHopRead : nhListRead) {
2246 if (nextHopRead.equals(nextHop)) {
2247 updateNextHops = true;
2249 nextHopList.add(nextHopRead);
2255 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2256 if (updateNextHops) {
2257 // An update must be done, not including the current next hop
2258 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2259 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2260 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2261 .setNextHopIpList(nextHopList)
2262 .withKey(new AdjacencyKey(destination))
2264 Adjacencies erAdjs =
2265 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2266 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2267 .addAugmentation(Adjacencies.class, erAdjs).build();
2268 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2269 vpnIfIdentifier, vpnIf);
2271 // Remove the whole route
2272 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2273 adjacencyIdentifier);
2274 LOG.trace("extra route {} deleted successfully", route);
2276 } catch (TransactionCommitFailedException | ReadFailedException e) {
2277 LOG.error("exception in deleting extra route with destination {} for interface {}",
2278 destination, infName, e);
2280 if (isLockAcquired) {
2281 interfaceLock.unlock(infName);
2285 LOG.error("Incorrect input received for extra route: {}", route);
2290 public void removeVpn(Uuid vpnId) {
2292 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2293 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2294 List<Uuid> routerUuidList = new ArrayList<>();
2295 // dissociate router
2296 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2297 for (RouterIds router : routerIdsList) {
2298 Uuid routerId = router.getRouterId();
2299 routerUuidList.add(routerId);
2300 dissociateRouterFromVpn(vpnId, routerId);
2303 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2304 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2306 // remove entire vpnMaps node
2307 deleteVpnMapsNode(vpnId);
2309 // remove vpn-instance
2310 deleteVpnInstance(vpnId);
2311 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2314 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2315 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2318 // TODO Clean up the exception handling
2319 @SuppressWarnings("checkstyle:IllegalCatch")
2320 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2321 updateVpnMaps(vpnId, null, routerId, null, null);
2322 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2323 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2324 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2325 for (Subnetmap sn : subMapList) {
2326 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2327 if (!ipVersion.isIpVersionChosen(ipVers)) {
2328 ipVersion = ipVersion.addVersion(ipVers);
2331 if (ipVersion != IpVersionChoice.UNDEFINED) {
2332 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2334 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2336 for (Subnetmap sn : subMapList) {
2337 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2341 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2342 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2343 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2344 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2345 for (Uuid subnet : routerSubnets) {
2346 IpVersionChoice version = NeutronvpnUtils
2347 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2348 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2349 addSubnetToVpn(vpnId, subnet, null);
2351 addSubnetToVpn(vpnId, subnet, internetVpnId);
2356 // TODO Clean up the exception handling
2357 @SuppressWarnings("checkstyle:IllegalCatch")
2358 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2360 clearFromVpnMaps(vpnId, routerId, null);
2361 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2362 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2363 for (Subnetmap sn : subMapList) {
2364 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2365 if (ipVersion.isIpVersionChosen(ipVers)) {
2366 ipVersion = ipVersion.addVersion(ipVers);
2368 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2369 routerId.getValue());
2370 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2372 if (ipVersion != IpVersionChoice.UNDEFINED) {
2373 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2375 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2381 * Parses and associates networks list with given VPN.
2383 * @param vpnId Uuid of given VPN.
2384 * @param networkList List list of network Ids (Uuid), which will be associated.
2385 * @return list of formatted strings with detailed error messages.
2388 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2389 List<String> failedNwList = new ArrayList<>();
2390 HashSet<Uuid> passedNwList = new HashSet<>();
2391 boolean isExternalNetwork = false;
2392 if (networkList.isEmpty()) {
2393 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2394 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2396 return failedNwList;
2398 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2399 if (vpnInstance == null) {
2400 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2401 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2402 + "in ConfigDS", vpnId.getValue()));
2403 return failedNwList;
2406 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2407 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2409 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2410 + "associated with", vpnId.getValue()));
2411 return failedNwList;
2413 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2414 for (Uuid nw : networkList) {
2415 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2416 if (network == null) {
2417 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2418 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2422 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2423 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2424 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2425 nw.getValue(), vpnId.getValue());
2426 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2427 nw.getValue(), vpnId.getValue()));
2430 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2431 if (networkVpnId != null) {
2432 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2433 nw.getValue(), networkVpnId.getValue());
2434 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2435 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2438 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2439 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2440 nw.getValue(), vpnId.getValue());
2441 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2442 nw.getValue(), vpnId.getValue()));
2445 if (NeutronvpnUtils.getIsExternal(network)) {
2446 isExternalNetwork = true;
2448 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2449 if (subnetmapList == null || subnetmapList.isEmpty()) {
2450 passedNwList.add(nw);
2453 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2456 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2457 for (Subnetmap subnetmap : subnetmapList) {
2458 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2459 if (!ipVersion.isIpVersionChosen(ipVers)) {
2460 ipVersion = ipVersion.addVersion(ipVers);
2463 if (ipVersion != IpVersionChoice.UNDEFINED) {
2464 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2465 + " for VPN {} ", ipVersion, vpnId);
2466 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2468 for (Subnetmap subnetmap : subnetmapList) {
2469 Uuid subnetId = subnetmap.getId();
2470 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2471 if (subnetVpnId != null) {
2472 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2473 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2474 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2475 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2478 if (!NeutronvpnUtils.getIsExternal(network)) {
2479 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2481 addSubnetToVpn(vpnId, subnetId, null);
2482 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2484 passedNwList.add(nw);
2487 passedNwList.add(nw);
2489 } catch (ReadFailedException e) {
2490 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2492 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2495 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2496 if (!isExternalNetwork) {
2497 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2499 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2500 return failedNwList;
2503 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2504 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2507 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2508 if (vpnOpDataEntry == null) {
2509 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2512 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2513 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2514 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2516 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2517 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2518 updateVpnMaps(vpnId, null, null, null, extNwList);
2519 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2520 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2521 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2523 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2526 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2527 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2530 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2531 updateVpnInternetForSubnet(sm, vpnId, true);
2533 if (!ipVersion.isIpVersionChosen(ipVers)) {
2534 ipVersion = ipVersion.addVersion(ipVers);
2537 if (ipVersion != IpVersionChoice.UNDEFINED) {
2538 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2539 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2540 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2546 * Parses and disassociates networks list from given VPN.
2548 * @param vpnId Uuid of given VPN.
2549 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2550 * @return list of formatted strings with detailed error messages.
2553 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2554 List<String> failedNwList = new ArrayList<>();
2555 HashSet<Uuid> passedNwList = new HashSet<>();
2556 if (networkList.isEmpty()) {
2557 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2558 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2560 return failedNwList;
2562 for (Uuid nw : networkList) {
2563 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2564 if (networkSubnets == null) {
2565 passedNwList.add(nw);
2568 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2569 if (network == null) {
2570 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2571 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2575 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2576 if (networkVpnId == null) {
2577 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2578 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2582 if (!vpnId.equals(networkVpnId)) {
2583 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2584 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2585 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2586 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2590 if (NeutronvpnUtils.getIsExternal(network)) {
2591 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2592 passedNwList.add(nw);
2594 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2595 nw.getValue(), vpnId.getValue());
2596 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2601 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2602 for (Uuid subnet : networkSubnets) {
2603 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2604 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2605 if (!ipVersion.isIpVersionChosen(ipVers)) {
2606 ipVersion = ipVersion.addVersion(ipVers);
2608 if (!NeutronvpnUtils.getIsExternal(network)) {
2609 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2611 removeSubnetFromVpn(vpnId, subnet, null);
2612 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2613 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2615 passedNwList.add(nw);
2618 if (ipVersion != IpVersionChoice.UNDEFINED) {
2619 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2620 + " for VPN {}", ipVersion, vpnId);
2621 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2624 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2625 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2626 passedNwList.toString(), vpnId.getValue());
2627 return failedNwList;
2630 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2631 if (!removeExternalNetworkFromVpn(extNet)) {
2634 // check, if there is another Provider Networks associated with given VPN
2635 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2636 if (vpnNets != null) {
2637 //Remove currently disassociated network from the list
2638 vpnNets.remove(extNet.getUuid());
2639 for (Uuid netId : vpnNets) {
2640 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2641 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2642 + "{}", vpnId.getValue(), netId.getValue());
2647 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2648 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2649 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2650 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2651 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2652 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2653 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2655 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2658 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2659 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2662 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2663 updateVpnInternetForSubnet(sm, vpnId, false);
2665 if (!ipVersion.isIpVersionChosen(ipVers)) {
2666 ipVersion = ipVersion.addVersion(ipVers);
2669 if (ipVersion != IpVersionChoice.UNDEFINED) {
2670 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2671 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2673 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2679 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2682 // TODO Clean up the exception handling
2683 @SuppressWarnings("checkstyle:IllegalCatch")
2684 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2686 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2687 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2688 StringBuilder returnMsg = new StringBuilder();
2689 Uuid vpnId = input.getVpnId();
2692 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2693 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2694 input.getNetworkId().toString());
2695 List<Uuid> netIds = input.getNetworkId();
2696 if (netIds != null && !netIds.isEmpty()) {
2697 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2698 if (!failed.isEmpty()) {
2699 returnMsg.append(failed);
2703 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2705 if (returnMsg.length() != 0) {
2706 opBuilder.setResponse(
2707 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2708 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2709 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2711 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2713 } catch (Exception ex) {
2714 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2715 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2716 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2718 LOG.debug("associateNetworks returns..");
2723 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2726 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2728 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2729 LOG.debug("associateRouter {}", input);
2730 StringBuilder returnMsg = new StringBuilder();
2731 Uuid vpnId = input.getVpnId();
2732 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2733 routerIds = input.getRouterIds();
2734 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2735 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2736 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2737 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2738 .RouterIds routerId : routerIds) {
2739 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2740 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2741 if (vpnMap != null) {
2743 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2744 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2745 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2746 .append(routerId.getRouterId());
2747 } else if (extVpnId != null) {
2748 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2749 + "another VPN ").append(extVpnId.getValue());
2751 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2752 routerId.getRouterId());
2753 associateRouterToVpn(vpnId, routerId.getRouterId());
2756 returnMsg.append("router not found : ").append(routerId.getRouterId());
2759 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2761 if (returnMsg.length() != 0) {
2762 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2763 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2764 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2766 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2769 LOG.debug("associateRouter returns..");
2774 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2777 // TODO Clean up the exception handling
2778 @SuppressWarnings("checkstyle:IllegalCatch")
2779 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2780 GetFixedIPsForNeutronPortInput input) {
2781 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2782 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2783 Uuid portId = input.getPortId();
2784 StringBuilder returnMsg = new StringBuilder();
2786 List<String> fixedIPList = new ArrayList<>();
2787 Port port = neutronvpnUtils.getNeutronPort(portId);
2789 for (FixedIps ip : port.nonnullFixedIps()) {
2790 fixedIPList.add(ip.getIpAddress().stringValue());
2793 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2795 if (returnMsg.length() != 0) {
2796 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2798 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2799 returnMsg)).build());
2801 opBuilder.setFixedIPs(fixedIPList);
2802 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2804 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2806 } catch (Exception ex) {
2807 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2808 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2809 portId.getValue(), ex.getMessage(), ex)).build());
2815 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2818 // TODO Clean up the exception handling
2819 @SuppressWarnings("checkstyle:IllegalCatch")
2820 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2822 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2823 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2825 LOG.debug("dissociateNetworks {}", input);
2826 StringBuilder returnMsg = new StringBuilder();
2827 Uuid vpnId = input.getVpnId();
2830 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2831 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2832 input.getNetworkId().toString());
2833 List<Uuid> netIds = input.getNetworkId();
2834 if (netIds != null && !netIds.isEmpty()) {
2835 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2836 if (!failed.isEmpty()) {
2837 returnMsg.append(failed);
2841 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2843 if (returnMsg.length() != 0) {
2844 opBuilder.setResponse(
2845 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2846 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2848 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2850 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2852 } catch (Exception ex) {
2853 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2854 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2855 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2857 LOG.debug("dissociateNetworks returns..");
2862 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2865 // TODO Clean up the exception handling
2866 @SuppressWarnings("checkstyle:IllegalCatch")
2867 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2869 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2871 LOG.debug("dissociateRouter {}", input);
2872 StringBuilder returnMsg = new StringBuilder();
2873 Uuid vpnId = input.getVpnId();
2874 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2875 .RouterIds> routerIdList = input.getRouterIds();
2876 String routerIdsString = "";
2877 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2878 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2879 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2880 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2881 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2882 .RouterIds routerId : routerIdList) {
2884 if (routerId != null) {
2885 routerIdsString += routerId.getRouterId() + ", ";
2886 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2888 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2889 if (routerVpnId == null) {
2890 returnMsg.append("input router ").append(routerId.getRouterId())
2891 .append(" not associated to any vpn yet");
2892 } else if (vpnId.equals(routerVpnId)) {
2893 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2895 returnMsg.append("input router ").append(routerId.getRouterId())
2896 .append(" associated to vpn ")
2897 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2900 returnMsg.append("router not found : ").append(routerId.getRouterId());
2903 if (returnMsg.length() != 0) {
2904 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2905 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2906 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2907 returnMsg)).build());
2909 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2911 } catch (Exception ex) {
2912 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2913 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2914 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2918 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2921 LOG.debug("dissociateRouter returns..");
2925 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2926 // check if the router is associated to some VPN
2927 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2928 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2929 if (vpnId != null) {
2930 // remove existing external vpn interfaces
2931 for (Uuid subnetId : routerSubnetIds) {
2932 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2934 clearFromVpnMaps(vpnId, routerId, null);
2936 // remove existing internal vpn interfaces
2937 for (Uuid subnetId : routerSubnetIds) {
2938 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2941 // delete entire vpnMaps node for internal VPN
2942 deleteVpnMapsNode(routerId);
2944 // delete vpn-instance for internal VPN
2945 deleteVpnInstance(routerId);
2948 protected Subnet getNeutronSubnet(Uuid subnetId) {
2949 return neutronvpnUtils.getNeutronSubnet(subnetId);
2953 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2954 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2956 return sn.getGatewayIp();
2962 protected Network getNeutronNetwork(Uuid networkId) {
2963 return neutronvpnUtils.getNeutronNetwork(networkId);
2966 protected Port getNeutronPort(String name) {
2967 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2970 protected Port getNeutronPort(Uuid portId) {
2971 return neutronvpnUtils.getNeutronPort(portId);
2974 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2975 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2978 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2979 return neutronvpnUtils.getNetworksForVpn(vpnId);
2983 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2985 * @return a List of String to be printed on screen
2986 * @throws ReadFailedException if there was a problem reading from the data store
2988 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2989 List<String> result = new ArrayList<>();
2990 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2992 result.add("-------------------------------------------------------------------------------------------");
2993 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2995 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2996 if (ports.isPresent() && ports.get().getPort() != null) {
2997 for (Port port : ports.get().nonnullPort()) {
2998 List<FixedIps> fixedIPs = port.getFixedIps();
2999 if (fixedIPs != null && !fixedIPs.isEmpty()) {
3000 List<String> ipList = new ArrayList<>();
3001 for (FixedIps fixedIp : fixedIPs) {
3002 IpAddress ipAddress = fixedIp.getIpAddress();
3003 if (ipAddress.getIpv4Address() != null) {
3004 ipList.add(ipAddress.getIpv4Address().getValue());
3006 ipList.add(ipAddress.getIpv6Address().getValue());
3009 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3010 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3011 ipList.toString()));
3013 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3014 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3023 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3025 * @param vpnuuid Uuid of the VPN whose config must be shown
3026 * @return formatted output list
3027 * @throws InterruptedException if there was a thread related problem getting the data to display
3028 * @throws ExecutionException if there was any other problem getting the data to display
3030 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3031 List<String> result = new ArrayList<>();
3032 if (vpnuuid == null) {
3034 result.add("Displaying VPN config for all VPNs");
3035 result.add("To display VPN config for a particular VPN, use the following syntax");
3036 result.add(getshowVpnConfigCLIHelp());
3038 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3039 if (rpcResult.isSuccessful()) {
3041 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3043 result.add(String.format(" %-80s ", "Import-RTs"));
3045 result.add(String.format(" %-80s ", "Export-RTs"));
3047 result.add(String.format(" %-76s ", "Subnet IDs"));
3049 result.add("------------------------------------------------------------------------------------");
3051 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3052 rpcResult.getResult().nonnullL3vpnInstances()) {
3053 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3055 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3056 vpn.getRouteDistinguisher()));
3058 result.add(String.format(" %-80s ", vpn.getImportRT()));
3060 result.add(String.format(" %-80s ", vpn.getExportRT()));
3063 Uuid vpnid = vpn.getId();
3064 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3065 if (!subnetList.isEmpty()) {
3066 for (Uuid subnetuuid : subnetList) {
3067 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3070 result.add(String.format(" %-76s ", "\" \""));
3073 result.add("----------------------------------------");
3077 String errortag = rpcResult.getErrors().iterator().next().getTag();
3078 if (Objects.equals(errortag, "")) {
3080 result.add("No VPN has been configured yet");
3081 } else if (Objects.equals(errortag, "invalid-value")) {
3083 result.add("VPN " + vpnuuid.getValue() + " is not present");
3085 result.add("error getting VPN info : " + rpcResult.getErrors());
3086 result.add(getshowVpnConfigCLIHelp());
3092 protected void createExternalVpnInterfaces(Uuid extNetId) {
3093 if (extNetId == null) {
3094 LOG.error("createExternalVpnInterfaces: external network is null");
3098 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3099 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3100 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3104 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3105 for (String elanInterface : extElanInterfaces) {
3106 createExternalVpnInterface(extNetId, elanInterface, tx);
3108 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3111 // TODO Clean up the exception handling
3112 @SuppressWarnings("checkstyle:IllegalCatch")
3113 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3114 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3115 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3116 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3119 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3120 for (String elanInterface : extElanInterfaces) {
3121 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3122 .buildVpnInterfaceIdentifier(elanInterface);
3123 LOG.info("Removing vpn interface {}", elanInterface);
3124 tx.delete(vpnIfIdentifier);
3126 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3129 private void createExternalVpnInterface(Uuid vpnId, String infName,
3130 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3131 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3132 false /* not a router iface */, wrtConfigTxn);
3135 // TODO Clean up the exception handling
3136 @SuppressWarnings("checkstyle:IllegalCatch")
3137 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3138 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3139 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3140 if (vpnIdList.isEmpty() || infName == null) {
3141 LOG.error("vpnid is empty or interface({}) is null", infName);
3144 if (wrtConfigTxn == null) {
3145 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3146 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3147 "Error writing VPN interface");
3150 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3151 for (Uuid vpnId: vpnIdList) {
3152 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3153 AssociatedSubnetType.V4AndV6Subnets);
3154 vpnIdListStruct.add(vpnInstance);
3157 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3158 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3160 .setVpnInstanceNames(vpnIdListStruct)
3161 .setRouterInterface(isRouterInterface);
3162 LOG.info("Network Id is {}", networkUuid);
3163 if (networkUuid != null) {
3164 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3165 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3166 NetworkAttributes.NetworkType networkType = providerType != null
3167 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3168 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3169 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3170 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3173 if (adjacencies != null) {
3174 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3176 VpnInterface vpnIf = vpnb.build();
3178 LOG.info("Creating vpn interface {}", vpnIf);
3179 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3180 } catch (Exception ex) {
3181 LOG.error("Creation of vpninterface {} failed", infName, ex);
3185 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3186 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3187 if (vpnId == null || infName == null) {
3188 LOG.error("vpn id or interface is null");
3191 if (wrtConfigTxn == null) {
3192 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3193 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3194 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3195 }), LOG, "Error updating VPN interface with adjacencies");
3199 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3200 boolean isLockAcquired = false;
3202 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3203 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3204 .syncReadOptional(dataBroker, LogicalDatastoreType
3205 .CONFIGURATION, vpnIfIdentifier);
3206 if (optionalVpnInterface.isPresent()) {
3207 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3208 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3210 if (adjacencies == null) {
3211 if (isLockAcquired) {
3212 interfaceLock.unlock(infName);
3216 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3217 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3218 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3219 optionalVpnInterface.get().getVpnInstanceNames());
3220 if (listVpnInstances.isEmpty() || !VpnHelper
3221 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3222 VpnInstanceNames vpnInstance = VpnHelper
3223 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3224 listVpnInstances.add(vpnInstance);
3225 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3228 VpnInstanceNames vpnInstance = VpnHelper
3229 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3230 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3231 listVpnInstances.add(vpnInstance);
3232 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3234 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3235 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3237 } catch (IllegalStateException | ReadFailedException ex) {
3238 LOG.error("Update of vpninterface {} failed", infName, ex);
3240 if (isLockAcquired) {
3241 interfaceLock.unlock(infName);
3246 private String getshowVpnConfigCLIHelp() {
3247 StringBuilder help = new StringBuilder("Usage:");
3248 help.append("display vpn-config [-vid/--vpnid <id>]");
3249 return help.toString();
3252 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3253 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3257 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3258 return neutronEvpnManager.createEVPN(input);
3262 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3263 return neutronEvpnManager.getEVPN(input);
3267 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3268 return neutronEvpnManager.deleteEVPN(input);
3271 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3272 Uuid extNetId = extNet.getUuid();
3273 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3274 .child(Networks.class, new NetworksKey(extNetId)).build();
3277 Optional<Networks> optionalExtNets =
3278 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3280 if (!optionalExtNets.isPresent()) {
3281 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3282 extNetId.getValue());
3285 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3286 builder.setVpnid(vpnId);
3287 Networks networks = builder.build();
3288 // Add Networks object to the ExternalNetworks list
3289 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3290 extNetId.getValue());
3291 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3294 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3295 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3296 extNetId.getValue(), ex);
3301 private boolean removeExternalNetworkFromVpn(Network extNet) {
3302 Uuid extNetId = extNet.getUuid();
3303 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3304 .child(Networks.class, new NetworksKey(extNetId)).build();
3306 Optional<Networks> optionalNets =
3307 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3309 NetworksBuilder builder = null;
3310 if (optionalNets.isPresent()) {
3311 builder = new NetworksBuilder(optionalNets.get());
3313 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3314 extNetId.getValue());
3317 builder.setVpnid(null);
3318 Networks networks = builder.build();
3319 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3320 extNetId.getValue());
3321 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3323 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3324 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3325 extNetId.getValue(), ex);
3330 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3331 Optional<String> existingVpnName = Optional.of(primaryRd);
3332 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3334 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3335 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3336 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3337 } catch (ReadFailedException e) {
3338 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3340 /*Read failed. We don't know if a VPN exists or not.
3341 * Return primaryRd to halt caller execution, to be safe.*/
3342 return existingVpnName;
3344 if (vpnInstanceOpDataOptional.isPresent()) {
3345 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3347 existingVpnName = Optional.absent();
3349 return existingVpnName;
3352 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3353 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3356 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3357 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3360 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3361 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3364 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3365 String message = tuple.getMessage();
3366 logger.accept(message);
3370 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3371 @NonNull Subnetmap subnetMap) {
3372 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3373 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3374 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3375 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3376 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3377 subnetMap.getId().getValue(), internetVpnId.getValue());
3381 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3382 @NonNull Subnetmap subnetMap) {
3383 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3384 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3387 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3388 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3389 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3390 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3391 internetVpnId.getValue(), routerId.getValue());
3392 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3397 private static ReentrantLock lockForUuid(Uuid uuid) {
3398 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3399 return JvmGlobalLocks.getLockForString(uuid.getValue());