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.ReadFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
50 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
51 import org.opendaylight.genius.infra.Datastore.Configuration;
52 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
54 import org.opendaylight.genius.infra.TypedWriteTransaction;
55 import org.opendaylight.genius.mdsalutil.NwConstants;
56 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
57 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
58 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
59 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
60 import org.opendaylight.netvirt.elanmanager.api.IElanService;
61 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
62 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
63 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
64 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
65 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
66 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
67 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
179 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
180 import org.opendaylight.yangtools.yang.common.RpcError;
181 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
182 import org.opendaylight.yangtools.yang.common.RpcResult;
183 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
184 import org.slf4j.Logger;
185 import org.slf4j.LoggerFactory;
186 import org.slf4j.helpers.FormattingTuple;
187 import org.slf4j.helpers.MessageFormatter;
190 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
192 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
193 private static long LOCK_WAIT_TIME = 10L;
195 private final DataBroker dataBroker;
196 private final ManagedNewTransactionRunner txRunner;
197 private final NotificationPublishService notificationPublishService;
198 private final VpnRpcService vpnRpcService;
199 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
200 private final IElanService elanService;
201 private final NeutronvpnConfig neutronvpnConfig;
202 private final NeutronEvpnManager neutronEvpnManager;
203 private final NeutronEvpnUtils neutronEvpnUtils;
204 private final JobCoordinator jobCoordinator;
205 private final NeutronvpnUtils neutronvpnUtils;
206 private final IVpnManager vpnManager;
207 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
208 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
209 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
210 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
213 public NeutronvpnManager(
214 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
215 final VpnRpcService vpnRpcSrv, final IElanService elanService,
216 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
217 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
218 final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
219 this.dataBroker = dataBroker;
220 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
221 notificationPublishService = notiPublishService;
222 vpnRpcService = vpnRpcSrv;
223 this.elanService = elanService;
224 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
225 this.neutronvpnConfig = neutronvpnConfig;
226 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
227 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
228 this.jobCoordinator = jobCoordinator;
229 this.neutronvpnUtils = neutronvpnUtils;
230 this.vpnManager = vpnManager;
237 public void close() {
238 LOG.info("{} close", getClass().getSimpleName());
241 private void configureFeatures() {
242 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
243 Neutron.class).child(Features.class).child(
244 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
245 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
247 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
248 } catch (TransactionCommitFailedException e) {
249 LOG.warn("Error configuring feature {}", feature, e);
253 public String getOpenDaylightVniRangesConfig() {
254 return neutronvpnConfig.getOpendaylightVniRanges();
257 // TODO Clean up the exception handling
258 @SuppressWarnings("checkstyle:IllegalCatch")
259 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
260 @Nullable NetworkAttributes.NetworkType networkType, long segmentationId) {
262 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
263 synchronized (subnetId.getValue().intern()) {
264 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
265 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
266 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
267 if (sn.isPresent()) {
268 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
269 subnetId.getValue());
272 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
273 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
274 .setNetworkType(networkType).setSegmentationId(segmentationId);
275 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
276 subnetId.getValue());
277 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
278 subnetMapIdentifier, subnetmapBuilder.build());
280 } catch (TransactionCommitFailedException | ReadFailedException e) {
281 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
283 // check if there are ports to update for already created Subnetmap node
284 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
285 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
286 if (entry.getValue().getValue().equals(subnetId.getValue())) {
287 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
288 unprocessedPortsMap.remove(entry.getKey());
294 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
295 @Nullable Uuid internetvpnId) {
296 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
297 .child(Subnetmap.class, new SubnetmapKey(subnetId))
300 synchronized (subnetId.getValue().intern()) {
301 Optional<Subnetmap> sn =
302 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
304 if (!sn.isPresent()) {
305 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
308 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
309 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
310 if (routerId != null) {
311 builder.setRouterId(routerId);
314 builder.setVpnId(vpnId);
316 if (neutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
317 builder.setInternetVpnId(internetvpnId);
319 Subnetmap subnetmap = builder.build();
320 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
321 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
324 } catch (ReadFailedException | TransactionCommitFailedException e) {
325 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
330 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
331 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
332 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
333 InstanceIdentifier<Subnetmap> id =
334 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
336 synchronized (subnetId.getValue().intern()) {
337 Optional<Subnetmap> sn =
338 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
340 if (!sn.isPresent()) {
341 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
342 subnetId.getValue());
345 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
346 subnetId.getValue());
347 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
348 builder.setRouterId(routerId);
349 builder.setRouterInterfacePortId(routerInterfacePortId);
350 builder.setRouterIntfMacAddress(routerIntfMacAddress);
351 builder.setRouterInterfaceFixedIp(fixedIp);
353 builder.setVpnId(vpnId);
355 Subnetmap subnetmap = builder.build();
356 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
357 subnetId.getValue());
358 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
360 } catch (ReadFailedException | TransactionCommitFailedException e) {
361 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
362 subnetId.getValue(), e);
366 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
367 @Nullable Uuid directPortId) {
368 Subnetmap subnetmap = null;
369 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
370 new SubnetmapKey(subnetId)).build();
371 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
373 synchronized (subnetId.getValue().intern()) {
374 Optional<Subnetmap> sn =
375 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
377 if (sn.isPresent()) {
378 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
379 if (null != portId) {
380 List<Uuid> portList = builder.getPortList();
381 if (null == portList) {
382 portList = new ArrayList<>();
384 portList.add(portId);
385 builder.setPortList(portList);
386 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
387 subnetId.getValue(), portId.getValue());
389 if (null != directPortId) {
390 List<Uuid> directPortList = builder.getDirectPortList();
391 if (null == directPortList) {
392 directPortList = new ArrayList<>();
394 directPortList.add(directPortId);
395 builder.setDirectPortList(directPortList);
396 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
397 directPortId.getValue());
399 subnetmap = builder.build();
400 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
403 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
404 + "cache ", subnetId.getValue(), portId.getValue());
405 unprocessedPortsMap.put(portId, subnetId);
408 } catch (ReadFailedException | TransactionCommitFailedException e) {
409 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
414 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
415 Uuid vpnId, @Nullable Uuid portId) {
416 Subnetmap subnetmap = null;
417 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
418 .child(Subnetmap.class, new SubnetmapKey(subnetId))
421 synchronized (subnetId.getValue().intern()) {
422 Optional<Subnetmap> sn =
423 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
425 if (sn.isPresent()) {
426 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
427 if (routerId != null) {
428 builder.setRouterId(null);
430 if (networkId != null) {
431 builder.setNetworkId(null);
434 builder.setVpnId(null);
436 builder.setInternetVpnId(null);
437 if (portId != null && builder.getPortList() != null) {
438 List<Uuid> portList = builder.getPortList();
439 portList.remove(portId);
440 builder.setPortList(portList);
443 subnetmap = builder.build();
444 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
445 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
448 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
451 } catch (ReadFailedException | TransactionCommitFailedException e) {
452 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
458 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
459 @Nullable Uuid directPortId) {
460 Subnetmap subnetmap = null;
461 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
462 new SubnetmapKey(subnetId)).build();
464 synchronized (subnetId.getValue().intern()) {
465 Optional<Subnetmap> sn =
466 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
468 if (sn.isPresent()) {
469 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
470 if (null != portId && null != builder.getPortList()) {
471 List<Uuid> portList = builder.getPortList();
472 portList.remove(portId);
473 builder.setPortList(portList);
474 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
475 subnetId.getValue());
477 if (null != directPortId && null != builder.getDirectPortList()) {
478 List<Uuid> directPortList = builder.getDirectPortList();
479 directPortList.remove(directPortId);
480 builder.setDirectPortList(directPortList);
481 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
482 .getValue(), subnetId.getValue());
484 subnetmap = builder.build();
485 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
488 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
491 } catch (ReadFailedException | TransactionCommitFailedException e) {
492 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
493 subnetId.getValue(), e);
498 // TODO Clean up the exception handling
499 @SuppressWarnings("checkstyle:IllegalCatch")
500 protected void deleteSubnetMapNode(Uuid subnetId) {
501 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
502 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
503 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
505 synchronized (subnetId.getValue().intern()) {
506 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
507 subnetMapIdentifier);
509 } catch (TransactionCommitFailedException e) {
510 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
514 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
515 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
516 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
518 Optional<VpnInstance> vpnInstanceConfig =
519 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
521 if (!vpnInstanceConfig.isPresent()) {
522 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
525 VpnInstance vpnInstance = vpnInstanceConfig.get();
526 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
527 if (vpnInstance.getIpv4Family() != null) {
528 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
529 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
531 if (vpnInstance.getIpv6Family() != null) {
532 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
533 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
535 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
536 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
537 updateVpnInstanceBuilder.build());
538 } catch (ReadFailedException | TransactionCommitFailedException ex) {
539 LOG.warn("Error configuring feature ", ex);
543 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
544 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
545 String vpnName = vpnId.getValue();
546 VpnInstanceBuilder builder = null;
547 List<VpnTarget> vpnTargetList = new ArrayList<>();
548 boolean isLockAcquired = false;
549 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
550 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
552 Optional<VpnInstance> optionalVpn =
553 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
555 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
556 if (optionalVpn.isPresent()) {
557 builder = new VpnInstanceBuilder(optionalVpn.get());
558 LOG.debug("updating existing vpninstance node");
560 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
561 .setType(type).setL3vni(l3vni);
563 if (irt != null && !irt.isEmpty()) {
564 if (ert != null && !ert.isEmpty()) {
565 List<String> commonRT = new ArrayList<>(irt);
566 commonRT.retainAll(ert);
568 for (String common : commonRT) {
571 VpnTarget vpnTarget =
572 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
573 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
574 vpnTargetList.add(vpnTarget);
577 for (String importRT : irt) {
578 VpnTarget vpnTarget =
579 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
580 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
581 vpnTargetList.add(vpnTarget);
585 if (ert != null && !ert.isEmpty()) {
586 for (String exportRT : ert) {
587 VpnTarget vpnTarget =
588 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
589 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
590 vpnTargetList.add(vpnTarget);
594 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
596 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
597 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
599 if (rd != null && !rd.isEmpty()) {
600 ipv4vpnBuilder.setRouteDistinguisher(rd);
601 ipv6vpnBuilder.setRouteDistinguisher(rd);
604 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
605 builder.setIpv4Family(ipv4vpnBuilder.build());
607 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
608 builder.setIpv6Family(ipv6vpnBuilder.build());
610 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
611 builder.setIpv4Family(ipv4vpnBuilder.build());
613 VpnInstance newVpn = builder.build();
614 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
615 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
616 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
618 } catch (ReadFailedException | TransactionCommitFailedException e) {
619 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
621 if (isLockAcquired) {
622 vpnLock.unlock(vpnId);
627 private void deleteVpnMapsNode(Uuid vpnId) {
628 boolean isLockAcquired = false;
629 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
630 .child(VpnMap.class, new VpnMapKey(vpnId))
632 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
634 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
635 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
636 } catch (TransactionCommitFailedException e) {
637 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
639 if (isLockAcquired) {
640 vpnLock.unlock(vpnId);
645 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
646 @Nullable List<Uuid> networks) {
647 VpnMapBuilder builder;
648 boolean isLockAcquired = false;
649 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
650 .child(VpnMap.class, new VpnMapKey(vpnId))
653 Optional<VpnMap> optionalVpnMap =
654 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
656 if (optionalVpnMap.isPresent()) {
657 builder = new VpnMapBuilder(optionalVpnMap.get());
659 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
663 builder.setName(name);
665 if (tenantId != null) {
666 builder.setTenantId(tenantId);
668 if (router != null) {
669 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
670 List<RouterIds> rtrIds = builder.getRouterIds();
671 if (rtrIds == null) {
672 rtrIds = Collections.singletonList(vpnRouterId);
674 rtrIds.add(vpnRouterId);
676 builder.setRouterIds(rtrIds);
678 if (networks != null) {
679 List<Uuid> nwList = builder.getNetworkIds();
680 if (nwList == null) {
681 nwList = new ArrayList<>();
683 nwList.addAll(networks);
684 builder.setNetworkIds(nwList);
687 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
688 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
689 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
691 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
692 } catch (ReadFailedException | TransactionCommitFailedException e) {
693 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
695 if (isLockAcquired) {
696 vpnLock.unlock(vpnId);
701 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
702 boolean isLockAcquired = false;
703 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
704 .child(VpnMap.class, new VpnMapKey(vpnId))
706 Optional<VpnMap> optionalVpnMap;
709 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
711 } catch (ReadFailedException e) {
712 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
715 if (optionalVpnMap.isPresent()) {
716 VpnMap vpnMap = optionalVpnMap.get();
717 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
718 List<RouterIds> rtrIds = vpnMap.getRouterIds();
719 if (rtrIds == null) {
720 rtrIds = new ArrayList<>();
722 if (routerId != null) {
723 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
724 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
725 vpnMapBuilder.setRouterIds(rtrIds);
727 // remove entire node in case of internal VPN
728 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
729 LOG.debug("removing vpnMaps node: {} ", vpnId);
730 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
732 } catch (TransactionCommitFailedException e) {
733 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
735 if (isLockAcquired) {
736 vpnLock.unlock(vpnId);
740 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
741 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
742 vpnMapBuilder.setRouterIds(rtrIds);
743 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
746 if (networkIds != null) {
747 List<Uuid> vpnNw = vpnMap.getNetworkIds();
748 vpnNw.removeAll(networkIds);
749 if (vpnNw.isEmpty()) {
750 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
751 vpnMapBuilder.setNetworkIds(null);
753 vpnMapBuilder.setNetworkIds(vpnNw);
758 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
759 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
760 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
761 vpnMapBuilder.build());
762 } catch (TransactionCommitFailedException e) {
763 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
765 if (isLockAcquired) {
766 vpnLock.unlock(vpnId);
770 LOG.error("VPN : {} not found", vpnId.getValue());
772 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
775 private void deleteVpnInstance(Uuid vpnId) {
776 boolean isLockAcquired = false;
777 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
778 .child(VpnInstance.class,
779 new VpnInstanceKey(vpnId.getValue()))
782 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
783 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
784 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
785 } catch (TransactionCommitFailedException e) {
786 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
788 if (isLockAcquired) {
789 vpnLock.unlock(vpnId);
794 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
795 TypedWriteTransaction<Configuration> wrtConfigTxn,
796 @Nullable Subnetmap sn, @Nullable VpnInterface vpnIface) {
797 List<Adjacency> adjList = new ArrayList<>();
798 if (vpnIface != null) {
799 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
801 String infName = port.getUuid().getValue();
802 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
803 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
804 String ipValue = ip.getIpAddress().stringValue();
805 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
806 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
809 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
810 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
812 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
813 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
814 //Create Neutron port adjacency if VPN presence is existing for subnet
815 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
816 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
817 .setSubnetId(ip.getSubnetId()).build();
818 if (!adjList.contains(vmAdj)) {
822 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
823 if (snTemp != null && snTemp.getInternetVpnId() != null) {
824 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
825 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
827 if (routerId != null) {
828 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
829 if (rtr != null && rtr.getRoutes() != null) {
830 List<Routes> routeList = rtr.getRoutes();
831 // create extraroute Adjacence for each ipValue,
832 // because router can have IPv4 and IPv6 subnet ports, or can have
833 // more that one IPv4 subnet port or more than one IPv6 subnet port
834 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
835 if (!erAdjList.isEmpty()) {
836 adjList.addAll(erAdjList);
841 return new AdjacenciesBuilder().setAdjacency(adjList).build();
844 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
845 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
846 boolean isRouterInterface = false;
847 if (port.getDeviceOwner() != null) {
848 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
850 String infName = port.getUuid().getValue();
851 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
852 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
853 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, vpnIface);
854 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
855 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
858 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
859 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
860 String infName = port.getUuid().getValue();
861 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
862 Optional<VpnInterface> optionalVpnInterface = null;
863 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
864 vpnId, internetVpnId, infName);
866 optionalVpnInterface = SingleTransactionDataBroker
867 .syncReadOptional(dataBroker, LogicalDatastoreType
868 .CONFIGURATION, vpnIfIdentifier);
869 } catch (ReadFailedException e) {
870 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
873 if (!optionalVpnInterface.isPresent()) {
876 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
877 sn != null ? sn.getSubnetIp() : "null");
878 List<Adjacency> vpnAdjsList =
879 requireNonNullElse(optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency(),
880 Collections.emptyList());
881 List<Adjacency> updatedAdjsList = new ArrayList<>();
882 boolean isIpFromAnotherSubnet = false;
883 for (Adjacency adj : vpnAdjsList) {
884 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
885 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
886 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
887 isIpFromAnotherSubnet = true;
889 updatedAdjsList.add(adj);
892 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
893 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
896 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
897 String.valueOf(adjString), wrtConfigTxn);
899 if (internetVpnId != null) {
900 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
901 String.valueOf(adjString), wrtConfigTxn);
904 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
905 && sn.getRouterId() != null) {
906 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
907 if (rtr != null && rtr.getRoutes() != null) {
908 List<Routes> extraRoutesToRemove = new ArrayList<>();
909 for (Routes rt: rtr.getRoutes()) {
910 if (rt.getNexthop().toString().equals(adjString)) {
911 extraRoutesToRemove.add(rt);
915 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
916 extraRoutesToRemove, vpnId);
917 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
919 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
924 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
926 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
928 if (!isIpFromAnotherSubnet) {
929 // no more subnetworks for neutron port
930 if (sn != null && sn.getRouterId() != null) {
931 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
933 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
939 // TODO Clean up the exception handling
940 @SuppressWarnings("checkstyle:IllegalCatch")
941 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
942 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
943 if (wrtConfigTxn == null) {
944 ListenableFutures.addErrorLogging(
945 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
946 tx -> deleteVpnInterface(infName, vpnId, tx)),
947 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
951 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
952 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
953 Optional<VpnInterface> optionalVpnInterface;
955 optionalVpnInterface =
956 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
958 } catch (ReadFailedException ex) {
959 LOG.error("Error during deletion of vpninterface {}", infName, ex);
962 if (!optionalVpnInterface.isPresent()) {
963 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
967 VpnInterface vpnInterface = optionalVpnInterface.get();
968 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
970 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
971 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
972 if (!vpnList.isEmpty()) {
973 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
974 + "List not empty", infName);
977 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
978 .setVpnInstanceNames(vpnList);
979 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
983 LOG.debug("Deleting vpn interface {}", infName);
984 wrtConfigTxn.delete(vpnIfIdentifier);
987 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
988 TypedWriteTransaction<Configuration> writeConfigTxn,
990 if (vpnId == null || port == null) {
993 String infName = port.getUuid().getValue();
994 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
996 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
997 .syncReadOptional(dataBroker, LogicalDatastoreType
998 .CONFIGURATION, vpnIfIdentifier);
999 if (optionalVpnInterface.isPresent()) {
1000 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1002 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1003 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1005 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1006 .setVpnInstanceNames(listVpn);
1007 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1008 LOG.debug("Updating vpn interface {}", infName);
1009 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1010 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1011 while (adjacencyIter.hasNext()) {
1012 Adjacency adjacency = adjacencyIter.next();
1013 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1016 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1017 InstanceIdentifier<LearntVpnVipToPort> id =
1018 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1019 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1020 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1021 LogicalDatastoreType.OPERATIONAL, id);
1022 if (optionalVpnVipToPort.isPresent()) {
1023 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1025 if (listVpn == null || listVpn.isEmpty()) {
1026 adjacencyIter.remove();
1028 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1029 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1030 mipToQuery, infName, vpnId.getValue());
1033 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1034 String ipValue = ip.getIpAddress().stringValue();
1036 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1039 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1040 ipValue, writeConfigTxn);
1042 if (listVpn == null || listVpn.isEmpty()) {
1043 if (sm != null && sm.getRouterId() != null) {
1044 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1046 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1048 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1051 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1053 } catch (ReadFailedException ex) {
1054 LOG.error("Update of vpninterface {} failed", infName, ex);
1058 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1060 TypedWriteTransaction<Configuration> writeConfigTxn,
1061 boolean isInternetVpn) {
1062 if (vpnId == null || port == null) {
1065 boolean isLockAcquired = false;
1066 String infName = port.getUuid().getValue();
1067 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1070 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1071 Optional<VpnInterface> optionalVpnInterface =
1072 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1074 if (optionalVpnInterface.isPresent()) {
1075 VpnInstanceNames vpnInstance = VpnHelper
1076 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1077 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1078 .get().getVpnInstanceNames());
1079 if (oldVpnId != null
1080 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1081 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1083 if (vpnId.getValue() != null
1084 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1085 listVpn.add(vpnInstance);
1087 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1088 .setVpnInstanceNames(listVpn);
1089 LOG.debug("Updating vpn interface {}", infName);
1090 if (!isBeingAssociated) {
1091 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1092 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1093 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1094 while (adjacencyIter.hasNext()) {
1095 Adjacency adjacency = adjacencyIter.next();
1096 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1097 InstanceIdentifier<LearntVpnVipToPort> id =
1098 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1099 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1100 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1101 LogicalDatastoreType.OPERATIONAL, id);
1102 if (optionalVpnVipToPort.isPresent()) {
1103 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1104 + "from VPN {}", infName, vpnId, oldVpnId);
1105 adjacencyIter.remove();
1106 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1108 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1109 mipToQuery, infName, vpnId.getValue());
1112 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1113 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1115 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1116 String ipValue = ip.getIpAddress().stringValue();
1117 if (oldVpnId != null) {
1118 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1119 ipValue, writeConfigTxn);
1121 if ((NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6)
1122 && (isInternetVpn == true)) {
1126 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1127 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1129 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1131 LOG.error("VPN Interface {} not found", infName);
1133 } catch (ReadFailedException ex) {
1134 LOG.error("Updation of vpninterface {} failed", infName, ex);
1136 if (isLockAcquired) {
1137 interfaceLock.unlock(infName);
1142 public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List<String> rd,
1143 @Nullable List<String> irt, @Nullable List<String> ert, @Nullable Uuid router,
1144 @Nullable List<Uuid> networks) {
1146 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1148 // Update VPN Instance node
1149 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1151 // Update local vpn-subnet DS
1152 updateVpnMaps(vpn, name, router, tenant, networks);
1154 if (router != null) {
1155 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1156 if (existingVpn != null) {
1157 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1158 // if before reboot, router was already associated to VPN, should not proceed associating router to
1159 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1160 // preserved upon reboot.
1161 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1162 // RouterInterfacesMap via #createVPNInterface call.
1163 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1164 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1167 associateRouterToInternalVpn(vpn, router);
1172 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1173 * specified Neutron Networks and Routers.
1175 * @param vpnId Uuid of the VPN tp be created
1176 * @param name Representative name of the new VPN
1177 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1178 * @param rdList Route-distinguisher for the VPN
1179 * @param irtList A list of Import Route Targets
1180 * @param ertList A list of Export Route Targets
1181 * @param routerIdsList ist of neutron router Id to associate with created VPN
1182 * @param networkList UUID of the neutron network the VPN may be associated to
1183 * @param type Type of the VPN Instance
1184 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1185 * @throws Exception if association of L3VPN failed
1187 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1188 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1189 VpnInstance.Type type, long l3vni) throws Exception {
1191 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1193 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1194 for (Uuid routerId : routerIdsList) {
1195 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1196 ipVersChoices = ipVersChoices.addVersion(vers);
1199 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1201 // Please note that router and networks will be filled into VPNMaps
1202 // by subsequent calls here to associateRouterToVpn and
1203 // associateNetworksToVpn
1204 updateVpnMaps(vpnId, name, null, tenantId, null);
1205 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1206 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1209 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1210 for (Uuid routerId : routerIdsList) {
1211 associateRouterToVpn(vpnId, routerId);
1214 if (networkList != null) {
1215 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1216 if (!failStrings.isEmpty()) {
1217 LOG.error("VPN {} association to networks failed for networks: {}. ",
1218 vpnId.getValue(), failStrings.toString());
1219 throw new Exception(failStrings.toString());
1225 * It handles the invocations to the createVPN RPC method.
1228 // TODO Clean up the exception handling
1229 @SuppressWarnings("checkstyle:IllegalCatch")
1230 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1232 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1233 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1234 List<RpcError> errorList = new ArrayList<>();
1235 int failurecount = 0;
1236 int warningcount = 0;
1238 List<L3vpn> vpns = input.getL3vpn();
1240 vpns = Collections.emptyList();
1242 for (L3vpn vpn : vpns) {
1243 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1244 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1245 formatAndLog(LOG::warn,
1246 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1247 vpn.getId().getValue())));
1251 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1252 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1253 formatAndLog(LOG::warn,
1254 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1255 vpn.getId().getValue())));
1259 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1261 if (vpn.getL3vni() != null) {
1262 l3vni = vpn.getL3vni();
1265 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1266 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1267 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1268 formatAndLog(LOG::warn,
1269 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1270 + "is already configured",
1271 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1275 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1276 if (operationalVpn.isPresent()) {
1277 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1278 formatAndLog(LOG::error,
1279 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1280 + "is still available. Please retry creation of a new vpn with the same RD"
1281 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1282 vpn.getRouteDistinguisher().get(0))));
1286 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1287 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1288 routerIdsList = vpn.getRouterIds();
1289 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1290 routerId : routerIdsList) {
1291 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1292 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1293 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1294 + "{}", vpn.getId(), routerId.getRouterId())));
1298 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1299 if (vpnId != null) {
1300 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1301 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1302 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1303 vpnId.getValue())));
1309 if (vpn.getNetworkIds() != null) {
1310 int initialWarningCount = warningcount;
1311 for (Uuid nw : vpn.getNetworkIds()) {
1312 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1313 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1314 if (network == null) {
1315 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1316 formatAndLog(LOG::warn,
1317 "Creation of L3VPN failed for VPN {} due to network not found {}",
1318 vpn.getId().getValue(), nw.getValue())));
1320 } else if (vpnId != null) {
1321 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1322 formatAndLog(LOG::warn,
1323 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1324 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1325 vpnId.getValue())));
1329 if (warningcount != initialWarningCount) {
1333 List<Uuid> rtrIdsList = new ArrayList<>();
1334 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1335 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1336 rtrId : vpn.getRouterIds()) {
1337 rtrIdsList.add(rtrId.getRouterId());
1341 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1342 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1343 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1344 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1345 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1346 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1347 vpnInstanceType, l3vni);
1348 } catch (Exception ex) {
1349 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1350 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1355 // if at least one succeeds; result is success
1356 // if none succeeds; result is failure
1357 if (failurecount + warningcount == vpns.size()) {
1358 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1360 List<String> errorResponseList = new ArrayList<>();
1361 if (!errorList.isEmpty()) {
1362 for (RpcError rpcError : errorList) {
1363 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1364 + ", ErrorMessage: " + rpcError.getMessage());
1367 errorResponseList.add("Operation successful with no errors");
1369 opBuilder.setResponse(errorResponseList);
1370 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1376 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1379 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1381 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1382 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1383 Uuid inputVpnId = input.getId();
1384 List<VpnInstance> vpns = new ArrayList<>();
1385 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1388 if (inputVpnId == null) {
1390 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1392 Optional<VpnInstances> optionalVpns =
1393 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1395 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1396 for (VpnInstance vpn : requireNonNullElse(optionalVpns.get().getVpnInstance(),
1397 Collections.<VpnInstance>emptyList())) {
1398 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1399 // from getL3VPN output
1400 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1403 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1409 opBuilder.setL3vpnInstances(l3vpnList);
1410 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1414 String name = inputVpnId.getValue();
1415 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1416 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1417 // read VpnInstance Info
1418 Optional<VpnInstance> optionalVpn =
1419 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1421 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1423 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1424 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1425 vpns.add(optionalVpn.get());
1428 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1429 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1433 for (VpnInstance vpnInstance : vpns) {
1434 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1435 // create VpnMaps id
1436 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1437 List<String> rd = Collections.EMPTY_LIST;
1438 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1439 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1440 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1441 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1443 List<String> ertList = new ArrayList<>();
1444 List<String> irtList = new ArrayList<>();
1446 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1447 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1448 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1449 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1450 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1451 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1452 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1454 if (!vpnTargetList.isEmpty()) {
1455 for (VpnTarget vpnTarget : vpnTargetList) {
1456 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1457 ertList.add(vpnTarget.getVrfRTValue());
1459 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1460 irtList.add(vpnTarget.getVrfRTValue());
1462 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1463 ertList.add(vpnTarget.getVrfRTValue());
1464 irtList.add(vpnTarget.getVrfRTValue());
1470 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1472 if (vpnInstance.getL3vni() != null) {
1473 l3vpn.setL3vni(vpnInstance.getL3vni());
1475 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1476 .class, new VpnMapKey(vpnId)).build();
1477 Optional<VpnMap> optionalVpnMap =
1478 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1480 if (optionalVpnMap.isPresent()) {
1481 VpnMap vpnMap = optionalVpnMap.get();
1482 List<Uuid> rtrIds = new ArrayList<>();
1483 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1484 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1485 rtrIds.add(rtrId.getRouterId());
1488 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1489 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1490 .setName(vpnMap.getName());
1493 l3vpnList.add(l3vpn.build());
1496 opBuilder.setL3vpnInstances(l3vpnList);
1497 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1499 } catch (ReadFailedException ex) {
1500 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1501 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1507 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1510 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1512 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1513 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1514 List<RpcError> errorList = new ArrayList<>();
1516 int failurecount = 0;
1517 int warningcount = 0;
1518 List<Uuid> vpns = requireNonNullElse(input.getId(), Collections.emptyList());
1519 for (Uuid vpn : vpns) {
1521 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1522 InstanceIdentifier<VpnInstance> vpnIdentifier =
1523 InstanceIdentifier.builder(VpnInstances.class)
1524 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1525 Optional<VpnInstance> optionalVpn =
1526 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1528 if (optionalVpn.isPresent()) {
1531 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1532 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1535 } catch (ReadFailedException ex) {
1536 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1537 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1542 // if at least one succeeds; result is success
1543 // if none succeeds; result is failure
1544 if (failurecount + warningcount == vpns.size()) {
1545 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1547 List<String> errorResponseList = new ArrayList<>();
1548 if (!errorList.isEmpty()) {
1549 for (RpcError rpcError : errorList) {
1550 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1551 + ", ErrorMessage: " + rpcError.getMessage());
1554 errorResponseList.add("Operation successful with no errors");
1556 opBuilder.setResponse(errorResponseList);
1557 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1562 public void createVpnInstanceForSubnet(Uuid subnetId) {
1563 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1564 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1567 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1568 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1569 removeVpn(subnetId);
1572 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1573 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1574 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1575 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1577 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1578 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1581 if (vpnId != null) {
1582 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1583 if (vpnMap == null) {
1584 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1585 + " cannot add subnet {} to VPN", vpnId.getValue(),
1589 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1590 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1591 if (isVpnOfTypeL2(vpnInstance)) {
1592 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1593 NeutronEvpnUtils.Operation.ADD);
1596 if (internetVpnId != null) {
1597 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1598 if (vpnMap == null) {
1599 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1600 + "subnet {} to VPN", internetVpnId.getValue(),
1605 final Uuid internetId = internetVpnId;
1606 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1607 List<Uuid> portList = sn.getPortList();
1608 if (portList != null) {
1609 for (final Uuid portId : portList) {
1610 String vpnInfName = portId.getValue();
1611 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1612 Port port = neutronvpnUtils.getNeutronPort(portId);
1614 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1615 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1618 final Boolean isRouterInterface = port.getDeviceOwner()
1619 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1620 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1621 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1622 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1624 if (vpnIface == null) {
1625 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1626 Set<Uuid> listVpn = new HashSet<>();
1627 if (vpnId != null) {
1630 if (internetId != null) {
1631 listVpn.add(internetId);
1633 writeVpnInterfaceToDs(listVpn,
1634 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1635 if (sn.getRouterId() != null) {
1636 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1639 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1640 if (vpnId != null) {
1641 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1643 if (internetId != null) {
1644 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1653 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1654 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1655 "removeSubnetFromVpn: at least one VPN must be not null");
1656 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1657 vpnId, internetVpnId);
1658 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1660 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1663 VpnMap vpnMap = null;
1664 VpnInstance vpnInstance = null;
1665 if (vpnId != null) {
1666 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1667 if (vpnMap == null) {
1668 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1669 vpnId.getValue(), subnet.getValue());
1672 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1674 if (internetVpnId == null) {
1675 internetVpnId = sn.getInternetVpnId();
1677 if (internetVpnId != null) {
1678 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1679 if (vpnMap == null) {
1680 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1681 + " from Internet VPN",
1682 internetVpnId.getValue(), subnet.getValue());
1686 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1687 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1688 NeutronEvpnUtils.Operation.DELETE);
1690 boolean subnetVpnAssociation = false;
1691 if (vpnId != null && sn.getVpnId() != null
1692 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1693 subnetVpnAssociation = true;
1694 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1695 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1696 subnetVpnAssociation = true;
1698 if (subnetVpnAssociation == false) {
1699 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1700 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1703 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1704 List<Uuid> portList = sn.getPortList();
1705 final Uuid internetId = internetVpnId;
1706 if (portList != null) {
1707 for (final Uuid portId : portList) {
1708 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1709 final Port port = neutronvpnUtils.getNeutronPort(portId);
1710 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1711 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1712 CONFIGURATION, tx -> {
1714 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1717 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1718 + "port is absent in Neutron config DS", portId.getValue(),
1724 //update subnet-vpn association
1725 removeFromSubnetNode(subnet, null, null, vpnId, null);
1728 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1729 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1730 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1732 Uuid internalVpnId = sm.getVpnId();
1733 if (internalVpnId == null) {
1734 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1735 sm.getId().getValue());
1738 if (isBeingAssociated) {
1739 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1741 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1744 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1745 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1746 if (isBeingAssociated) {
1747 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1748 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1750 removeInternetVpnFromVpnInterface(vpn,
1751 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1756 // Check for ports on this subnet and update association of
1757 // corresponding vpn-interfaces to internet vpn
1758 List<Uuid> portList = sm.getPortList();
1759 if (portList != null) {
1760 for (Uuid port : portList) {
1761 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1762 port.getValue(), isBeingAssociated);
1763 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1764 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1766 if (isBeingAssociated) {
1767 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1768 true, false, tx, true);
1770 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1778 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1779 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1780 oldVpnId.getValue(), newVpnId.getValue());
1781 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1782 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1783 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1784 Uuid vpnExtUuid = netIsExternal ? null
1785 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1786 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1788 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1791 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1792 * associated with internet BGP-VPN.
1794 if (vpnExtUuid != null) {
1795 /* Update V6 Internet default route match with new VPN metadata.
1796 * isBeingAssociated = true means oldVpnId is same as routerId
1797 * isBeingAssociated = false means newVpnId is same as routerId
1799 if (isBeingAssociated) {
1800 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1802 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1805 //Update Router Interface first synchronously.
1806 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1807 ListenableFuture<Void> future =
1808 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1809 tx -> updateVpnInterface(newVpnId, oldVpnId,
1810 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1811 isBeingAssociated, true, tx, false));
1812 Futures.addCallback(future, new FutureCallback<Void>() {
1814 public void onSuccess(Void result) {
1815 // Check for ports on this subnet and update association of
1816 // corresponding vpn-interfaces to external vpn
1817 List<Uuid> portList = sn.getPortList();
1818 if (portList != null) {
1819 for (Uuid port : portList) {
1820 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1821 port.getValue(), isBeingAssociated);
1822 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1823 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1824 tx -> updateVpnInterface(newVpnId, oldVpnId,
1825 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1832 public void onFailure(Throwable throwable) {
1834 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1836 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1838 }, MoreExecutors.directExecutor());
1843 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1844 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1845 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1848 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1849 synchronized (routerId.getValue().intern()) {
1850 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1852 Optional<RouterInterfaces> optRouterInterfaces =
1853 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1854 routerInterfacesId);
1855 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1856 .setInterfaceId(interfaceName).build();
1857 if (optRouterInterfaces.isPresent()) {
1858 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1859 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1862 // TODO Shouldn't we be doing something with builder and interfaces?
1863 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1864 // List<Interfaces> interfaces = new ArrayList<>();
1865 // interfaces.add(routerInterface);
1867 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1868 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1871 } catch (ReadFailedException | TransactionCommitFailedException e) {
1872 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1877 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1878 synchronized (routerId.getValue().intern()) {
1879 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1881 Optional<RouterInterfaces> optRouterInterfaces =
1882 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1883 routerInterfacesId);
1884 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1885 .setInterfaceId(interfaceName).build();
1886 if (optRouterInterfaces.isPresent()) {
1887 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1888 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1889 if (interfaces != null && interfaces.remove(routerInterface)) {
1890 if (interfaces.isEmpty()) {
1891 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1892 routerInterfacesId);
1894 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1895 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1899 } catch (ReadFailedException | TransactionCommitFailedException e) {
1900 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1906 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1907 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1908 * route will be ignored.
1910 * @param vpnName the VPN identifier
1911 * @param interVpnLinkRoutes The list of static routes
1912 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1914 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1915 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1916 for (Routes route : interVpnLinkRoutes) {
1917 String nexthop = route.getNexthop().stringValue();
1918 String destination = route.getDestination().stringValue();
1919 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1920 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1921 AddStaticRouteInput rpcInput =
1922 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1923 .setVpnInstanceName(vpnName.getValue())
1925 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1926 RpcResult<AddStaticRouteOutput> rpcResult;
1928 rpcResult = labelOuputFtr.get();
1929 if (rpcResult.isSuccessful()) {
1930 LOG.debug("Label generated for destination {} is: {}",
1931 destination, rpcResult.getResult().getLabel());
1933 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1934 destination, nexthop, rpcResult.getErrors());
1936 } catch (InterruptedException | ExecutionException e) {
1937 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1938 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1941 // Any other case is a fault.
1942 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1943 route.getDestination().stringValue(), nexthop);
1950 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1951 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1953 * @param vpnName the VPN identifier
1954 * @param interVpnLinkRoutes The list of static routes
1955 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1957 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1958 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1959 for (Routes route : interVpnLinkRoutes) {
1960 String nexthop = route.getNexthop().stringValue();
1961 String destination = route.getDestination().stringValue();
1962 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1963 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1964 RemoveStaticRouteInput rpcInput =
1965 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1966 .setVpnInstanceName(vpnName.getValue())
1969 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1970 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1972 // Any other case is a fault.
1973 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1974 route.getDestination().stringValue(), nexthop);
1981 * Returns true if the specified nexthop is the other endpoint in an
1982 * InterVpnLink, regarding one of the VPN's point of view.
1984 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1986 interVpnLink != null
1987 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1988 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1989 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1990 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1994 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
1995 List<Adjacency> adjList = new ArrayList<>();
1996 Map<String, List<String>> adjMap = new HashMap<>();
1997 for (Routes route : routeList) {
1998 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1999 LOG.error("Incorrect input received for extra route. {}", route);
2001 String nextHop = route.getNexthop().stringValue();
2002 String destination = route.getDestination().stringValue();
2003 if (!nextHop.equals(fixedIp)) {
2004 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2007 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2009 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2010 if (!hops.contains(nextHop)) {
2016 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2017 final String destination = entry.getKey();
2018 final List<String> ipList = entry.getValue();
2019 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2020 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2021 .withKey(new AdjacencyKey(destination)).build();
2027 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2028 checkAlarmExtraRoutes(vpnId, routeList);
2030 for (Routes route : routeList) {
2031 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2032 LOG.error("Incorrect input received for extra route. {}", route);
2034 String nextHop = route.getNexthop().stringValue();
2035 String destination = route.getDestination().stringValue();
2036 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2038 if (infName != null) {
2039 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2040 destination, vpnId.getValue(), nextHop, infName);
2041 boolean isLockAcquired = false;
2043 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2044 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2045 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2046 .child(Adjacency.class, new AdjacencyKey(destination));
2047 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2048 LogicalDatastoreType.CONFIGURATION, path);
2049 if (existingAdjacency.isPresent()
2050 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2051 LOG.error("The route with destination {} nextHop {} is already present as"
2052 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2053 destination, nextHop, infName);
2056 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2057 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2058 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2059 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2060 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2062 } catch (TransactionCommitFailedException e) {
2063 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2064 destination, nextHop, e);
2065 } catch (ReadFailedException e) {
2066 LOG.error("Exception on reading data-store ", e);
2068 if (isLockAcquired) {
2069 interfaceLock.unlock(infName);
2073 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2074 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2081 * This method setup or down an alarm about extra route fault.
2082 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2083 * available RDs, then an alarm and an error is generated.<br>
2084 * <b>Be careful</b> the routeList could be changed.
2086 * @param vpnId the vpnId of vpn to control.
2087 * @param routeList the list of router to check, it could be modified.
2089 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2090 if (!neutronvpnAlarm.isAlarmEnabled()) {
2091 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2094 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2095 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2096 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2100 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2101 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2102 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2106 for (Routes route : routeList) {
2107 // count the number of nexthops for each same route.getDestingation().getValue()
2108 String destination = route.getDestination().stringValue();
2109 String nextHop = route.getNexthop().stringValue();
2110 List<String> nextHopList = new ArrayList<>();
2111 nextHopList.add(nextHop);
2113 for (Routes routeTmp : routeList) {
2114 String routeDest = routeTmp.getDestination().stringValue();
2115 if (!destination.equals(routeDest)) {
2118 String routeNextH = routeTmp.getNexthop().stringValue();
2119 if (nextHop.equals(routeNextH)) {
2123 nextHopList.add(routeTmp.getNexthop().stringValue());
2125 final List<String> rdList = new ArrayList<>();
2126 if (vpnInstance.getIpv4Family() != null
2127 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2128 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2134 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2135 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2136 if (rd != null && !rdList.contains(rd)) {
2141 // 1. VPN Instance Name
2142 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2145 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2146 Uuid routerUuid = routerUuidList.get(0);
2147 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2148 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2150 // 3. List of RDs associated with the VPN
2151 detailsAlarm.append(" List of RDs associated with the VPN: ");
2152 for (String s : rdList) {
2153 detailsAlarm.append(s);
2154 detailsAlarm.append(", ");
2157 // 4. Prefix in question
2158 detailsAlarm.append(" for prefix: ");
2159 detailsAlarm.append(route.getDestination().stringValue());
2161 // 5. List of NHs for the prefix
2162 detailsAlarm.append(" for nextHops: ");
2163 for (String s : nextHopList) {
2164 detailsAlarm.append(s);
2165 detailsAlarm.append(", ");
2168 if (rdList.size() < nbNextHops) {
2169 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2171 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2176 // TODO Clean up the exception handling
2177 @SuppressWarnings("checkstyle:IllegalCatch")
2178 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2179 for (Routes route : routeList) {
2180 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2181 boolean isLockAcquired = false;
2182 String nextHop = route.getNexthop().stringValue();
2183 String destination = route.getDestination().stringValue();
2184 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2186 if (infName == null) {
2187 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2188 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2189 // Proceed to remove the next extra-route
2192 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2193 destination, vpnId.getValue(), nextHop, infName);
2195 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2196 InstanceIdentifier.builder(VpnInterfaces.class)
2197 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2198 .augmentation(Adjacencies.class)
2199 .child(Adjacency.class, new AdjacencyKey(destination))
2203 // Looking for existing prefix in MDSAL database
2204 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2205 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2206 boolean updateNextHops = false;
2207 List<String> nextHopList = new ArrayList<>();
2208 if (adjacency.isPresent()) {
2209 List<String> nhListRead = adjacency.get().getNextHopIpList();
2210 if (nhListRead.size() > 1) { // ECMP case
2211 for (String nextHopRead : nhListRead) {
2212 if (nextHopRead.equals(nextHop)) {
2213 updateNextHops = true;
2215 nextHopList.add(nextHopRead);
2221 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2222 if (updateNextHops) {
2223 // An update must be done, not including the current next hop
2224 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2225 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2226 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2227 .setNextHopIpList(nextHopList)
2228 .withKey(new AdjacencyKey(destination))
2230 Adjacencies erAdjs =
2231 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2232 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2233 .addAugmentation(Adjacencies.class, erAdjs).build();
2234 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2235 vpnIfIdentifier, vpnIf);
2237 // Remove the whole route
2238 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2239 adjacencyIdentifier);
2240 LOG.trace("extra route {} deleted successfully", route);
2242 } catch (TransactionCommitFailedException | ReadFailedException e) {
2243 LOG.error("exception in deleting extra route with destination {} for interface {}",
2244 destination, infName, e);
2246 if (isLockAcquired) {
2247 interfaceLock.unlock(infName);
2251 LOG.error("Incorrect input received for extra route: {}", route);
2256 public void removeVpn(Uuid vpnId) {
2258 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2259 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2260 List<Uuid> routerUuidList = new ArrayList<>();
2261 // dissociate router
2262 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2263 for (RouterIds router : routerIdsList) {
2264 Uuid routerId = router.getRouterId();
2265 routerUuidList.add(routerId);
2266 dissociateRouterFromVpn(vpnId, routerId);
2269 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2270 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2272 // remove entire vpnMaps node
2273 deleteVpnMapsNode(vpnId);
2275 // remove vpn-instance
2276 deleteVpnInstance(vpnId);
2277 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2280 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2281 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2284 // TODO Clean up the exception handling
2285 @SuppressWarnings("checkstyle:IllegalCatch")
2286 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2287 updateVpnMaps(vpnId, null, routerId, null, null);
2288 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2289 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2290 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2291 for (Subnetmap sn : subMapList) {
2292 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2293 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2294 if (!ipVersion.isIpVersionChosen(ipVers)) {
2295 ipVersion = ipVersion.addVersion(ipVers);
2298 if (ipVersion != IpVersionChoice.UNDEFINED) {
2299 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", ipVersion,
2301 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2305 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2306 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2308 } catch (Exception e) {
2309 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2310 .getValue(), vpnId.getValue(), e);
2314 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2315 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2316 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2317 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2318 for (Uuid subnet : routerSubnets) {
2319 IpVersionChoice version = NeutronvpnUtils
2320 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2321 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2322 addSubnetToVpn(vpnId, subnet, null);
2324 addSubnetToVpn(vpnId, subnet, internetVpnId);
2329 // TODO Clean up the exception handling
2330 @SuppressWarnings("checkstyle:IllegalCatch")
2331 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2333 clearFromVpnMaps(vpnId, routerId, null);
2334 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2335 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2336 for (Subnetmap sn : subMapList) {
2337 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2338 if (ipVersion.isIpVersionChosen(ipVers)) {
2339 ipVersion = ipVersion.addVersion(ipVers);
2341 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2342 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2344 if (ipVersion != IpVersionChoice.UNDEFINED) {
2345 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2347 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2351 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2352 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2354 } catch (Exception e) {
2355 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2356 .getValue(), vpnId.getValue(), e);
2361 * Parses and associates networks list with given VPN.
2363 * @param vpnId Uuid of given VPN.
2364 * @param networkList List list of network Ids (Uuid), which will be associated.
2365 * @return list of formatted strings with detailed error messages.
2368 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2369 List<String> failedNwList = new ArrayList<>();
2370 HashSet<Uuid> passedNwList = new HashSet<>();
2371 boolean isExternalNetwork = false;
2372 if (networkList.isEmpty()) {
2373 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2374 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2376 return failedNwList;
2378 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2379 if (vpnInstance == null) {
2380 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2381 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2382 + "in ConfigDS", vpnId.getValue()));
2383 return failedNwList;
2386 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2387 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2389 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2390 + "associated with", vpnId.getValue()));
2391 return failedNwList;
2393 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2394 for (Uuid nw : networkList) {
2395 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2396 if (network == null) {
2397 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2398 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2402 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2403 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2404 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2405 nw.getValue(), vpnId.getValue());
2406 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2407 nw.getValue(), vpnId.getValue()));
2410 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2411 if (networkVpnId != null) {
2412 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2413 nw.getValue(), networkVpnId.getValue());
2414 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2415 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2418 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2419 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2420 nw.getValue(), vpnId.getValue());
2421 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2422 nw.getValue(), vpnId.getValue()));
2425 if (NeutronvpnUtils.getIsExternal(network)) {
2426 isExternalNetwork = true;
2428 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2429 if (subnetmapList == null || subnetmapList.isEmpty()) {
2430 passedNwList.add(nw);
2433 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2436 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2437 for (Subnetmap subnetmap : subnetmapList) {
2438 Uuid subnetId = subnetmap.getId();
2439 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2440 if (subnetVpnId != null) {
2441 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2442 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2443 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2444 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2447 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2448 if (!ipVersion.isIpVersionChosen(ipVers)) {
2449 ipVersion = ipVersion.addVersion(ipVers);
2451 if (!NeutronvpnUtils.getIsExternal(network)) {
2452 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2454 addSubnetToVpn(vpnId, subnetId, null);
2455 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2457 passedNwList.add(nw);
2460 if (ipVersion != IpVersionChoice.UNDEFINED) {
2461 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2463 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2465 passedNwList.add(nw);
2467 } catch (ReadFailedException e) {
2468 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2470 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2473 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2474 if (!isExternalNetwork) {
2475 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2477 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2478 return failedNwList;
2481 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2482 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2485 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2486 if (vpnOpDataEntry == null) {
2487 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2490 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2491 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2492 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2494 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2495 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2496 updateVpnMaps(vpnId, null, null, null, extNwList);
2497 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2498 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2499 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2501 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2504 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2505 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2508 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2509 updateVpnInternetForSubnet(sm, vpnId, true);
2511 if (!ipVersion.isIpVersionChosen(ipVers)) {
2512 ipVersion = ipVersion.addVersion(ipVers);
2515 if (ipVersion != IpVersionChoice.UNDEFINED) {
2516 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2517 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2518 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2524 * Parses and disassociates networks list from given VPN.
2526 * @param vpnId Uuid of given VPN.
2527 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2528 * @return list of formatted strings with detailed error messages.
2531 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2532 List<String> failedNwList = new ArrayList<>();
2533 HashSet<Uuid> passedNwList = new HashSet<>();
2534 if (networkList.isEmpty()) {
2535 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2536 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2538 return failedNwList;
2540 for (Uuid nw : networkList) {
2541 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2542 if (networkSubnets == null) {
2543 passedNwList.add(nw);
2546 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2547 if (network == null) {
2548 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2549 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2553 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2554 if (networkVpnId == null) {
2555 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2556 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2560 if (!vpnId.equals(networkVpnId)) {
2561 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2562 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2563 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2564 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2568 if (NeutronvpnUtils.getIsExternal(network)) {
2569 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2570 passedNwList.add(nw);
2572 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2573 nw.getValue(), vpnId.getValue());
2574 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2579 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2580 for (Uuid subnet : networkSubnets) {
2581 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2582 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2583 if (!ipVersion.isIpVersionChosen(ipVers)) {
2584 ipVersion = ipVersion.addVersion(ipVers);
2586 if (!NeutronvpnUtils.getIsExternal(network)) {
2587 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2589 removeSubnetFromVpn(vpnId, subnet, null);
2590 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2591 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2593 passedNwList.add(nw);
2596 if (ipVersion != IpVersionChoice.UNDEFINED) {
2597 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
2599 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2602 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2603 LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
2605 return failedNwList;
2608 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2609 if (!removeExternalNetworkFromVpn(extNet)) {
2612 // check, if there is another Provider Networks associated with given VPN
2613 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2614 if (vpnNets != null) {
2615 //Remove currently disassociated network from the list
2616 vpnNets.remove(extNet.getUuid());
2617 for (Uuid netId : vpnNets) {
2618 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2619 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2620 + "{}", vpnId.getValue(), netId.getValue());
2625 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2626 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2627 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2628 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2629 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2630 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2631 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2633 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2636 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2637 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2640 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2641 updateVpnInternetForSubnet(sm, vpnId, false);
2643 if (!ipVersion.isIpVersionChosen(ipVers)) {
2644 ipVersion = ipVersion.addVersion(ipVers);
2647 if (ipVersion != IpVersionChoice.UNDEFINED) {
2648 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2649 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2651 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2657 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2660 // TODO Clean up the exception handling
2661 @SuppressWarnings("checkstyle:IllegalCatch")
2662 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2664 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2665 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2666 StringBuilder returnMsg = new StringBuilder();
2667 Uuid vpnId = input.getVpnId();
2670 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2671 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2672 input.getNetworkId().toString());
2673 List<Uuid> netIds = input.getNetworkId();
2674 if (netIds != null && !netIds.isEmpty()) {
2675 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2676 if (!failed.isEmpty()) {
2677 returnMsg.append(failed);
2681 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2683 if (returnMsg.length() != 0) {
2684 opBuilder.setResponse(
2685 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2686 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2687 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2689 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2691 } catch (Exception ex) {
2692 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2693 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2694 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2696 LOG.debug("associateNetworks returns..");
2701 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2704 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2706 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2707 LOG.debug("associateRouter {}", input);
2708 StringBuilder returnMsg = new StringBuilder();
2709 Uuid vpnId = input.getVpnId();
2710 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2711 routerIds = input.getRouterIds();
2712 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2713 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2714 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2715 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2716 .RouterIds routerId : routerIds) {
2717 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2718 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2719 if (vpnMap != null) {
2721 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2722 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2723 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2724 .append(routerId.getRouterId());
2725 } else if (extVpnId != null) {
2726 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2727 + "another VPN ").append(extVpnId.getValue());
2729 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2730 routerId.getRouterId());
2731 associateRouterToVpn(vpnId, routerId.getRouterId());
2734 returnMsg.append("router not found : ").append(routerId.getRouterId());
2737 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2739 if (returnMsg.length() != 0) {
2740 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2741 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2742 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2744 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2747 LOG.debug("associateRouter returns..");
2752 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2755 // TODO Clean up the exception handling
2756 @SuppressWarnings("checkstyle:IllegalCatch")
2757 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2758 GetFixedIPsForNeutronPortInput input) {
2759 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2760 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2761 Uuid portId = input.getPortId();
2762 StringBuilder returnMsg = new StringBuilder();
2764 List<String> fixedIPList = new ArrayList<>();
2765 Port port = neutronvpnUtils.getNeutronPort(portId);
2767 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
2768 fixedIPList.add(ip.getIpAddress().stringValue());
2771 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2773 if (returnMsg.length() != 0) {
2774 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2776 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2777 returnMsg)).build());
2779 opBuilder.setFixedIPs(fixedIPList);
2780 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2782 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2784 } catch (Exception ex) {
2785 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2786 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2787 portId.getValue(), ex.getMessage(), ex)).build());
2793 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2796 // TODO Clean up the exception handling
2797 @SuppressWarnings("checkstyle:IllegalCatch")
2798 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2800 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2801 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2803 LOG.debug("dissociateNetworks {}", input);
2804 StringBuilder returnMsg = new StringBuilder();
2805 Uuid vpnId = input.getVpnId();
2808 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2809 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2810 input.getNetworkId().toString());
2811 List<Uuid> netIds = input.getNetworkId();
2812 if (netIds != null && !netIds.isEmpty()) {
2813 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2814 if (!failed.isEmpty()) {
2815 returnMsg.append(failed);
2819 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2821 if (returnMsg.length() != 0) {
2822 opBuilder.setResponse(
2823 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2824 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2826 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2828 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2830 } catch (Exception ex) {
2831 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2832 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2833 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2835 LOG.debug("dissociateNetworks returns..");
2840 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2843 // TODO Clean up the exception handling
2844 @SuppressWarnings("checkstyle:IllegalCatch")
2845 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2847 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2849 LOG.debug("dissociateRouter {}", input);
2850 StringBuilder returnMsg = new StringBuilder();
2851 Uuid vpnId = input.getVpnId();
2852 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2853 .RouterIds> routerIdList = input.getRouterIds();
2854 String routerIdsString = "";
2855 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2856 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2857 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2858 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2859 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2860 .RouterIds routerId : routerIdList) {
2862 if (routerId != null) {
2863 routerIdsString += routerId.getRouterId() + ", ";
2864 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2866 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2867 if (routerVpnId == null) {
2868 returnMsg.append("input router ").append(routerId.getRouterId())
2869 .append(" not associated to any vpn yet");
2870 } else if (vpnId.equals(routerVpnId)) {
2871 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2873 returnMsg.append("input router ").append(routerId.getRouterId())
2874 .append(" associated to vpn ")
2875 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2878 returnMsg.append("router not found : ").append(routerId.getRouterId());
2881 if (returnMsg.length() != 0) {
2882 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2883 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2884 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2885 returnMsg)).build());
2887 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2889 } catch (Exception ex) {
2890 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2891 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2892 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2896 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2899 LOG.debug("dissociateRouter returns..");
2903 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2904 // check if the router is associated to some VPN
2905 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2906 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2907 if (vpnId != null) {
2908 // remove existing external vpn interfaces
2909 for (Uuid subnetId : routerSubnetIds) {
2910 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2912 clearFromVpnMaps(vpnId, routerId, null);
2914 // remove existing internal vpn interfaces
2915 for (Uuid subnetId : routerSubnetIds) {
2916 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2919 // delete entire vpnMaps node for internal VPN
2920 deleteVpnMapsNode(routerId);
2922 // delete vpn-instance for internal VPN
2923 deleteVpnInstance(routerId);
2926 protected Subnet getNeutronSubnet(Uuid subnetId) {
2927 return neutronvpnUtils.getNeutronSubnet(subnetId);
2931 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2932 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2934 return sn.getGatewayIp();
2940 protected Network getNeutronNetwork(Uuid networkId) {
2941 return neutronvpnUtils.getNeutronNetwork(networkId);
2944 protected Port getNeutronPort(String name) {
2945 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2948 protected Port getNeutronPort(Uuid portId) {
2949 return neutronvpnUtils.getNeutronPort(portId);
2952 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2953 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2956 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2957 return neutronvpnUtils.getNetworksForVpn(vpnId);
2961 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2963 * @return a List of String to be printed on screen
2964 * @throws ReadFailedException if there was a problem reading from the data store
2966 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2967 List<String> result = new ArrayList<>();
2968 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2970 result.add("-------------------------------------------------------------------------------------------");
2971 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2973 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2974 if (ports.isPresent() && ports.get().getPort() != null) {
2975 for (Port port : requireNonNullElse(ports.get().getPort(), Collections.<Port>emptyList())) {
2976 List<FixedIps> fixedIPs = port.getFixedIps();
2977 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2978 List<String> ipList = new ArrayList<>();
2979 for (FixedIps fixedIp : fixedIPs) {
2980 IpAddress ipAddress = fixedIp.getIpAddress();
2981 if (ipAddress.getIpv4Address() != null) {
2982 ipList.add(ipAddress.getIpv4Address().getValue());
2984 ipList.add(ipAddress.getIpv6Address().getValue());
2987 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2988 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2989 ipList.toString()));
2991 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2992 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3001 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3003 * @param vpnuuid Uuid of the VPN whose config must be shown
3004 * @return formatted output list
3005 * @throws InterruptedException if there was a thread related problem getting the data to display
3006 * @throws ExecutionException if there was any other problem getting the data to display
3008 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3009 List<String> result = new ArrayList<>();
3010 if (vpnuuid == null) {
3012 result.add("Displaying VPN config for all VPNs");
3013 result.add("To display VPN config for a particular VPN, use the following syntax");
3014 result.add(getshowVpnConfigCLIHelp());
3016 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3017 if (rpcResult.isSuccessful()) {
3019 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3021 result.add(String.format(" %-80s ", "Import-RTs"));
3023 result.add(String.format(" %-80s ", "Export-RTs"));
3025 result.add(String.format(" %-76s ", "Subnet IDs"));
3027 result.add("------------------------------------------------------------------------------------");
3029 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3030 requireNonNullElse(rpcResult.getResult().getL3vpnInstances(),
3031 Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
3032 .VpnInstance>emptyList())) {
3033 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3035 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3036 vpn.getRouteDistinguisher()));
3038 result.add(String.format(" %-80s ", vpn.getImportRT()));
3040 result.add(String.format(" %-80s ", vpn.getExportRT()));
3043 Uuid vpnid = vpn.getId();
3044 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3045 if (!subnetList.isEmpty()) {
3046 for (Uuid subnetuuid : subnetList) {
3047 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3050 result.add(String.format(" %-76s ", "\" \""));
3053 result.add("----------------------------------------");
3057 String errortag = rpcResult.getErrors().iterator().next().getTag();
3058 if (Objects.equals(errortag, "")) {
3060 result.add("No VPN has been configured yet");
3061 } else if (Objects.equals(errortag, "invalid-value")) {
3063 result.add("VPN " + vpnuuid.getValue() + " is not present");
3065 result.add("error getting VPN info : " + rpcResult.getErrors());
3066 result.add(getshowVpnConfigCLIHelp());
3072 protected void createExternalVpnInterfaces(Uuid extNetId) {
3073 if (extNetId == null) {
3074 LOG.error("createExternalVpnInterfaces: external network is null");
3078 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3079 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3080 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3084 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3085 for (String elanInterface : extElanInterfaces) {
3086 createExternalVpnInterface(extNetId, elanInterface, tx);
3088 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3091 // TODO Clean up the exception handling
3092 @SuppressWarnings("checkstyle:IllegalCatch")
3093 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3094 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3095 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3096 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3099 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3100 for (String elanInterface : extElanInterfaces) {
3101 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3102 .buildVpnInterfaceIdentifier(elanInterface);
3103 LOG.info("Removing vpn interface {}", elanInterface);
3104 tx.delete(vpnIfIdentifier);
3106 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3109 private void createExternalVpnInterface(Uuid vpnId, String infName,
3110 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3111 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3112 false /* not a router iface */, wrtConfigTxn);
3115 // TODO Clean up the exception handling
3116 @SuppressWarnings("checkstyle:IllegalCatch")
3117 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName,
3118 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3119 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3120 if (vpnIdList.isEmpty() || infName == null) {
3121 LOG.error("vpnid is empty or interface({}) is null", infName);
3124 if (wrtConfigTxn == null) {
3125 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3126 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3127 "Error writing VPN interface");
3130 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3131 for (Uuid vpnId: vpnIdList) {
3132 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3133 AssociatedSubnetType.V4AndV6Subnets);
3134 vpnIdListStruct.add(vpnInstance);
3137 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3138 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3140 .setVpnInstanceNames(vpnIdListStruct)
3141 .setRouterInterface(isRouterInterface);
3142 LOG.info("Network Id is {}", networkUuid);
3143 if (networkUuid != null) {
3144 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3145 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3146 NetworkAttributes.NetworkType networkType = (providerType != null)
3147 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3148 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3149 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3150 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3153 if (adjacencies != null) {
3154 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3156 VpnInterface vpnIf = vpnb.build();
3158 LOG.info("Creating vpn interface {}", vpnIf);
3159 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3160 } catch (Exception ex) {
3161 LOG.error("Creation of vpninterface {} failed", infName, ex);
3165 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3166 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3167 if (vpnId == null || infName == null) {
3168 LOG.error("vpn id or interface is null");
3171 if (wrtConfigTxn == null) {
3172 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3173 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3174 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3175 }), LOG, "Error updating VPN interface with adjacencies");
3179 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3180 boolean isLockAcquired = false;
3182 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3183 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3184 .syncReadOptional(dataBroker, LogicalDatastoreType
3185 .CONFIGURATION, vpnIfIdentifier);
3186 if (optionalVpnInterface.isPresent()) {
3187 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3188 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3190 if (adjacencies == null) {
3191 if (isLockAcquired) {
3192 interfaceLock.unlock(infName);
3196 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3197 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3198 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3199 optionalVpnInterface.get().getVpnInstanceNames());
3200 if (listVpnInstances.isEmpty() || !VpnHelper
3201 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3202 VpnInstanceNames vpnInstance = VpnHelper
3203 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3204 listVpnInstances.add(vpnInstance);
3205 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3208 VpnInstanceNames vpnInstance = VpnHelper
3209 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3210 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3211 listVpnInstances.add(vpnInstance);
3212 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3214 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3215 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3217 } catch (IllegalStateException | ReadFailedException ex) {
3218 LOG.error("Update of vpninterface {} failed", infName, ex);
3220 if (isLockAcquired) {
3221 interfaceLock.unlock(infName);
3226 private String getshowVpnConfigCLIHelp() {
3227 StringBuilder help = new StringBuilder("Usage:");
3228 help.append("display vpn-config [-vid/--vpnid <id>]");
3229 return help.toString();
3232 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3233 InterruptedException {
3234 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3235 .setVpnId(vpnId).build();
3236 LOG.info("publishing notification upon association of router to VPN");
3237 notificationPublishService.putNotification(routerAssociatedToVpn);
3240 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3241 InterruptedException {
3242 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3243 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3244 LOG.info("publishing notification upon disassociation of router from VPN");
3245 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3248 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3249 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3253 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3254 return neutronEvpnManager.createEVPN(input);
3258 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3259 return neutronEvpnManager.getEVPN(input);
3263 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3264 return neutronEvpnManager.deleteEVPN(input);
3267 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3268 Uuid extNetId = extNet.getUuid();
3269 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3270 .child(Networks.class, new NetworksKey(extNetId)).build();
3273 Optional<Networks> optionalExtNets =
3274 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3276 if (!optionalExtNets.isPresent()) {
3277 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3278 extNetId.getValue());
3281 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3282 builder.setVpnid(vpnId);
3283 Networks networks = builder.build();
3284 // Add Networks object to the ExternalNetworks list
3285 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3286 extNetId.getValue());
3287 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3290 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3291 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3292 extNetId.getValue(), ex);
3297 private boolean removeExternalNetworkFromVpn(Network extNet) {
3298 Uuid extNetId = extNet.getUuid();
3299 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3300 .child(Networks.class, new NetworksKey(extNetId)).build();
3302 Optional<Networks> optionalNets =
3303 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3305 NetworksBuilder builder = null;
3306 if (optionalNets.isPresent()) {
3307 builder = new NetworksBuilder(optionalNets.get());
3309 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3310 extNetId.getValue());
3313 builder.setVpnid(null);
3314 Networks networks = builder.build();
3315 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3316 extNetId.getValue());
3317 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3319 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3320 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3321 extNetId.getValue(), ex);
3326 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3327 Optional<String> existingVpnName = Optional.of(primaryRd);
3328 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3330 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3331 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3332 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3333 } catch (ReadFailedException e) {
3334 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3336 /*Read failed. We don't know if a VPN exists or not.
3337 * Return primaryRd to halt caller execution, to be safe.*/
3338 return existingVpnName;
3340 if (vpnInstanceOpDataOptional.isPresent()) {
3341 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3343 existingVpnName = Optional.absent();
3345 return existingVpnName;
3348 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3349 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3352 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3353 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3356 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3357 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3360 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3361 String message = tuple.getMessage();
3362 logger.accept(message);
3366 protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3367 @Nonnull Subnetmap subnetMap) {
3368 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3369 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3370 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3371 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3372 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3373 subnetMap.getId().getValue(), internetVpnId.getValue());
3377 protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3378 @Nonnull Subnetmap subnetMap) {
3379 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3380 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3383 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3384 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3385 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3386 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3387 internetVpnId.getValue(), routerId.getValue());
3388 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW