2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import static org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils.requireNonNullElse;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.JdkFutureAdapters;
20 import com.google.common.util.concurrent.ListenableFuture;
21 import com.google.common.util.concurrent.MoreExecutors;
22 import com.google.common.util.concurrent.SettableFuture;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.Map.Entry;
33 import java.util.Objects;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.function.Consumer;
40 import javax.annotation.Nonnull;
41 import javax.annotation.Nullable;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
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.infrautils.jobcoordinator.JobCoordinator;
58 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
59 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
60 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
61 import org.opendaylight.netvirt.elanmanager.api.IElanService;
62 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
63 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
64 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
65 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
66 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
67 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
68 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
177 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
178 import org.opendaylight.yangtools.yang.common.RpcError;
179 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
180 import org.opendaylight.yangtools.yang.common.RpcResult;
181 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
182 import org.slf4j.Logger;
183 import org.slf4j.LoggerFactory;
184 import org.slf4j.helpers.FormattingTuple;
185 import org.slf4j.helpers.MessageFormatter;
188 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
190 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
191 private static long LOCK_WAIT_TIME = 10L;
193 private final DataBroker dataBroker;
194 private final ManagedNewTransactionRunner txRunner;
195 private final NotificationPublishService notificationPublishService;
196 private final VpnRpcService vpnRpcService;
197 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
198 private final IElanService elanService;
199 private final NeutronvpnConfig neutronvpnConfig;
200 private final NeutronEvpnManager neutronEvpnManager;
201 private final NeutronEvpnUtils neutronEvpnUtils;
202 private final JobCoordinator jobCoordinator;
203 private final NeutronvpnUtils neutronvpnUtils;
204 private final IVpnManager vpnManager;
205 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
206 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
207 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
208 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
211 public NeutronvpnManager(
212 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
213 final VpnRpcService vpnRpcSrv, final IElanService elanService,
214 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
215 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
216 final JobCoordinator jobCoordinator,
217 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
218 this.dataBroker = dataBroker;
219 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
220 notificationPublishService = notiPublishService;
221 vpnRpcService = vpnRpcSrv;
222 this.elanService = elanService;
223 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
224 this.neutronvpnConfig = neutronvpnConfig;
225 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
226 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
227 this.jobCoordinator = jobCoordinator;
228 this.neutronvpnUtils = neutronvpnUtils;
229 this.vpnManager = vpnManager;
236 public void close() {
237 LOG.info("{} close", getClass().getSimpleName());
240 private void configureFeatures() throws TransactionCommitFailedException {
241 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
242 Neutron.class).child(Features.class).child(
243 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
244 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
246 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
247 } catch (OptimisticLockFailedException e) {
248 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
250 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
251 Neutron.class).child(Features.class).child(
252 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
253 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
255 SingleTransactionDataBroker.syncWrite(
256 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
257 } catch (OptimisticLockFailedException e) {
258 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
262 public String getOpenDaylightVniRangesConfig() {
263 return neutronvpnConfig.getOpendaylightVniRanges();
266 // TODO Clean up the exception handling
267 @SuppressWarnings("checkstyle:IllegalCatch")
268 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
269 @Nullable NetworkAttributes.NetworkType networkType, long segmentationId) {
271 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
272 synchronized (subnetId.getValue().intern()) {
273 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
274 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
275 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
276 if (sn.isPresent()) {
277 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
278 subnetId.getValue());
281 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
282 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
283 .setNetworkType(networkType).setSegmentationId(segmentationId);
284 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
285 subnetId.getValue());
286 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
287 subnetMapIdentifier, subnetmapBuilder.build());
289 } catch (TransactionCommitFailedException | ReadFailedException e) {
290 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
292 // check if there are ports to update for already created Subnetmap node
293 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
294 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
295 if (entry.getValue().getValue().equals(subnetId.getValue())) {
296 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
297 unprocessedPortsMap.remove(entry.getKey());
303 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
304 @Nullable Uuid internetvpnId) {
305 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
306 .child(Subnetmap.class, new SubnetmapKey(subnetId))
309 synchronized (subnetId.getValue().intern()) {
310 Optional<Subnetmap> sn =
311 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
313 if (!sn.isPresent()) {
314 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
317 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
318 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
319 if (routerId != null) {
320 builder.setRouterId(routerId);
323 builder.setVpnId(vpnId);
325 if (neutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
326 builder.setInternetVpnId(internetvpnId);
328 Subnetmap subnetmap = builder.build();
329 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
330 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
333 } catch (ReadFailedException | TransactionCommitFailedException e) {
334 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
339 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
340 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
341 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
342 InstanceIdentifier<Subnetmap> id =
343 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
345 synchronized (subnetId.getValue().intern()) {
346 Optional<Subnetmap> sn =
347 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
349 if (!sn.isPresent()) {
350 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
351 subnetId.getValue());
354 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
355 subnetId.getValue());
356 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
357 builder.setRouterId(routerId);
358 builder.setRouterInterfacePortId(routerInterfacePortId);
359 builder.setRouterIntfMacAddress(routerIntfMacAddress);
360 builder.setRouterInterfaceFixedIp(fixedIp);
362 builder.setVpnId(vpnId);
364 Subnetmap subnetmap = builder.build();
365 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
366 subnetId.getValue());
367 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
369 } catch (ReadFailedException | TransactionCommitFailedException e) {
370 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
371 subnetId.getValue(), e);
375 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
376 @Nullable Uuid directPortId) {
377 Subnetmap subnetmap = null;
378 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
379 new SubnetmapKey(subnetId)).build();
380 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
382 synchronized (subnetId.getValue().intern()) {
383 Optional<Subnetmap> sn =
384 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
386 if (sn.isPresent()) {
387 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
388 if (null != portId) {
389 List<Uuid> portList = builder.getPortList();
390 if (null == portList) {
391 portList = new ArrayList<>();
393 portList.add(portId);
394 builder.setPortList(portList);
395 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
396 subnetId.getValue(), portId.getValue());
398 if (null != directPortId) {
399 List<Uuid> directPortList = builder.getDirectPortList();
400 if (null == directPortList) {
401 directPortList = new ArrayList<>();
403 directPortList.add(directPortId);
404 builder.setDirectPortList(directPortList);
405 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
406 directPortId.getValue());
408 subnetmap = builder.build();
409 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
412 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
413 + "cache ", subnetId.getValue(), portId.getValue());
414 unprocessedPortsMap.put(portId, subnetId);
417 } catch (ReadFailedException | TransactionCommitFailedException e) {
418 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
423 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
424 Uuid vpnId, @Nullable Uuid portId) {
425 Subnetmap subnetmap = null;
426 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
427 .child(Subnetmap.class, new SubnetmapKey(subnetId))
430 synchronized (subnetId.getValue().intern()) {
431 Optional<Subnetmap> sn =
432 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
434 if (sn.isPresent()) {
435 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
436 if (routerId != null) {
437 builder.setRouterId(null);
439 if (networkId != null) {
440 builder.setNetworkId(null);
443 builder.setVpnId(null);
445 builder.setInternetVpnId(null);
446 if (portId != null && builder.getPortList() != null) {
447 List<Uuid> portList = builder.getPortList();
448 portList.remove(portId);
449 builder.setPortList(portList);
452 subnetmap = builder.build();
453 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
454 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
457 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
460 } catch (ReadFailedException | TransactionCommitFailedException e) {
461 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
467 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
468 @Nullable Uuid directPortId) {
469 Subnetmap subnetmap = null;
470 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
471 new SubnetmapKey(subnetId)).build();
473 synchronized (subnetId.getValue().intern()) {
474 Optional<Subnetmap> sn =
475 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
477 if (sn.isPresent()) {
478 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
479 if (null != portId && null != builder.getPortList()) {
480 List<Uuid> portList = builder.getPortList();
481 portList.remove(portId);
482 builder.setPortList(portList);
483 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
484 subnetId.getValue());
486 if (null != directPortId && null != builder.getDirectPortList()) {
487 List<Uuid> directPortList = builder.getDirectPortList();
488 directPortList.remove(directPortId);
489 builder.setDirectPortList(directPortList);
490 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
491 .getValue(), subnetId.getValue());
493 subnetmap = builder.build();
494 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
497 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
500 } catch (ReadFailedException | TransactionCommitFailedException e) {
501 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
502 subnetId.getValue(), e);
507 // TODO Clean up the exception handling
508 @SuppressWarnings("checkstyle:IllegalCatch")
509 protected void deleteSubnetMapNode(Uuid subnetId) {
510 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
511 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
512 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
514 synchronized (subnetId.getValue().intern()) {
515 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
516 subnetMapIdentifier);
518 } catch (TransactionCommitFailedException e) {
519 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
523 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
524 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
525 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
527 Optional<VpnInstance> vpnInstanceConfig =
528 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
530 if (!vpnInstanceConfig.isPresent()) {
531 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
534 VpnInstance vpnInstance = vpnInstanceConfig.get();
535 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
536 if (vpnInstance.getIpv4Family() != null) {
537 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
538 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
540 if (vpnInstance.getIpv6Family() != null) {
541 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
542 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
544 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
545 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
546 updateVpnInstanceBuilder.build());
547 } catch (ReadFailedException | TransactionCommitFailedException ex) {
548 LOG.warn("Error configuring feature ", ex);
552 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
553 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
554 String vpnName = vpnId.getValue();
555 VpnInstanceBuilder builder = null;
556 List<VpnTarget> vpnTargetList = new ArrayList<>();
557 boolean isLockAcquired = false;
558 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
559 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
561 Optional<VpnInstance> optionalVpn =
562 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
564 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
565 if (optionalVpn.isPresent()) {
566 builder = new VpnInstanceBuilder(optionalVpn.get());
567 LOG.debug("updating existing vpninstance node");
569 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
570 .setType(type).setL3vni(l3vni);
572 if (irt != null && !irt.isEmpty()) {
573 if (ert != null && !ert.isEmpty()) {
574 List<String> commonRT = new ArrayList<>(irt);
575 commonRT.retainAll(ert);
577 for (String common : commonRT) {
580 VpnTarget vpnTarget =
581 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
582 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
583 vpnTargetList.add(vpnTarget);
586 for (String importRT : irt) {
587 VpnTarget vpnTarget =
588 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
589 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
590 vpnTargetList.add(vpnTarget);
594 if (ert != null && !ert.isEmpty()) {
595 for (String exportRT : ert) {
596 VpnTarget vpnTarget =
597 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
598 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
599 vpnTargetList.add(vpnTarget);
603 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
605 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
606 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
608 if (rd != null && !rd.isEmpty()) {
609 ipv4vpnBuilder.setRouteDistinguisher(rd);
610 ipv6vpnBuilder.setRouteDistinguisher(rd);
613 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
614 builder.setIpv4Family(ipv4vpnBuilder.build());
616 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
617 builder.setIpv6Family(ipv6vpnBuilder.build());
619 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
620 builder.setIpv4Family(ipv4vpnBuilder.build());
622 VpnInstance newVpn = builder.build();
623 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
624 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
625 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
627 } catch (ReadFailedException | TransactionCommitFailedException e) {
628 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
630 if (isLockAcquired) {
631 vpnLock.unlock(vpnId);
636 private void deleteVpnMapsNode(Uuid vpnId) {
637 boolean isLockAcquired = false;
638 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
639 .child(VpnMap.class, new VpnMapKey(vpnId))
641 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
643 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
644 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
645 } catch (TransactionCommitFailedException e) {
646 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
648 if (isLockAcquired) {
649 vpnLock.unlock(vpnId);
654 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
655 @Nullable List<Uuid> networks) {
656 VpnMapBuilder builder;
657 boolean isLockAcquired = false;
658 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
659 .child(VpnMap.class, new VpnMapKey(vpnId))
662 Optional<VpnMap> optionalVpnMap =
663 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
665 if (optionalVpnMap.isPresent()) {
666 builder = new VpnMapBuilder(optionalVpnMap.get());
668 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
672 builder.setName(name);
674 if (tenantId != null) {
675 builder.setTenantId(tenantId);
677 if (router != null) {
678 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
679 List<RouterIds> rtrIds = builder.getRouterIds();
680 if (rtrIds == null) {
681 rtrIds = Collections.singletonList(vpnRouterId);
683 rtrIds.add(vpnRouterId);
685 builder.setRouterIds(rtrIds);
687 if (networks != null) {
688 List<Uuid> nwList = builder.getNetworkIds();
689 if (nwList == null) {
690 nwList = new ArrayList<>();
692 nwList.addAll(networks);
693 builder.setNetworkIds(nwList);
696 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
697 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
698 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
700 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
701 } catch (ReadFailedException | TransactionCommitFailedException e) {
702 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
704 if (isLockAcquired) {
705 vpnLock.unlock(vpnId);
710 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
711 boolean isLockAcquired = false;
712 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
713 .child(VpnMap.class, new VpnMapKey(vpnId))
715 Optional<VpnMap> optionalVpnMap;
718 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
720 } catch (ReadFailedException e) {
721 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
724 if (optionalVpnMap.isPresent()) {
725 VpnMap vpnMap = optionalVpnMap.get();
726 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
727 List<RouterIds> rtrIds = vpnMap.getRouterIds();
728 if (rtrIds == null) {
729 rtrIds = new ArrayList<>();
731 if (routerId != null) {
732 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
733 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
734 vpnMapBuilder.setRouterIds(rtrIds);
736 // remove entire node in case of internal VPN
737 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
738 LOG.debug("removing vpnMaps node: {} ", vpnId);
739 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
741 } catch (TransactionCommitFailedException e) {
742 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
744 if (isLockAcquired) {
745 vpnLock.unlock(vpnId);
749 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
750 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
751 vpnMapBuilder.setRouterIds(rtrIds);
752 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
755 if (networkIds != null) {
756 List<Uuid> vpnNw = vpnMap.getNetworkIds();
757 vpnNw.removeAll(networkIds);
758 if (vpnNw.isEmpty()) {
759 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
760 vpnMapBuilder.setNetworkIds(null);
762 vpnMapBuilder.setNetworkIds(vpnNw);
767 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
768 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
769 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
770 vpnMapBuilder.build());
771 } catch (TransactionCommitFailedException e) {
772 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
774 if (isLockAcquired) {
775 vpnLock.unlock(vpnId);
779 LOG.error("VPN : {} not found", vpnId.getValue());
781 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
784 private void deleteVpnInstance(Uuid vpnId) {
785 boolean isLockAcquired = false;
786 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
787 .child(VpnInstance.class,
788 new VpnInstanceKey(vpnId.getValue()))
791 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
792 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
793 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
794 } catch (TransactionCommitFailedException e) {
795 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
797 if (isLockAcquired) {
798 vpnLock.unlock(vpnId);
803 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
804 TypedWriteTransaction<Configuration> wrtConfigTxn,
805 @Nullable Subnetmap sn, @Nullable VpnInterface vpnIface) {
806 List<Adjacency> adjList = new ArrayList<>();
807 if (vpnIface != null) {
808 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
810 String infName = port.getUuid().getValue();
811 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
812 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
813 String ipValue = ip.getIpAddress().stringValue();
814 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
815 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
818 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
819 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
821 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
822 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
823 //Create Neutron port adjacency if VPN presence is existing for subnet
824 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
825 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
826 .setSubnetId(ip.getSubnetId()).build();
827 if (!adjList.contains(vmAdj)) {
831 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
832 if (snTemp != null && snTemp.getInternetVpnId() != null) {
833 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
834 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
836 if (routerId != null) {
837 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
838 if (rtr != null && rtr.getRoutes() != null) {
839 List<Routes> routeList = rtr.getRoutes();
840 // create extraroute Adjacence for each ipValue,
841 // because router can have IPv4 and IPv6 subnet ports, or can have
842 // more that one IPv4 subnet port or more than one IPv6 subnet port
843 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
844 if (!erAdjList.isEmpty()) {
845 adjList.addAll(erAdjList);
850 return new AdjacenciesBuilder().setAdjacency(adjList).build();
853 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
854 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
855 boolean isRouterInterface = false;
856 if (port.getDeviceOwner() != null) {
857 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
859 String infName = port.getUuid().getValue();
860 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
861 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
862 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, vpnIface);
863 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
864 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
867 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
868 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
869 String infName = port.getUuid().getValue();
870 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
871 Optional<VpnInterface> optionalVpnInterface = null;
872 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
873 vpnId, internetVpnId, infName);
875 optionalVpnInterface = SingleTransactionDataBroker
876 .syncReadOptional(dataBroker, LogicalDatastoreType
877 .CONFIGURATION, vpnIfIdentifier);
878 } catch (ReadFailedException e) {
879 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
882 if (!optionalVpnInterface.isPresent()) {
885 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
886 sn != null ? sn.getSubnetIp() : "null");
887 List<Adjacency> vpnAdjsList =
888 requireNonNullElse(optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency(),
889 Collections.emptyList());
890 List<Adjacency> updatedAdjsList = new ArrayList<>();
891 boolean isIpFromAnotherSubnet = false;
892 for (Adjacency adj : vpnAdjsList) {
893 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
894 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
895 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
896 isIpFromAnotherSubnet = true;
898 updatedAdjsList.add(adj);
901 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
902 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
905 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
906 String.valueOf(adjString), wrtConfigTxn);
908 if (internetVpnId != null) {
909 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
910 String.valueOf(adjString), wrtConfigTxn);
913 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
914 && sn.getRouterId() != null) {
915 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
916 if (rtr != null && rtr.getRoutes() != null) {
917 List<Routes> extraRoutesToRemove = new ArrayList<>();
918 for (Routes rt: rtr.getRoutes()) {
919 if (rt.getNexthop().toString().equals(adjString)) {
920 extraRoutesToRemove.add(rt);
924 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
925 extraRoutesToRemove, vpnId);
926 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
928 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
933 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
935 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
937 if (!isIpFromAnotherSubnet) {
938 // no more subnetworks for neutron port
939 if (sn != null && sn.getRouterId() != null) {
940 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
942 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
948 // TODO Clean up the exception handling
949 @SuppressWarnings("checkstyle:IllegalCatch")
950 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
951 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
952 if (wrtConfigTxn == null) {
953 ListenableFutures.addErrorLogging(
954 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
955 tx -> deleteVpnInterface(infName, vpnId, tx)),
956 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
960 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
961 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
962 Optional<VpnInterface> optionalVpnInterface;
964 optionalVpnInterface =
965 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
967 } catch (ReadFailedException ex) {
968 LOG.error("Error during deletion of vpninterface {}", infName, ex);
971 if (!optionalVpnInterface.isPresent()) {
972 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
976 VpnInterface vpnInterface = optionalVpnInterface.get();
977 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
979 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
980 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
981 if (!vpnList.isEmpty()) {
982 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
983 + "List not empty", infName);
986 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
987 .setVpnInstanceNames(vpnList);
988 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
992 LOG.debug("Deleting vpn interface {}", infName);
993 wrtConfigTxn.delete(vpnIfIdentifier);
996 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
997 TypedWriteTransaction<Configuration> writeConfigTxn,
999 if (vpnId == null || port == null) {
1002 String infName = port.getUuid().getValue();
1003 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1005 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1006 .syncReadOptional(dataBroker, LogicalDatastoreType
1007 .CONFIGURATION, vpnIfIdentifier);
1008 if (optionalVpnInterface.isPresent()) {
1009 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1011 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1012 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1014 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1015 .setVpnInstanceNames(listVpn);
1016 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1017 LOG.debug("Updating vpn interface {}", infName);
1018 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1019 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1020 while (adjacencyIter.hasNext()) {
1021 Adjacency adjacency = adjacencyIter.next();
1022 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1025 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1026 InstanceIdentifier<LearntVpnVipToPort> id =
1027 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1028 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1029 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1030 LogicalDatastoreType.OPERATIONAL, id);
1031 if (optionalVpnVipToPort.isPresent()) {
1032 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1034 if (listVpn == null || listVpn.isEmpty()) {
1035 adjacencyIter.remove();
1037 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1038 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1039 mipToQuery, infName, vpnId.getValue());
1042 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1043 String ipValue = ip.getIpAddress().stringValue();
1045 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1048 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1049 ipValue, writeConfigTxn);
1051 if (listVpn == null || listVpn.isEmpty()) {
1052 if (sm != null && sm.getRouterId() != null) {
1053 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1055 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1057 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1060 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1062 } catch (ReadFailedException ex) {
1063 LOG.error("Update of vpninterface {} failed", infName, ex);
1067 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1069 TypedWriteTransaction<Configuration> writeConfigTxn,
1070 boolean isInternetVpn) {
1071 if (vpnId == null || port == null) {
1074 boolean isLockAcquired = false;
1075 String infName = port.getUuid().getValue();
1076 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1079 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1080 Optional<VpnInterface> optionalVpnInterface =
1081 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1083 if (optionalVpnInterface.isPresent()) {
1084 VpnInstanceNames vpnInstance = VpnHelper
1085 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1086 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1087 .get().getVpnInstanceNames());
1088 if (oldVpnId != null
1089 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1090 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1092 if (vpnId.getValue() != null
1093 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1094 listVpn.add(vpnInstance);
1096 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1097 .setVpnInstanceNames(listVpn);
1098 LOG.debug("Updating vpn interface {}", infName);
1099 if (!isBeingAssociated) {
1100 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1101 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1102 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1103 while (adjacencyIter.hasNext()) {
1104 Adjacency adjacency = adjacencyIter.next();
1105 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1106 InstanceIdentifier<LearntVpnVipToPort> id =
1107 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1108 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1109 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1110 LogicalDatastoreType.OPERATIONAL, id);
1111 if (optionalVpnVipToPort.isPresent()) {
1112 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1113 + "from VPN {}", infName, vpnId, oldVpnId);
1114 adjacencyIter.remove();
1115 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1117 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1118 mipToQuery, infName, vpnId.getValue());
1121 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1122 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1124 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1125 String ipValue = ip.getIpAddress().stringValue();
1126 if (oldVpnId != null) {
1127 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1128 ipValue, writeConfigTxn);
1130 if ((NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6)
1131 && (isInternetVpn == true)) {
1135 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1136 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1138 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1140 LOG.error("VPN Interface {} not found", infName);
1142 } catch (ReadFailedException ex) {
1143 LOG.error("Updation of vpninterface {} failed", infName, ex);
1145 if (isLockAcquired) {
1146 interfaceLock.unlock(infName);
1151 public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List<String> rd,
1152 @Nullable List<String> irt, @Nullable List<String> ert, @Nullable Uuid router,
1153 @Nullable List<Uuid> networks) {
1155 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1157 // Update VPN Instance node
1158 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1160 // Update local vpn-subnet DS
1161 updateVpnMaps(vpn, name, router, tenant, networks);
1163 if (router != null) {
1164 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1165 if (existingVpn != null) {
1166 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1167 // if before reboot, router was already associated to VPN, should not proceed associating router to
1168 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1169 // preserved upon reboot.
1170 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1171 // RouterInterfacesMap via #createVPNInterface call.
1172 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1173 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1176 associateRouterToInternalVpn(vpn, router);
1181 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1182 * specified Neutron Networks and Routers.
1184 * @param vpnId Uuid of the VPN tp be created
1185 * @param name Representative name of the new VPN
1186 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1187 * @param rdList Route-distinguisher for the VPN
1188 * @param irtList A list of Import Route Targets
1189 * @param ertList A list of Export Route Targets
1190 * @param routerIdsList ist of neutron router Id to associate with created VPN
1191 * @param networkList UUID of the neutron network the VPN may be associated to
1192 * @param type Type of the VPN Instance
1193 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1194 * @throws Exception if association of L3VPN failed
1196 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1197 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1198 VpnInstance.Type type, long l3vni) throws Exception {
1200 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1202 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1203 for (Uuid routerId : routerIdsList) {
1204 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1205 ipVersChoices = ipVersChoices.addVersion(vers);
1208 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1210 // Please note that router and networks will be filled into VPNMaps
1211 // by subsequent calls here to associateRouterToVpn and
1212 // associateNetworksToVpn
1213 updateVpnMaps(vpnId, name, null, tenantId, null);
1214 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1215 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1218 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1219 for (Uuid routerId : routerIdsList) {
1220 associateRouterToVpn(vpnId, routerId);
1223 if (networkList != null) {
1224 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1225 if (!failStrings.isEmpty()) {
1226 LOG.error("VPN {} association to networks failed for networks: {}. ",
1227 vpnId.getValue(), failStrings.toString());
1228 throw new Exception(failStrings.toString());
1234 * It handles the invocations to the createVPN RPC method.
1237 // TODO Clean up the exception handling
1238 @SuppressWarnings("checkstyle:IllegalCatch")
1239 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1241 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1242 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1243 List<RpcError> errorList = new ArrayList<>();
1244 int failurecount = 0;
1245 int warningcount = 0;
1247 List<L3vpn> vpns = input.getL3vpn();
1249 vpns = Collections.emptyList();
1251 for (L3vpn vpn : vpns) {
1252 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1253 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1254 formatAndLog(LOG::warn,
1255 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1256 vpn.getId().getValue())));
1260 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1261 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1262 formatAndLog(LOG::warn,
1263 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1264 vpn.getId().getValue())));
1268 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1270 if (vpn.getL3vni() != null) {
1271 l3vni = vpn.getL3vni();
1274 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1275 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1276 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1277 formatAndLog(LOG::warn,
1278 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1279 + "is already configured",
1280 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1284 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1285 if (operationalVpn.isPresent()) {
1286 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1287 formatAndLog(LOG::error,
1288 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1289 + "is still available. Please retry creation of a new vpn with the same RD"
1290 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1291 vpn.getRouteDistinguisher().get(0))));
1295 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1296 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1297 routerIdsList = vpn.getRouterIds();
1298 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1299 routerId : routerIdsList) {
1300 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1301 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1302 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1303 + "{}", vpn.getId(), routerId.getRouterId())));
1307 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1308 if (vpnId != null) {
1309 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1310 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1311 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1312 vpnId.getValue())));
1318 if (vpn.getNetworkIds() != null) {
1319 int initialWarningCount = warningcount;
1320 for (Uuid nw : vpn.getNetworkIds()) {
1321 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1322 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1323 if (network == null) {
1324 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1325 formatAndLog(LOG::warn,
1326 "Creation of L3VPN failed for VPN {} due to network not found {}",
1327 vpn.getId().getValue(), nw.getValue())));
1329 } else if (vpnId != null) {
1330 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1331 formatAndLog(LOG::warn,
1332 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1333 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1334 vpnId.getValue())));
1338 if (warningcount != initialWarningCount) {
1342 List<Uuid> rtrIdsList = new ArrayList<>();
1343 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1344 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1345 rtrId : vpn.getRouterIds()) {
1346 rtrIdsList.add(rtrId.getRouterId());
1350 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1351 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1352 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1353 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1354 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1355 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1356 vpnInstanceType, l3vni);
1357 } catch (Exception ex) {
1358 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1359 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1364 // if at least one succeeds; result is success
1365 // if none succeeds; result is failure
1366 if (failurecount + warningcount == vpns.size()) {
1367 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1369 List<String> errorResponseList = new ArrayList<>();
1370 if (!errorList.isEmpty()) {
1371 for (RpcError rpcError : errorList) {
1372 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1373 + ", ErrorMessage: " + rpcError.getMessage());
1376 errorResponseList.add("Operation successful with no errors");
1378 opBuilder.setResponse(errorResponseList);
1379 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1385 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1388 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1390 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1391 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1392 Uuid inputVpnId = input.getId();
1393 List<VpnInstance> vpns = new ArrayList<>();
1394 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1397 if (inputVpnId == null) {
1399 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1401 Optional<VpnInstances> optionalVpns =
1402 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1404 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1405 for (VpnInstance vpn : requireNonNullElse(optionalVpns.get().getVpnInstance(),
1406 Collections.<VpnInstance>emptyList())) {
1407 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1408 // from getL3VPN output
1409 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1412 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1418 opBuilder.setL3vpnInstances(l3vpnList);
1419 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1423 String name = inputVpnId.getValue();
1424 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1425 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1426 // read VpnInstance Info
1427 Optional<VpnInstance> optionalVpn =
1428 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1430 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1432 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1433 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1434 vpns.add(optionalVpn.get());
1437 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1438 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1442 for (VpnInstance vpnInstance : vpns) {
1443 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1444 // create VpnMaps id
1445 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1446 List<String> rd = Collections.EMPTY_LIST;
1447 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1448 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1449 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1450 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1452 List<String> ertList = new ArrayList<>();
1453 List<String> irtList = new ArrayList<>();
1455 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1456 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1457 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1458 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1459 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1460 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1461 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1463 if (!vpnTargetList.isEmpty()) {
1464 for (VpnTarget vpnTarget : vpnTargetList) {
1465 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1466 ertList.add(vpnTarget.getVrfRTValue());
1468 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1469 irtList.add(vpnTarget.getVrfRTValue());
1471 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1472 ertList.add(vpnTarget.getVrfRTValue());
1473 irtList.add(vpnTarget.getVrfRTValue());
1479 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1481 if (vpnInstance.getL3vni() != null) {
1482 l3vpn.setL3vni(vpnInstance.getL3vni());
1484 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1485 .class, new VpnMapKey(vpnId)).build();
1486 Optional<VpnMap> optionalVpnMap =
1487 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1489 if (optionalVpnMap.isPresent()) {
1490 VpnMap vpnMap = optionalVpnMap.get();
1491 List<Uuid> rtrIds = new ArrayList<>();
1492 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1493 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1494 rtrIds.add(rtrId.getRouterId());
1497 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1498 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1499 .setName(vpnMap.getName());
1502 l3vpnList.add(l3vpn.build());
1505 opBuilder.setL3vpnInstances(l3vpnList);
1506 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1508 } catch (ReadFailedException ex) {
1509 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1510 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1516 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1519 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1521 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1522 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1523 List<RpcError> errorList = new ArrayList<>();
1525 int failurecount = 0;
1526 int warningcount = 0;
1527 List<Uuid> vpns = requireNonNullElse(input.getId(), Collections.emptyList());
1528 for (Uuid vpn : vpns) {
1530 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1531 InstanceIdentifier<VpnInstance> vpnIdentifier =
1532 InstanceIdentifier.builder(VpnInstances.class)
1533 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1534 Optional<VpnInstance> optionalVpn =
1535 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1537 if (optionalVpn.isPresent()) {
1540 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1541 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1544 } catch (ReadFailedException ex) {
1545 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1546 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1551 // if at least one succeeds; result is success
1552 // if none succeeds; result is failure
1553 if (failurecount + warningcount == vpns.size()) {
1554 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1556 List<String> errorResponseList = new ArrayList<>();
1557 if (!errorList.isEmpty()) {
1558 for (RpcError rpcError : errorList) {
1559 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1560 + ", ErrorMessage: " + rpcError.getMessage());
1563 errorResponseList.add("Operation successful with no errors");
1565 opBuilder.setResponse(errorResponseList);
1566 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1571 public void createVpnInstanceForSubnet(Uuid subnetId) {
1572 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1573 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1576 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1577 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1578 removeVpn(subnetId);
1581 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1582 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1583 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1584 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1586 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1587 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1590 if (vpnId != null) {
1591 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1592 if (vpnMap == null) {
1593 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1594 + " cannot add subnet {} to VPN", vpnId.getValue(),
1598 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1599 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1600 if (isVpnOfTypeL2(vpnInstance)) {
1601 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1602 NeutronEvpnUtils.Operation.ADD);
1605 if (internetVpnId != null) {
1606 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1607 if (vpnMap == null) {
1608 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1609 + "subnet {} to VPN", internetVpnId.getValue(),
1614 final Uuid internetId = internetVpnId;
1615 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1616 List<Uuid> portList = sn.getPortList();
1617 if (portList != null) {
1618 for (final Uuid portId : portList) {
1619 String vpnInfName = portId.getValue();
1620 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1621 Port port = neutronvpnUtils.getNeutronPort(portId);
1623 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1624 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1627 final Boolean isRouterInterface = port.getDeviceOwner()
1628 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1629 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1630 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1631 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1633 if (vpnIface == null) {
1634 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1635 Set<Uuid> listVpn = new HashSet<>();
1636 if (vpnId != null) {
1639 if (internetId != null) {
1640 listVpn.add(internetId);
1642 writeVpnInterfaceToDs(listVpn,
1643 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1644 if (sn.getRouterId() != null) {
1645 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1648 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1649 if (vpnId != null) {
1650 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1652 if (internetId != null) {
1653 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1662 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1663 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1664 "removeSubnetFromVpn: at least one VPN must be not null");
1665 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1666 vpnId, internetVpnId);
1667 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1669 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1672 VpnMap vpnMap = null;
1673 VpnInstance vpnInstance = null;
1674 if (vpnId != null) {
1675 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1676 if (vpnMap == null) {
1677 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1678 vpnId.getValue(), subnet.getValue());
1681 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1683 if (internetVpnId == null) {
1684 internetVpnId = sn.getInternetVpnId();
1686 if (internetVpnId != null) {
1687 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1688 if (vpnMap == null) {
1689 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1690 + " from Internet VPN",
1691 internetVpnId.getValue(), subnet.getValue());
1695 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1696 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1697 NeutronEvpnUtils.Operation.DELETE);
1699 boolean subnetVpnAssociation = false;
1700 if (vpnId != null && sn.getVpnId() != null
1701 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1702 subnetVpnAssociation = true;
1703 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1704 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1705 subnetVpnAssociation = true;
1707 if (subnetVpnAssociation == false) {
1708 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1709 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1712 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1713 List<Uuid> portList = sn.getPortList();
1714 final Uuid internetId = internetVpnId;
1715 if (portList != null) {
1716 for (final Uuid portId : portList) {
1717 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1718 final Port port = neutronvpnUtils.getNeutronPort(portId);
1719 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1720 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1721 CONFIGURATION, tx -> {
1723 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1726 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1727 + "port is absent in Neutron config DS", portId.getValue(),
1733 //update subnet-vpn association
1734 removeFromSubnetNode(subnet, null, null, vpnId, null);
1737 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1738 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1739 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1741 Uuid internalVpnId = sm.getVpnId();
1742 if (internalVpnId == null) {
1743 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1744 sm.getId().getValue());
1747 if (isBeingAssociated) {
1748 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1750 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1753 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1754 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1755 if (isBeingAssociated) {
1756 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1757 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1759 removeInternetVpnFromVpnInterface(vpn,
1760 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1765 // Check for ports on this subnet and update association of
1766 // corresponding vpn-interfaces to internet vpn
1767 List<Uuid> portList = sm.getPortList();
1768 if (portList != null) {
1769 for (Uuid port : portList) {
1770 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1771 port.getValue(), isBeingAssociated);
1772 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1773 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1775 if (isBeingAssociated) {
1776 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1777 true, false, tx, true);
1779 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1787 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1788 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1789 oldVpnId.getValue(), newVpnId.getValue());
1790 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1791 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1792 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1793 Uuid vpnExtUuid = netIsExternal ? null
1794 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1795 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1797 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1800 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1801 * associated with internet BGP-VPN.
1803 if (vpnExtUuid != null) {
1804 /* Update V6 Internet default route match with new VPN metadata.
1805 * isBeingAssociated = true means oldVpnId is same as routerId
1806 * isBeingAssociated = false means newVpnId is same as routerId
1808 if (isBeingAssociated) {
1809 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1811 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1814 //Update Router Interface first synchronously.
1815 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1816 ListenableFuture<Void> future =
1817 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1818 tx -> updateVpnInterface(newVpnId, oldVpnId,
1819 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1820 isBeingAssociated, true, tx, false));
1821 Futures.addCallback(future, new FutureCallback<Void>() {
1823 public void onSuccess(Void result) {
1824 // Check for ports on this subnet and update association of
1825 // corresponding vpn-interfaces to external vpn
1826 List<Uuid> portList = sn.getPortList();
1827 if (portList != null) {
1828 for (Uuid port : portList) {
1829 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1830 port.getValue(), isBeingAssociated);
1831 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1832 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1833 tx -> updateVpnInterface(newVpnId, oldVpnId,
1834 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1841 public void onFailure(Throwable throwable) {
1843 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1845 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1847 }, MoreExecutors.directExecutor());
1852 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1853 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1854 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1857 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1858 synchronized (routerId.getValue().intern()) {
1859 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1861 Optional<RouterInterfaces> optRouterInterfaces =
1862 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1863 routerInterfacesId);
1864 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1865 .setInterfaceId(interfaceName).build();
1866 if (optRouterInterfaces.isPresent()) {
1867 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1868 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1871 // TODO Shouldn't we be doing something with builder and interfaces?
1872 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1873 // List<Interfaces> interfaces = new ArrayList<>();
1874 // interfaces.add(routerInterface);
1876 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1877 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1880 } catch (ReadFailedException | TransactionCommitFailedException e) {
1881 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1886 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1887 synchronized (routerId.getValue().intern()) {
1888 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1890 Optional<RouterInterfaces> optRouterInterfaces =
1891 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1892 routerInterfacesId);
1893 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1894 .setInterfaceId(interfaceName).build();
1895 if (optRouterInterfaces.isPresent()) {
1896 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1897 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1898 if (interfaces != null && interfaces.remove(routerInterface)) {
1899 if (interfaces.isEmpty()) {
1900 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1901 routerInterfacesId);
1903 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1904 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1908 } catch (ReadFailedException | TransactionCommitFailedException e) {
1909 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1915 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1916 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1917 * route will be ignored.
1919 * @param vpnName the VPN identifier
1920 * @param interVpnLinkRoutes The list of static routes
1921 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1923 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1924 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1925 for (Routes route : interVpnLinkRoutes) {
1926 String nexthop = route.getNexthop().stringValue();
1927 String destination = route.getDestination().stringValue();
1928 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1929 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1930 AddStaticRouteInput rpcInput =
1931 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1932 .setVpnInstanceName(vpnName.getValue())
1934 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1935 RpcResult<AddStaticRouteOutput> rpcResult;
1937 rpcResult = labelOuputFtr.get();
1938 if (rpcResult.isSuccessful()) {
1939 LOG.debug("Label generated for destination {} is: {}",
1940 destination, rpcResult.getResult().getLabel());
1942 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1943 destination, nexthop, rpcResult.getErrors());
1945 } catch (InterruptedException | ExecutionException e) {
1946 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1947 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1950 // Any other case is a fault.
1951 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1952 route.getDestination().stringValue(), nexthop);
1959 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1960 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1962 * @param vpnName the VPN identifier
1963 * @param interVpnLinkRoutes The list of static routes
1964 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1966 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1967 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1968 for (Routes route : interVpnLinkRoutes) {
1969 String nexthop = route.getNexthop().stringValue();
1970 String destination = route.getDestination().stringValue();
1971 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1972 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1973 RemoveStaticRouteInput rpcInput =
1974 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1975 .setVpnInstanceName(vpnName.getValue())
1978 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1979 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1981 // Any other case is a fault.
1982 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1983 route.getDestination().stringValue(), nexthop);
1990 * Returns true if the specified nexthop is the other endpoint in an
1991 * InterVpnLink, regarding one of the VPN's point of view.
1993 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1995 interVpnLink != null
1996 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1997 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1998 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1999 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2003 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2004 List<Adjacency> adjList = new ArrayList<>();
2005 Map<String, List<String>> adjMap = new HashMap<>();
2006 for (Routes route : routeList) {
2007 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2008 LOG.error("Incorrect input received for extra route. {}", route);
2010 String nextHop = route.getNexthop().stringValue();
2011 String destination = route.getDestination().stringValue();
2012 if (!nextHop.equals(fixedIp)) {
2013 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2016 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2018 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2019 if (!hops.contains(nextHop)) {
2025 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2026 final String destination = entry.getKey();
2027 final List<String> ipList = entry.getValue();
2028 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2029 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2030 .withKey(new AdjacencyKey(destination)).build();
2036 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2037 checkAlarmExtraRoutes(vpnId, routeList);
2039 for (Routes route : routeList) {
2040 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2041 LOG.error("Incorrect input received for extra route. {}", route);
2043 String nextHop = route.getNexthop().stringValue();
2044 String destination = route.getDestination().stringValue();
2045 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2047 if (infName != null) {
2048 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2049 destination, vpnId.getValue(), nextHop, infName);
2050 boolean isLockAcquired = false;
2052 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2053 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2054 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2055 .child(Adjacency.class, new AdjacencyKey(destination));
2056 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2057 LogicalDatastoreType.CONFIGURATION, path);
2058 if (existingAdjacency.isPresent()
2059 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2060 LOG.error("The route with destination {} nextHop {} is already present as"
2061 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2062 destination, nextHop, infName);
2065 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2066 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2067 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2068 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2069 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2071 } catch (TransactionCommitFailedException e) {
2072 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2073 destination, nextHop, e);
2074 } catch (ReadFailedException e) {
2075 LOG.error("Exception on reading data-store ", e);
2077 if (isLockAcquired) {
2078 interfaceLock.unlock(infName);
2082 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2083 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2090 * This method setup or down an alarm about extra route fault.
2091 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2092 * available RDs, then an alarm and an error is generated.<br>
2093 * <b>Be careful</b> the routeList could be changed.
2095 * @param vpnId the vpnId of vpn to control.
2096 * @param routeList the list of router to check, it could be modified.
2098 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2099 if (!neutronvpnAlarm.isAlarmEnabled()) {
2100 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2103 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2104 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2105 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2109 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2110 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2111 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2115 for (Routes route : routeList) {
2116 // count the number of nexthops for each same route.getDestingation().getValue()
2117 String destination = route.getDestination().stringValue();
2118 String nextHop = route.getNexthop().stringValue();
2119 List<String> nextHopList = new ArrayList<>();
2120 nextHopList.add(nextHop);
2122 for (Routes routeTmp : routeList) {
2123 String routeDest = routeTmp.getDestination().stringValue();
2124 if (!destination.equals(routeDest)) {
2127 String routeNextH = routeTmp.getNexthop().stringValue();
2128 if (nextHop.equals(routeNextH)) {
2132 nextHopList.add(routeTmp.getNexthop().stringValue());
2134 final List<String> rdList = new ArrayList<>();
2135 if (vpnInstance.getIpv4Family() != null
2136 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2137 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2143 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2144 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2145 if (rd != null && !rdList.contains(rd)) {
2150 // 1. VPN Instance Name
2151 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2154 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2155 Uuid routerUuid = routerUuidList.get(0);
2156 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2157 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2159 // 3. List of RDs associated with the VPN
2160 detailsAlarm.append(" List of RDs associated with the VPN: ");
2161 for (String s : rdList) {
2162 detailsAlarm.append(s);
2163 detailsAlarm.append(", ");
2166 // 4. Prefix in question
2167 detailsAlarm.append(" for prefix: ");
2168 detailsAlarm.append(route.getDestination().stringValue());
2170 // 5. List of NHs for the prefix
2171 detailsAlarm.append(" for nextHops: ");
2172 for (String s : nextHopList) {
2173 detailsAlarm.append(s);
2174 detailsAlarm.append(", ");
2177 if (rdList.size() < nbNextHops) {
2178 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2180 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2185 // TODO Clean up the exception handling
2186 @SuppressWarnings("checkstyle:IllegalCatch")
2187 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2188 for (Routes route : routeList) {
2189 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2190 boolean isLockAcquired = false;
2191 String nextHop = route.getNexthop().stringValue();
2192 String destination = route.getDestination().stringValue();
2193 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2195 if (infName == null) {
2196 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2197 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2198 // Proceed to remove the next extra-route
2201 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2202 destination, vpnId.getValue(), nextHop, infName);
2204 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2205 InstanceIdentifier.builder(VpnInterfaces.class)
2206 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2207 .augmentation(Adjacencies.class)
2208 .child(Adjacency.class, new AdjacencyKey(destination))
2212 // Looking for existing prefix in MDSAL database
2213 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2214 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2215 boolean updateNextHops = false;
2216 List<String> nextHopList = new ArrayList<>();
2217 if (adjacency.isPresent()) {
2218 List<String> nhListRead = adjacency.get().getNextHopIpList();
2219 if (nhListRead.size() > 1) { // ECMP case
2220 for (String nextHopRead : nhListRead) {
2221 if (nextHopRead.equals(nextHop)) {
2222 updateNextHops = true;
2224 nextHopList.add(nextHopRead);
2230 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2231 if (updateNextHops) {
2232 // An update must be done, not including the current next hop
2233 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2234 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2235 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2236 .setNextHopIpList(nextHopList)
2237 .withKey(new AdjacencyKey(destination))
2239 Adjacencies erAdjs =
2240 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2241 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2242 .addAugmentation(Adjacencies.class, erAdjs).build();
2243 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2244 vpnIfIdentifier, vpnIf);
2246 // Remove the whole route
2247 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2248 adjacencyIdentifier);
2249 LOG.trace("extra route {} deleted successfully", route);
2251 } catch (TransactionCommitFailedException | ReadFailedException e) {
2252 LOG.error("exception in deleting extra route with destination {} for interface {}",
2253 destination, infName, e);
2255 if (isLockAcquired) {
2256 interfaceLock.unlock(infName);
2260 LOG.error("Incorrect input received for extra route: {}", route);
2265 public void removeVpn(Uuid vpnId) {
2267 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2268 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2269 List<Uuid> routerUuidList = new ArrayList<>();
2270 // dissociate router
2271 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2272 for (RouterIds router : routerIdsList) {
2273 Uuid routerId = router.getRouterId();
2274 routerUuidList.add(routerId);
2275 dissociateRouterFromVpn(vpnId, routerId);
2278 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2279 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2281 // remove entire vpnMaps node
2282 deleteVpnMapsNode(vpnId);
2284 // remove vpn-instance
2285 deleteVpnInstance(vpnId);
2286 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2289 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2290 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2293 // TODO Clean up the exception handling
2294 @SuppressWarnings("checkstyle:IllegalCatch")
2295 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2296 updateVpnMaps(vpnId, null, routerId, null, null);
2297 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2298 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2299 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2300 for (Subnetmap sn : subMapList) {
2301 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2302 if (!ipVersion.isIpVersionChosen(ipVers)) {
2303 ipVersion = ipVersion.addVersion(ipVers);
2306 if (ipVersion != IpVersionChoice.UNDEFINED) {
2307 LOG.debug("associateRouterToVpn: Updating vpnInstanceOpDataEntrywith ip address family {} for VPN {} ",
2309 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2311 for (Subnetmap sn : subMapList) {
2312 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2316 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2317 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2318 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2319 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2320 for (Uuid subnet : routerSubnets) {
2321 IpVersionChoice version = NeutronvpnUtils
2322 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2323 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2324 addSubnetToVpn(vpnId, subnet, null);
2326 addSubnetToVpn(vpnId, subnet, internetVpnId);
2331 // TODO Clean up the exception handling
2332 @SuppressWarnings("checkstyle:IllegalCatch")
2333 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2335 clearFromVpnMaps(vpnId, routerId, null);
2336 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2337 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2338 for (Subnetmap sn : subMapList) {
2339 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2340 if (ipVersion.isIpVersionChosen(ipVers)) {
2341 ipVersion = ipVersion.addVersion(ipVers);
2343 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2344 routerId.getValue());
2345 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2347 if (ipVersion != IpVersionChoice.UNDEFINED) {
2348 LOG.debug("dissociateRouterFromVpn; Updating vpnInstanceOpDataEntry with ip address family {} for VPN {} ",
2350 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2356 * Parses and associates networks list with given VPN.
2358 * @param vpnId Uuid of given VPN.
2359 * @param networkList List list of network Ids (Uuid), which will be associated.
2360 * @return list of formatted strings with detailed error messages.
2363 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2364 List<String> failedNwList = new ArrayList<>();
2365 HashSet<Uuid> passedNwList = new HashSet<>();
2366 boolean isExternalNetwork = false;
2367 if (networkList.isEmpty()) {
2368 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2369 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2371 return failedNwList;
2373 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2374 if (vpnInstance == null) {
2375 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2376 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2377 + "in ConfigDS", vpnId.getValue()));
2378 return failedNwList;
2381 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2382 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2384 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2385 + "associated with", vpnId.getValue()));
2386 return failedNwList;
2388 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2389 for (Uuid nw : networkList) {
2390 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2391 if (network == null) {
2392 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2393 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2397 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2398 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2399 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2400 nw.getValue(), vpnId.getValue());
2401 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2402 nw.getValue(), vpnId.getValue()));
2405 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2406 if (networkVpnId != null) {
2407 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2408 nw.getValue(), networkVpnId.getValue());
2409 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2410 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2413 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2414 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2415 nw.getValue(), vpnId.getValue());
2416 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2417 nw.getValue(), vpnId.getValue()));
2420 if (NeutronvpnUtils.getIsExternal(network)) {
2421 isExternalNetwork = true;
2423 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2424 if (subnetmapList == null || subnetmapList.isEmpty()) {
2425 passedNwList.add(nw);
2428 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2431 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2432 for (Subnetmap subnetmap : subnetmapList) {
2433 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2434 if (!ipVersion.isIpVersionChosen(ipVers)) {
2435 ipVersion = ipVersion.addVersion(ipVers);
2438 if (ipVersion != IpVersionChoice.UNDEFINED) {
2439 LOG.debug("associateNetworksToVpn: Updating vpnInstanceOpDataEntry with ip address family {}"
2440 + " for VPN {} ", ipVersion, vpnId);
2441 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2443 for (Subnetmap subnetmap : subnetmapList) {
2444 Uuid subnetId = subnetmap.getId();
2445 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2446 if (subnetVpnId != null) {
2447 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2448 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2449 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2450 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2453 if (!NeutronvpnUtils.getIsExternal(network)) {
2454 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2456 addSubnetToVpn(vpnId, subnetId, null);
2457 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2459 passedNwList.add(nw);
2462 passedNwList.add(nw);
2464 } catch (ReadFailedException e) {
2465 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2467 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2470 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2471 if (!isExternalNetwork) {
2472 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2474 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2475 return failedNwList;
2478 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2479 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2482 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2483 if (vpnOpDataEntry == null) {
2484 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2487 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2488 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2489 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2491 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2492 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2493 updateVpnMaps(vpnId, null, null, null, extNwList);
2494 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2495 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2496 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2498 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2501 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2502 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2505 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2506 updateVpnInternetForSubnet(sm, vpnId, true);
2508 if (!ipVersion.isIpVersionChosen(ipVers)) {
2509 ipVersion = ipVersion.addVersion(ipVers);
2512 if (ipVersion != IpVersionChoice.UNDEFINED) {
2513 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2514 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2515 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2521 * Parses and disassociates networks list from given VPN.
2523 * @param vpnId Uuid of given VPN.
2524 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2525 * @return list of formatted strings with detailed error messages.
2528 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2529 List<String> failedNwList = new ArrayList<>();
2530 HashSet<Uuid> passedNwList = new HashSet<>();
2531 if (networkList.isEmpty()) {
2532 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2533 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2535 return failedNwList;
2537 for (Uuid nw : networkList) {
2538 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2539 if (networkSubnets == null) {
2540 passedNwList.add(nw);
2543 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2544 if (network == null) {
2545 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2546 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2550 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2551 if (networkVpnId == null) {
2552 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2553 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2557 if (!vpnId.equals(networkVpnId)) {
2558 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2559 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2560 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2561 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2565 if (NeutronvpnUtils.getIsExternal(network)) {
2566 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2567 passedNwList.add(nw);
2569 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2570 nw.getValue(), vpnId.getValue());
2571 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2576 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2577 for (Uuid subnet : networkSubnets) {
2578 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2579 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2580 if (!ipVersion.isIpVersionChosen(ipVers)) {
2581 ipVersion = ipVersion.addVersion(ipVers);
2583 if (!NeutronvpnUtils.getIsExternal(network)) {
2584 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2586 removeSubnetFromVpn(vpnId, subnet, null);
2587 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2588 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2590 passedNwList.add(nw);
2593 if (ipVersion != IpVersionChoice.UNDEFINED) {
2594 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstanceOpDataEntryupdate with ip address family {}"
2595 + " for VPN {}", ipVersion, vpnId);
2596 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2599 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2600 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2601 passedNwList.toString(), vpnId.getValue());
2602 return failedNwList;
2605 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2606 if (!removeExternalNetworkFromVpn(extNet)) {
2609 // check, if there is another Provider Networks associated with given VPN
2610 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2611 if (vpnNets != null) {
2612 //Remove currently disassociated network from the list
2613 vpnNets.remove(extNet.getUuid());
2614 for (Uuid netId : vpnNets) {
2615 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2616 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2617 + "{}", vpnId.getValue(), netId.getValue());
2622 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2623 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2624 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2625 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2626 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2627 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2628 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2630 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2633 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2634 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2637 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2638 updateVpnInternetForSubnet(sm, vpnId, false);
2640 if (!ipVersion.isIpVersionChosen(ipVers)) {
2641 ipVersion = ipVersion.addVersion(ipVers);
2644 if (ipVersion != IpVersionChoice.UNDEFINED) {
2645 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2646 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2648 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2654 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2657 // TODO Clean up the exception handling
2658 @SuppressWarnings("checkstyle:IllegalCatch")
2659 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2661 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2662 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2663 StringBuilder returnMsg = new StringBuilder();
2664 Uuid vpnId = input.getVpnId();
2667 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2668 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2669 input.getNetworkId().toString());
2670 List<Uuid> netIds = input.getNetworkId();
2671 if (netIds != null && !netIds.isEmpty()) {
2672 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2673 if (!failed.isEmpty()) {
2674 returnMsg.append(failed);
2678 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2680 if (returnMsg.length() != 0) {
2681 opBuilder.setResponse(
2682 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2683 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2684 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2686 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2688 } catch (Exception ex) {
2689 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2690 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2691 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2693 LOG.debug("associateNetworks returns..");
2698 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2701 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2703 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2704 LOG.debug("associateRouter {}", input);
2705 StringBuilder returnMsg = new StringBuilder();
2706 Uuid vpnId = input.getVpnId();
2707 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2708 routerIds = input.getRouterIds();
2709 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2710 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2711 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2712 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2713 .RouterIds routerId : routerIds) {
2714 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2715 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2716 if (vpnMap != null) {
2718 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2719 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2720 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2721 .append(routerId.getRouterId());
2722 } else if (extVpnId != null) {
2723 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2724 + "another VPN ").append(extVpnId.getValue());
2726 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2727 routerId.getRouterId());
2728 associateRouterToVpn(vpnId, routerId.getRouterId());
2731 returnMsg.append("router not found : ").append(routerId.getRouterId());
2734 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2736 if (returnMsg.length() != 0) {
2737 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2738 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2739 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2741 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2744 LOG.debug("associateRouter returns..");
2749 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2752 // TODO Clean up the exception handling
2753 @SuppressWarnings("checkstyle:IllegalCatch")
2754 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2755 GetFixedIPsForNeutronPortInput input) {
2756 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2757 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2758 Uuid portId = input.getPortId();
2759 StringBuilder returnMsg = new StringBuilder();
2761 List<String> fixedIPList = new ArrayList<>();
2762 Port port = neutronvpnUtils.getNeutronPort(portId);
2764 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
2765 fixedIPList.add(ip.getIpAddress().stringValue());
2768 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2770 if (returnMsg.length() != 0) {
2771 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2773 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2774 returnMsg)).build());
2776 opBuilder.setFixedIPs(fixedIPList);
2777 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2779 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2781 } catch (Exception ex) {
2782 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2783 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2784 portId.getValue(), ex.getMessage(), ex)).build());
2790 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2793 // TODO Clean up the exception handling
2794 @SuppressWarnings("checkstyle:IllegalCatch")
2795 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2797 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2798 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2800 LOG.debug("dissociateNetworks {}", input);
2801 StringBuilder returnMsg = new StringBuilder();
2802 Uuid vpnId = input.getVpnId();
2805 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2806 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2807 input.getNetworkId().toString());
2808 List<Uuid> netIds = input.getNetworkId();
2809 if (netIds != null && !netIds.isEmpty()) {
2810 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2811 if (!failed.isEmpty()) {
2812 returnMsg.append(failed);
2816 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2818 if (returnMsg.length() != 0) {
2819 opBuilder.setResponse(
2820 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2821 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2823 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2825 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2827 } catch (Exception ex) {
2828 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2829 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2830 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2832 LOG.debug("dissociateNetworks returns..");
2837 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2840 // TODO Clean up the exception handling
2841 @SuppressWarnings("checkstyle:IllegalCatch")
2842 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2844 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2846 LOG.debug("dissociateRouter {}", input);
2847 StringBuilder returnMsg = new StringBuilder();
2848 Uuid vpnId = input.getVpnId();
2849 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2850 .RouterIds> routerIdList = input.getRouterIds();
2851 String routerIdsString = "";
2852 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2853 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2854 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2855 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2856 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2857 .RouterIds routerId : routerIdList) {
2859 if (routerId != null) {
2860 routerIdsString += routerId.getRouterId() + ", ";
2861 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2863 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2864 if (routerVpnId == null) {
2865 returnMsg.append("input router ").append(routerId.getRouterId())
2866 .append(" not associated to any vpn yet");
2867 } else if (vpnId.equals(routerVpnId)) {
2868 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2870 returnMsg.append("input router ").append(routerId.getRouterId())
2871 .append(" associated to vpn ")
2872 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2875 returnMsg.append("router not found : ").append(routerId.getRouterId());
2878 if (returnMsg.length() != 0) {
2879 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2880 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2881 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2882 returnMsg)).build());
2884 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2886 } catch (Exception ex) {
2887 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2888 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2889 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2893 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2896 LOG.debug("dissociateRouter returns..");
2900 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2901 // check if the router is associated to some VPN
2902 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2903 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2904 if (vpnId != null) {
2905 // remove existing external vpn interfaces
2906 for (Uuid subnetId : routerSubnetIds) {
2907 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2909 clearFromVpnMaps(vpnId, routerId, null);
2911 // remove existing internal vpn interfaces
2912 for (Uuid subnetId : routerSubnetIds) {
2913 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2916 // delete entire vpnMaps node for internal VPN
2917 deleteVpnMapsNode(routerId);
2919 // delete vpn-instance for internal VPN
2920 deleteVpnInstance(routerId);
2923 protected Subnet getNeutronSubnet(Uuid subnetId) {
2924 return neutronvpnUtils.getNeutronSubnet(subnetId);
2928 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2929 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2931 return sn.getGatewayIp();
2937 protected Network getNeutronNetwork(Uuid networkId) {
2938 return neutronvpnUtils.getNeutronNetwork(networkId);
2941 protected Port getNeutronPort(String name) {
2942 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2945 protected Port getNeutronPort(Uuid portId) {
2946 return neutronvpnUtils.getNeutronPort(portId);
2949 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2950 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2953 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2954 return neutronvpnUtils.getNetworksForVpn(vpnId);
2958 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2960 * @return a List of String to be printed on screen
2961 * @throws ReadFailedException if there was a problem reading from the data store
2963 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2964 List<String> result = new ArrayList<>();
2965 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2967 result.add("-------------------------------------------------------------------------------------------");
2968 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2970 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2971 if (ports.isPresent() && ports.get().getPort() != null) {
2972 for (Port port : requireNonNullElse(ports.get().getPort(), Collections.<Port>emptyList())) {
2973 List<FixedIps> fixedIPs = port.getFixedIps();
2974 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2975 List<String> ipList = new ArrayList<>();
2976 for (FixedIps fixedIp : fixedIPs) {
2977 IpAddress ipAddress = fixedIp.getIpAddress();
2978 if (ipAddress.getIpv4Address() != null) {
2979 ipList.add(ipAddress.getIpv4Address().getValue());
2981 ipList.add(ipAddress.getIpv6Address().getValue());
2984 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2985 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2986 ipList.toString()));
2988 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2989 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2998 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3000 * @param vpnuuid Uuid of the VPN whose config must be shown
3001 * @return formatted output list
3002 * @throws InterruptedException if there was a thread related problem getting the data to display
3003 * @throws ExecutionException if there was any other problem getting the data to display
3005 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3006 List<String> result = new ArrayList<>();
3007 if (vpnuuid == null) {
3009 result.add("Displaying VPN config for all VPNs");
3010 result.add("To display VPN config for a particular VPN, use the following syntax");
3011 result.add(getshowVpnConfigCLIHelp());
3013 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3014 if (rpcResult.isSuccessful()) {
3016 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3018 result.add(String.format(" %-80s ", "Import-RTs"));
3020 result.add(String.format(" %-80s ", "Export-RTs"));
3022 result.add(String.format(" %-76s ", "Subnet IDs"));
3024 result.add("------------------------------------------------------------------------------------");
3026 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3027 requireNonNullElse(rpcResult.getResult().getL3vpnInstances(),
3028 Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
3029 .VpnInstance>emptyList())) {
3030 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3032 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3033 vpn.getRouteDistinguisher()));
3035 result.add(String.format(" %-80s ", vpn.getImportRT()));
3037 result.add(String.format(" %-80s ", vpn.getExportRT()));
3040 Uuid vpnid = vpn.getId();
3041 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3042 if (!subnetList.isEmpty()) {
3043 for (Uuid subnetuuid : subnetList) {
3044 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3047 result.add(String.format(" %-76s ", "\" \""));
3050 result.add("----------------------------------------");
3054 String errortag = rpcResult.getErrors().iterator().next().getTag();
3055 if (Objects.equals(errortag, "")) {
3057 result.add("No VPN has been configured yet");
3058 } else if (Objects.equals(errortag, "invalid-value")) {
3060 result.add("VPN " + vpnuuid.getValue() + " is not present");
3062 result.add("error getting VPN info : " + rpcResult.getErrors());
3063 result.add(getshowVpnConfigCLIHelp());
3069 protected void createExternalVpnInterfaces(Uuid extNetId) {
3070 if (extNetId == null) {
3071 LOG.error("createExternalVpnInterfaces: external network is null");
3075 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3076 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3077 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3081 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3082 for (String elanInterface : extElanInterfaces) {
3083 createExternalVpnInterface(extNetId, elanInterface, tx);
3085 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3088 // TODO Clean up the exception handling
3089 @SuppressWarnings("checkstyle:IllegalCatch")
3090 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3091 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3092 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3093 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3096 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3097 for (String elanInterface : extElanInterfaces) {
3098 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3099 .buildVpnInterfaceIdentifier(elanInterface);
3100 LOG.info("Removing vpn interface {}", elanInterface);
3101 tx.delete(vpnIfIdentifier);
3103 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3106 private void createExternalVpnInterface(Uuid vpnId, String infName,
3107 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3108 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3109 false /* not a router iface */, wrtConfigTxn);
3112 // TODO Clean up the exception handling
3113 @SuppressWarnings("checkstyle:IllegalCatch")
3114 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName,
3115 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3116 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3117 if (vpnIdList.isEmpty() || infName == null) {
3118 LOG.error("vpnid is empty or interface({}) is null", infName);
3121 if (wrtConfigTxn == null) {
3122 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3123 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3124 "Error writing VPN interface");
3127 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3128 for (Uuid vpnId: vpnIdList) {
3129 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3130 AssociatedSubnetType.V4AndV6Subnets);
3131 vpnIdListStruct.add(vpnInstance);
3134 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3135 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3137 .setVpnInstanceNames(vpnIdListStruct)
3138 .setRouterInterface(isRouterInterface);
3139 LOG.info("Network Id is {}", networkUuid);
3140 if (networkUuid != null) {
3141 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3142 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3143 NetworkAttributes.NetworkType networkType = (providerType != null)
3144 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3145 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3146 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3147 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3150 if (adjacencies != null) {
3151 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3153 VpnInterface vpnIf = vpnb.build();
3155 LOG.info("Creating vpn interface {}", vpnIf);
3156 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3157 } catch (Exception ex) {
3158 LOG.error("Creation of vpninterface {} failed", infName, ex);
3162 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3163 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3164 if (vpnId == null || infName == null) {
3165 LOG.error("vpn id or interface is null");
3168 if (wrtConfigTxn == null) {
3169 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3170 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3171 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3172 }), LOG, "Error updating VPN interface with adjacencies");
3176 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3177 boolean isLockAcquired = false;
3179 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3180 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3181 .syncReadOptional(dataBroker, LogicalDatastoreType
3182 .CONFIGURATION, vpnIfIdentifier);
3183 if (optionalVpnInterface.isPresent()) {
3184 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3185 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3187 if (adjacencies == null) {
3188 if (isLockAcquired) {
3189 interfaceLock.unlock(infName);
3193 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3194 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3195 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3196 optionalVpnInterface.get().getVpnInstanceNames());
3197 if (listVpnInstances.isEmpty() || !VpnHelper
3198 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3199 VpnInstanceNames vpnInstance = VpnHelper
3200 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3201 listVpnInstances.add(vpnInstance);
3202 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3205 VpnInstanceNames vpnInstance = VpnHelper
3206 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3207 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3208 listVpnInstances.add(vpnInstance);
3209 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3211 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3212 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3214 } catch (IllegalStateException | ReadFailedException ex) {
3215 LOG.error("Update of vpninterface {} failed", infName, ex);
3217 if (isLockAcquired) {
3218 interfaceLock.unlock(infName);
3223 private String getshowVpnConfigCLIHelp() {
3224 StringBuilder help = new StringBuilder("Usage:");
3225 help.append("display vpn-config [-vid/--vpnid <id>]");
3226 return help.toString();
3229 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3230 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3234 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3235 return neutronEvpnManager.createEVPN(input);
3239 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3240 return neutronEvpnManager.getEVPN(input);
3244 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3245 return neutronEvpnManager.deleteEVPN(input);
3248 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3249 Uuid extNetId = extNet.getUuid();
3250 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3251 .child(Networks.class, new NetworksKey(extNetId)).build();
3254 Optional<Networks> optionalExtNets =
3255 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3257 if (!optionalExtNets.isPresent()) {
3258 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3259 extNetId.getValue());
3262 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3263 builder.setVpnid(vpnId);
3264 Networks networks = builder.build();
3265 // Add Networks object to the ExternalNetworks list
3266 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3267 extNetId.getValue());
3268 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3271 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3272 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3273 extNetId.getValue(), ex);
3278 private boolean removeExternalNetworkFromVpn(Network extNet) {
3279 Uuid extNetId = extNet.getUuid();
3280 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3281 .child(Networks.class, new NetworksKey(extNetId)).build();
3283 Optional<Networks> optionalNets =
3284 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3286 NetworksBuilder builder = null;
3287 if (optionalNets.isPresent()) {
3288 builder = new NetworksBuilder(optionalNets.get());
3290 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3291 extNetId.getValue());
3294 builder.setVpnid(null);
3295 Networks networks = builder.build();
3296 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3297 extNetId.getValue());
3298 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3300 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3301 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3302 extNetId.getValue(), ex);
3307 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3308 Optional<String> existingVpnName = Optional.of(primaryRd);
3309 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3311 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3312 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3313 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3314 } catch (ReadFailedException e) {
3315 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3317 /*Read failed. We don't know if a VPN exists or not.
3318 * Return primaryRd to halt caller execution, to be safe.*/
3319 return existingVpnName;
3321 if (vpnInstanceOpDataOptional.isPresent()) {
3322 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3324 existingVpnName = Optional.absent();
3326 return existingVpnName;
3329 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3330 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3333 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3334 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3337 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3338 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3341 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3342 String message = tuple.getMessage();
3343 logger.accept(message);
3347 protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3348 @Nonnull Subnetmap subnetMap) {
3349 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3350 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3351 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3352 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3353 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3354 subnetMap.getId().getValue(), internetVpnId.getValue());
3358 protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3359 @Nonnull Subnetmap subnetMap) {
3360 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3361 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3364 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3365 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3366 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3367 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3368 internetVpnId.getValue(), routerId.getValue());
3369 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW