2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.JdkFutureAdapters;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.ExecutionException;
36 import java.util.concurrent.Future;
37 import java.util.concurrent.TimeUnit;
38 import java.util.function.Consumer;
39 import javax.annotation.Nonnull;
40 import javax.annotation.Nullable;
41 import javax.annotation.PreDestroy;
42 import javax.inject.Inject;
43 import javax.inject.Singleton;
44 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
45 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
46 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
47 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
48 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
49 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
50 import org.opendaylight.genius.infra.Datastore;
51 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
52 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
53 import org.opendaylight.genius.infra.TypedWriteTransaction;
54 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
55 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
56 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
57 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
58 import org.opendaylight.netvirt.elanmanager.api.IElanService;
59 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
60 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
61 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
62 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
63 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
64 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
65 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
177 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
178 import org.opendaylight.yangtools.yang.common.RpcError;
179 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
180 import org.opendaylight.yangtools.yang.common.RpcResult;
181 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
182 import org.slf4j.Logger;
183 import org.slf4j.LoggerFactory;
184 import org.slf4j.helpers.FormattingTuple;
185 import org.slf4j.helpers.MessageFormatter;
188 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
190 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
191 private static long LOCK_WAIT_TIME = 10L;
193 private final DataBroker dataBroker;
194 private final ManagedNewTransactionRunner txRunner;
195 private final NotificationPublishService notificationPublishService;
196 private final VpnRpcService vpnRpcService;
197 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
198 private final IElanService elanService;
199 private final NeutronvpnConfig neutronvpnConfig;
200 private final NeutronEvpnManager neutronEvpnManager;
201 private final NeutronEvpnUtils neutronEvpnUtils;
202 private final JobCoordinator jobCoordinator;
203 private final NeutronvpnUtils neutronvpnUtils;
204 private final IVpnManager vpnManager;
205 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
206 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
207 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
208 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
211 public NeutronvpnManager(
212 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
213 final VpnRpcService vpnRpcSrv, final IElanService elanService,
214 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
215 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
216 final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
217 this.dataBroker = dataBroker;
218 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
219 notificationPublishService = notiPublishService;
220 vpnRpcService = vpnRpcSrv;
221 this.elanService = elanService;
222 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
223 this.neutronvpnConfig = neutronvpnConfig;
224 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
225 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
226 this.jobCoordinator = jobCoordinator;
227 this.neutronvpnUtils = neutronvpnUtils;
228 this.vpnManager = vpnManager;
235 public void close() {
236 LOG.info("{} close", getClass().getSimpleName());
239 private void configureFeatures() {
240 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
241 Neutron.class).child(Features.class).child(
242 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
243 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
245 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
246 } catch (TransactionCommitFailedException e) {
247 LOG.warn("Error configuring feature {}", feature, e);
251 public String getOpenDaylightVniRangesConfig() {
252 return neutronvpnConfig.getOpendaylightVniRanges();
255 // TODO Clean up the exception handling
256 @SuppressWarnings("checkstyle:IllegalCatch")
257 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
258 NetworkAttributes.NetworkType networkType, long segmentationId) {
260 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
261 synchronized (subnetId.getValue().intern()) {
262 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
263 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
264 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
265 if (sn.isPresent()) {
266 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
267 subnetId.getValue());
270 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
271 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
272 .setNetworkType(networkType).setSegmentationId(segmentationId);
273 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
274 subnetId.getValue());
275 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
276 subnetMapIdentifier, subnetmapBuilder.build());
278 } catch (TransactionCommitFailedException | ReadFailedException e) {
279 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
281 // check if there are ports to update for already created Subnetmap node
282 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
283 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
284 if (entry.getValue().getValue().equals(subnetId.getValue())) {
285 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
286 unprocessedPortsMap.remove(entry.getKey());
291 protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) {
292 Subnetmap subnetmap = null;
293 SubnetmapBuilder builder = null;
294 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
295 .child(Subnetmap.class, new SubnetmapKey(subnetId))
298 synchronized (subnetId.getValue().intern()) {
299 Optional<Subnetmap> sn =
300 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
302 if (sn.isPresent()) {
303 builder = new SubnetmapBuilder(sn.get());
304 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
306 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
309 if (routerId != null) {
310 builder.setRouterId(routerId);
313 builder.setVpnId(vpnId);
315 builder.setInternetVpnId(internetvpnId);
317 subnetmap = builder.build();
318 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
319 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
321 } catch (ReadFailedException | TransactionCommitFailedException e) {
322 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
327 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
328 Uuid routerInterfacePortId, String fixedIp,
329 String routerIntfMacAddress, Uuid vpnId) {
330 Subnetmap subnetmap = null;
331 SubnetmapBuilder builder = null;
332 InstanceIdentifier<Subnetmap> id =
333 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
335 synchronized (subnetId.getValue().intern()) {
336 Optional<Subnetmap> sn =
337 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
339 if (sn.isPresent()) {
340 builder = new SubnetmapBuilder(sn.get());
341 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
342 subnetId.getValue());
344 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
345 subnetId.getValue());
348 builder.setRouterId(routerId);
349 builder.setRouterInterfacePortId(routerInterfacePortId);
350 builder.setRouterIntfMacAddress(routerIntfMacAddress);
351 builder.setRouterInterfaceFixedIp(fixedIp);
353 builder.setVpnId(vpnId);
355 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, Uuid portId, Uuid directPortId) {
367 Subnetmap subnetmap = null;
368 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
369 new SubnetmapKey(subnetId)).build();
370 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
372 synchronized (subnetId.getValue().intern()) {
373 Optional<Subnetmap> sn =
374 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
376 if (sn.isPresent()) {
377 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
378 if (null != portId) {
379 List<Uuid> portList = builder.getPortList();
380 if (null == portList) {
381 portList = new ArrayList<>();
383 portList.add(portId);
384 builder.setPortList(portList);
385 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
386 subnetId.getValue(), portId.getValue());
388 if (null != directPortId) {
389 List<Uuid> directPortList = builder.getDirectPortList();
390 if (null == directPortList) {
391 directPortList = new ArrayList<>();
393 directPortList.add(directPortId);
394 builder.setDirectPortList(directPortList);
395 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
396 directPortId.getValue());
398 subnetmap = builder.build();
399 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
402 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
403 + "cache ", subnetId.getValue(), portId.getValue());
404 unprocessedPortsMap.put(portId, subnetId);
407 } catch (ReadFailedException | TransactionCommitFailedException e) {
408 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
413 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId,
414 Uuid vpnId, Uuid portId) {
415 Subnetmap subnetmap = null;
416 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
417 .child(Subnetmap.class, new SubnetmapKey(subnetId))
420 synchronized (subnetId.getValue().intern()) {
421 Optional<Subnetmap> sn =
422 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
424 if (sn.isPresent()) {
425 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
426 if (routerId != null) {
427 builder.setRouterId(null);
429 if (networkId != null) {
430 builder.setNetworkId(null);
433 builder.setVpnId(null);
435 builder.setInternetVpnId(null);
436 if (portId != null && builder.getPortList() != null) {
437 List<Uuid> portList = builder.getPortList();
438 portList.remove(portId);
439 builder.setPortList(portList);
442 subnetmap = builder.build();
443 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
444 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
447 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
450 } catch (ReadFailedException | TransactionCommitFailedException e) {
451 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
456 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
457 Subnetmap subnetmap = null;
458 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
459 new SubnetmapKey(subnetId)).build();
461 synchronized (subnetId.getValue().intern()) {
462 Optional<Subnetmap> sn =
463 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
465 if (sn.isPresent()) {
466 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
467 if (null != portId && null != builder.getPortList()) {
468 List<Uuid> portList = builder.getPortList();
469 portList.remove(portId);
470 builder.setPortList(portList);
471 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
472 subnetId.getValue());
474 if (null != directPortId && null != builder.getDirectPortList()) {
475 List<Uuid> directPortList = builder.getDirectPortList();
476 directPortList.remove(directPortId);
477 builder.setDirectPortList(directPortList);
478 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
479 .getValue(), subnetId.getValue());
481 subnetmap = builder.build();
482 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
485 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
488 } catch (ReadFailedException | TransactionCommitFailedException e) {
489 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
490 subnetId.getValue(), e);
495 // TODO Clean up the exception handling
496 @SuppressWarnings("checkstyle:IllegalCatch")
497 protected void deleteSubnetMapNode(Uuid subnetId) {
498 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
499 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
500 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
502 synchronized (subnetId.getValue().intern()) {
503 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
504 subnetMapIdentifier);
506 } catch (TransactionCommitFailedException e) {
507 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
511 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
512 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
513 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
515 Optional<VpnInstance> vpnInstanceConfig =
516 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
518 if (!vpnInstanceConfig.isPresent()) {
519 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
522 VpnInstance vpnInstance = vpnInstanceConfig.get();
523 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
524 if (vpnInstance.getIpv4Family() != null) {
525 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
526 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
528 if (vpnInstance.getIpv6Family() != null) {
529 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
530 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
532 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
533 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
534 updateVpnInstanceBuilder.build());
535 } catch (ReadFailedException | TransactionCommitFailedException ex) {
536 LOG.warn("Error configuring feature ", ex);
540 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
541 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
542 String vpnName = vpnId.getValue();
543 VpnInstanceBuilder builder = null;
544 List<VpnTarget> vpnTargetList = new ArrayList<>();
545 boolean isLockAcquired = false;
546 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
547 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
549 Optional<VpnInstance> optionalVpn =
550 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
552 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
553 if (optionalVpn.isPresent()) {
554 builder = new VpnInstanceBuilder(optionalVpn.get());
555 LOG.debug("updating existing vpninstance node");
557 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
558 .setType(type).setL3vni(l3vni);
560 if (irt != null && !irt.isEmpty()) {
561 if (ert != null && !ert.isEmpty()) {
562 List<String> commonRT = new ArrayList<>(irt);
563 commonRT.retainAll(ert);
565 for (String common : commonRT) {
568 VpnTarget vpnTarget =
569 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
570 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
571 vpnTargetList.add(vpnTarget);
574 for (String importRT : irt) {
575 VpnTarget vpnTarget =
576 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
577 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
578 vpnTargetList.add(vpnTarget);
582 if (ert != null && !ert.isEmpty()) {
583 for (String exportRT : ert) {
584 VpnTarget vpnTarget =
585 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
586 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
587 vpnTargetList.add(vpnTarget);
591 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
593 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
594 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
596 if (rd != null && !rd.isEmpty()) {
597 ipv4vpnBuilder.setRouteDistinguisher(rd);
598 ipv6vpnBuilder.setRouteDistinguisher(rd);
601 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
602 builder.setIpv4Family(ipv4vpnBuilder.build());
604 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
605 builder.setIpv6Family(ipv6vpnBuilder.build());
607 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
608 builder.setIpv4Family(ipv4vpnBuilder.build());
610 VpnInstance newVpn = builder.build();
611 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
612 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
613 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
615 } catch (ReadFailedException | TransactionCommitFailedException e) {
616 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
618 if (isLockAcquired) {
619 vpnLock.unlock(vpnId);
624 private void deleteVpnMapsNode(Uuid vpnId) {
625 boolean isLockAcquired = false;
626 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
627 .child(VpnMap.class, new VpnMapKey(vpnId))
629 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
631 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
632 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
633 } catch (TransactionCommitFailedException e) {
634 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
636 if (isLockAcquired) {
637 vpnLock.unlock(vpnId);
642 protected void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
643 VpnMapBuilder builder;
644 boolean isLockAcquired = false;
645 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
646 .child(VpnMap.class, new VpnMapKey(vpnId))
649 Optional<VpnMap> optionalVpnMap =
650 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
652 if (optionalVpnMap.isPresent()) {
653 builder = new VpnMapBuilder(optionalVpnMap.get());
655 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
659 builder.setName(name);
661 if (tenantId != null) {
662 builder.setTenantId(tenantId);
664 if (router != null) {
665 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
666 List<RouterIds> rtrIds = builder.getRouterIds();
667 if (rtrIds == null) {
668 rtrIds = Collections.singletonList(vpnRouterId);
670 rtrIds.add(vpnRouterId);
672 builder.setRouterIds(rtrIds);
674 if (networks != null) {
675 List<Uuid> nwList = builder.getNetworkIds();
676 if (nwList == null) {
677 nwList = new ArrayList<>();
679 nwList.addAll(networks);
680 builder.setNetworkIds(nwList);
683 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
684 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
685 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
687 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
688 } catch (ReadFailedException | TransactionCommitFailedException e) {
689 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
691 if (isLockAcquired) {
692 vpnLock.unlock(vpnId);
697 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
698 boolean isLockAcquired = false;
699 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
700 .child(VpnMap.class, new VpnMapKey(vpnId))
702 Optional<VpnMap> optionalVpnMap;
705 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
707 } catch (ReadFailedException e) {
708 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
711 if (optionalVpnMap.isPresent()) {
712 VpnMap vpnMap = optionalVpnMap.get();
713 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
714 List<RouterIds> rtrIds = vpnMap.getRouterIds();
715 if (rtrIds == null) {
716 rtrIds = new ArrayList<>();
718 if (routerId != null) {
719 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
720 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
721 vpnMapBuilder.setRouterIds(rtrIds);
723 // remove entire node in case of internal VPN
724 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
725 LOG.debug("removing vpnMaps node: {} ", vpnId);
726 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
728 } catch (TransactionCommitFailedException e) {
729 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
731 if (isLockAcquired) {
732 vpnLock.unlock(vpnId);
736 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
737 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
738 vpnMapBuilder.setRouterIds(rtrIds);
739 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
742 if (networkIds != null) {
743 List<Uuid> vpnNw = vpnMap.getNetworkIds();
744 vpnNw.removeAll(networkIds);
745 if (vpnNw.isEmpty()) {
746 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
747 vpnMapBuilder.setNetworkIds(null);
749 vpnMapBuilder.setNetworkIds(vpnNw);
754 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
755 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
756 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
757 vpnMapBuilder.build());
758 } catch (TransactionCommitFailedException e) {
759 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
761 if (isLockAcquired) {
762 vpnLock.unlock(vpnId);
766 LOG.error("VPN : {} not found", vpnId.getValue());
768 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
771 private void deleteVpnInstance(Uuid vpnId) {
772 boolean isLockAcquired = false;
773 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
774 .child(VpnInstance.class,
775 new VpnInstanceKey(vpnId.getValue()))
778 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
779 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
780 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
781 } catch (TransactionCommitFailedException e) {
782 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
784 if (isLockAcquired) {
785 vpnLock.unlock(vpnId);
790 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
791 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn,
792 Subnetmap sn, VpnInterface vpnIface) {
793 List<Adjacency> adjList = new ArrayList<>();
794 if (vpnIface != null) {
795 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
797 String infName = port.getUuid().getValue();
798 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
799 for (FixedIps ip : port.getFixedIps()) {
800 String ipValue = ip.getIpAddress().stringValue();
801 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
802 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
805 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
806 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
808 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
809 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
810 //Create Neutron port adjacency if VPN presence is existing for subnet
811 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
812 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
813 .setSubnetId(ip.getSubnetId()).build();
814 if (!adjList.contains(vmAdj)) {
818 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
819 if (snTemp != null && snTemp.getInternetVpnId() != null) {
820 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
821 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
823 if (routerId != null) {
824 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
825 if (rtr != null && rtr.getRoutes() != null) {
826 List<Routes> routeList = rtr.getRoutes();
827 // create extraroute Adjacence for each ipValue,
828 // because router can have IPv4 and IPv6 subnet ports, or can have
829 // more that one IPv4 subnet port or more than one IPv6 subnet port
830 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
831 if (!erAdjList.isEmpty()) {
832 adjList.addAll(erAdjList);
837 return new AdjacenciesBuilder().setAdjacency(adjList).build();
840 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
841 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
842 boolean isRouterInterface = false;
843 if (port.getDeviceOwner() != null) {
844 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
846 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
847 String infName = port.getUuid().getValue();
848 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
849 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
852 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
853 Port port, Subnetmap sn, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
854 String infName = port.getUuid().getValue();
855 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
856 Optional<VpnInterface> optionalVpnInterface = null;
857 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
858 vpnId, internetVpnId, infName);
860 optionalVpnInterface = SingleTransactionDataBroker
861 .syncReadOptional(dataBroker, LogicalDatastoreType
862 .CONFIGURATION, vpnIfIdentifier);
863 } catch (ReadFailedException e) {
864 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
867 if (!optionalVpnInterface.isPresent()) {
870 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
871 sn != null ? sn.getSubnetIp() : "null");
872 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency();
873 List<Adjacency> updatedAdjsList = new ArrayList<>();
874 boolean isIpFromAnotherSubnet = false;
875 for (Adjacency adj : vpnAdjsList) {
876 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
877 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
878 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
879 isIpFromAnotherSubnet = true;
881 updatedAdjsList.add(adj);
884 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
885 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
888 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
889 String.valueOf(adjString), wrtConfigTxn);
891 if (internetVpnId != null) {
892 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
893 String.valueOf(adjString), wrtConfigTxn);
896 if (port.getDeviceOwner()
897 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
898 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
899 if (rtr != null && rtr.getRoutes() != null) {
900 List<Routes> extraRoutesToRemove = new ArrayList<>();
901 for (Routes rt: rtr.getRoutes()) {
902 if (rt.getNexthop().toString().equals(adjString)) {
903 extraRoutesToRemove.add(rt);
907 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
908 extraRoutesToRemove, vpnId);
909 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
911 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
916 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
918 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
920 if (!isIpFromAnotherSubnet) {
921 // no more subnetworks for neutron port
922 if (sn != null && sn.getRouterId() != null) {
923 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
925 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
931 // TODO Clean up the exception handling
932 @SuppressWarnings("checkstyle:IllegalCatch")
933 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
934 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
935 if (wrtConfigTxn == null) {
936 ListenableFutures.addErrorLogging(
937 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
938 tx -> deleteVpnInterface(infName, vpnId, tx)),
939 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
943 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
944 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
945 Optional<VpnInterface> optionalVpnInterface;
947 optionalVpnInterface =
948 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
950 } catch (ReadFailedException ex) {
951 LOG.error("Error during deletion of vpninterface {}", infName, ex);
954 if (!optionalVpnInterface.isPresent()) {
955 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
959 VpnInterface vpnInterface = optionalVpnInterface.get();
960 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
962 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
963 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
964 if (!vpnList.isEmpty()) {
965 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
966 + "List not empty", infName);
969 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
970 .setVpnInstanceNames(vpnList);
971 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
975 LOG.debug("Deleting vpn interface {}", infName);
976 wrtConfigTxn.delete(vpnIfIdentifier);
979 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
980 TypedWriteTransaction<Datastore.Configuration> writeConfigTxn,
982 if (vpnId == null || port == null) {
985 String infName = port.getUuid().getValue();
986 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
988 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
989 .syncReadOptional(dataBroker, LogicalDatastoreType
990 .CONFIGURATION, vpnIfIdentifier);
991 if (optionalVpnInterface.isPresent()) {
992 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
994 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
995 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
997 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
998 .setVpnInstanceNames(listVpn);
999 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1000 LOG.debug("Updating vpn interface {}", infName);
1001 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1002 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1003 while (adjacencyIter.hasNext()) {
1004 Adjacency adjacency = adjacencyIter.next();
1005 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1008 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1009 InstanceIdentifier<LearntVpnVipToPort> id =
1010 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1011 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1012 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1013 LogicalDatastoreType.OPERATIONAL, id);
1014 if (optionalVpnVipToPort.isPresent()) {
1015 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1017 if (listVpn == null || listVpn.isEmpty()) {
1018 adjacencyIter.remove();
1020 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1021 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1022 mipToQuery, infName, vpnId.getValue());
1025 List<FixedIps> ips = port.getFixedIps();
1026 for (FixedIps ip : ips) {
1027 String ipValue = ip.getIpAddress().stringValue();
1029 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1032 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1033 ipValue, writeConfigTxn);
1035 if (listVpn == null || listVpn.isEmpty()) {
1036 if (sm != null && sm.getRouterId() != null) {
1037 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1039 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1041 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1044 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1046 } catch (ReadFailedException ex) {
1047 LOG.error("Update of vpninterface {} failed", infName, ex);
1051 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
1053 TypedWriteTransaction<Datastore.Configuration> writeConfigTxn) {
1054 if (vpnId == null || port == null) {
1057 boolean isLockAcquired = false;
1058 String infName = port.getUuid().getValue();
1059 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1062 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1063 Optional<VpnInterface> optionalVpnInterface =
1064 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1066 if (optionalVpnInterface.isPresent()) {
1067 VpnInstanceNames vpnInstance = VpnHelper
1068 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1069 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1070 .get().getVpnInstanceNames());
1071 if (oldVpnId != null
1072 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1073 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1075 if (vpnId.getValue() != null
1076 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1077 listVpn.add(vpnInstance);
1079 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1080 .setVpnInstanceNames(listVpn);
1081 LOG.debug("Updating vpn interface {}", infName);
1082 if (!isBeingAssociated) {
1083 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1084 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1085 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1086 while (adjacencyIter.hasNext()) {
1087 Adjacency adjacency = adjacencyIter.next();
1088 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1089 InstanceIdentifier<LearntVpnVipToPort> id =
1090 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1091 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1092 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1093 LogicalDatastoreType.OPERATIONAL, id);
1094 if (optionalVpnVipToPort.isPresent()) {
1095 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1096 + "from VPN {}", infName, vpnId, oldVpnId);
1097 adjacencyIter.remove();
1098 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1100 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1101 mipToQuery, infName, vpnId.getValue());
1104 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1105 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1107 List<FixedIps> ips = port.getFixedIps();
1108 for (FixedIps ip : ips) {
1109 String ipValue = ip.getIpAddress().stringValue();
1110 if (oldVpnId != null) {
1111 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1112 ipValue, writeConfigTxn);
1114 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1115 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1117 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1119 LOG.error("VPN Interface {} not found", infName);
1121 } catch (ReadFailedException ex) {
1122 LOG.error("Updation of vpninterface {} failed", infName, ex);
1124 if (isLockAcquired) {
1125 interfaceLock.unlock(infName);
1130 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
1131 List<String> ert, Uuid router, List<Uuid> networks) {
1133 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1135 // Update VPN Instance node
1136 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1138 // Update local vpn-subnet DS
1139 updateVpnMaps(vpn, name, router, tenant, networks);
1141 if (router != null) {
1142 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1143 if (existingVpn != null) {
1144 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1145 // if before reboot, router was already associated to VPN, should not proceed associating router to
1146 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1147 // preserved upon reboot.
1148 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1149 // RouterInterfacesMap via #createVPNInterface call.
1150 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1151 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1154 associateRouterToInternalVpn(vpn, router);
1159 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1160 * specified Neutron Networks and Routers.
1162 * @param vpnId Uuid of the VPN tp be created
1163 * @param name Representative name of the new VPN
1164 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1165 * @param rdList Route-distinguisher for the VPN
1166 * @param irtList A list of Import Route Targets
1167 * @param ertList A list of Export Route Targets
1168 * @param routerIdsList ist of neutron router Id to associate with created VPN
1169 * @param networkList UUID of the neutron network the VPN may be associated to
1170 * @param type Type of the VPN Instance
1171 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1172 * @throws Exception if association of L3VPN failed
1174 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1175 List<String> ertList, @Nullable List<Uuid> routerIdsList, List<Uuid> networkList,
1176 VpnInstance.Type type, long l3vni) throws Exception {
1178 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1180 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1181 for (Uuid routerId : routerIdsList) {
1182 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1183 ipVersChoices = ipVersChoices.addVersion(vers);
1186 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1188 // Please note that router and networks will be filled into VPNMaps
1189 // by subsequent calls here to associateRouterToVpn and
1190 // associateNetworksToVpn
1191 updateVpnMaps(vpnId, name, null, tenantId, null);
1192 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1193 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1196 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1197 for (Uuid routerId : routerIdsList) {
1198 associateRouterToVpn(vpnId, routerId);
1201 if (networkList != null) {
1202 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1203 if (!failStrings.isEmpty()) {
1204 LOG.error("VPN {} association to networks failed for networks: {}. ",
1205 vpnId.getValue(), failStrings.toString());
1206 throw new Exception(failStrings.toString());
1212 * It handles the invocations to the createVPN RPC method.
1215 // TODO Clean up the exception handling
1216 @SuppressWarnings("checkstyle:IllegalCatch")
1217 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1219 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1220 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1221 List<RpcError> errorList = new ArrayList<>();
1222 int failurecount = 0;
1223 int warningcount = 0;
1225 List<L3vpn> vpns = input.getL3vpn();
1227 vpns = Collections.emptyList();
1229 for (L3vpn vpn : vpns) {
1230 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1231 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1232 formatAndLog(LOG::warn,
1233 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1234 vpn.getId().getValue())));
1238 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1239 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1240 formatAndLog(LOG::warn,
1241 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1242 vpn.getId().getValue())));
1246 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1248 if (vpn.getL3vni() != null) {
1249 l3vni = vpn.getL3vni();
1252 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1253 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1254 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1255 formatAndLog(LOG::warn,
1256 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1257 + "is already configured",
1258 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1262 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1263 if (operationalVpn.isPresent()) {
1264 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1265 formatAndLog(LOG::error,
1266 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1267 + "is still available. Please retry creation of a new vpn with the same RD"
1268 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1269 vpn.getRouteDistinguisher().get(0))));
1273 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1274 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1275 routerIdsList = vpn.getRouterIds();
1276 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1277 routerId : routerIdsList) {
1278 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1279 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1280 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1281 + "{}", vpn.getId(), routerId.getRouterId())));
1285 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1286 if (vpnId != null) {
1287 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1288 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1289 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1290 vpnId.getValue())));
1296 if (vpn.getNetworkIds() != null) {
1297 int initialWarningCount = warningcount;
1298 for (Uuid nw : vpn.getNetworkIds()) {
1299 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1300 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1301 if (network == null) {
1302 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1303 formatAndLog(LOG::warn,
1304 "Creation of L3VPN failed for VPN {} due to network not found {}",
1305 vpn.getId().getValue(), nw.getValue())));
1307 } else if (vpnId != null) {
1308 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1309 formatAndLog(LOG::warn,
1310 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1311 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1312 vpnId.getValue())));
1316 if (warningcount != initialWarningCount) {
1320 List<Uuid> rtrIdsList = new ArrayList<>();
1321 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1322 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1323 rtrId : vpn.getRouterIds()) {
1324 rtrIdsList.add(rtrId.getRouterId());
1328 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1329 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1330 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1331 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1332 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1333 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1334 vpnInstanceType, l3vni);
1335 } catch (Exception ex) {
1336 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1337 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1342 // if at least one succeeds; result is success
1343 // if none succeeds; result is failure
1344 if (failurecount + warningcount == vpns.size()) {
1345 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1347 List<String> errorResponseList = new ArrayList<>();
1348 if (!errorList.isEmpty()) {
1349 for (RpcError rpcError : errorList) {
1350 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1351 + ", ErrorMessage: " + rpcError.getMessage());
1354 errorResponseList.add("Operation successful with no errors");
1356 opBuilder.setResponse(errorResponseList);
1357 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1363 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1366 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1368 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1369 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1370 Uuid inputVpnId = input.getId();
1371 List<VpnInstance> vpns = new ArrayList<>();
1372 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1375 if (inputVpnId == null) {
1377 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1379 Optional<VpnInstances> optionalVpns =
1380 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1382 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1383 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1384 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1385 // from getL3VPN output
1386 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1389 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1395 opBuilder.setL3vpnInstances(l3vpnList);
1396 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1400 String name = inputVpnId.getValue();
1401 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1402 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1403 // read VpnInstance Info
1404 Optional<VpnInstance> optionalVpn =
1405 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1407 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1409 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1410 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1411 vpns.add(optionalVpn.get());
1414 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1415 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1419 for (VpnInstance vpnInstance : vpns) {
1420 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1421 // create VpnMaps id
1422 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1423 List<String> rd = Collections.EMPTY_LIST;
1424 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1425 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1426 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1427 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1429 List<String> ertList = new ArrayList<>();
1430 List<String> irtList = new ArrayList<>();
1432 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1433 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1434 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1435 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1436 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1437 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1438 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1440 if (!vpnTargetList.isEmpty()) {
1441 for (VpnTarget vpnTarget : vpnTargetList) {
1442 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1443 ertList.add(vpnTarget.getVrfRTValue());
1445 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1446 irtList.add(vpnTarget.getVrfRTValue());
1448 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1449 ertList.add(vpnTarget.getVrfRTValue());
1450 irtList.add(vpnTarget.getVrfRTValue());
1456 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1458 if (vpnInstance.getL3vni() != null) {
1459 l3vpn.setL3vni(vpnInstance.getL3vni());
1461 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1462 .class, new VpnMapKey(vpnId)).build();
1463 Optional<VpnMap> optionalVpnMap =
1464 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1466 if (optionalVpnMap.isPresent()) {
1467 VpnMap vpnMap = optionalVpnMap.get();
1468 List<Uuid> rtrIds = new ArrayList<>();
1469 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1470 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1471 rtrIds.add(rtrId.getRouterId());
1474 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1475 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1476 .setName(vpnMap.getName());
1479 l3vpnList.add(l3vpn.build());
1482 opBuilder.setL3vpnInstances(l3vpnList);
1483 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1485 } catch (ReadFailedException ex) {
1486 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1487 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1493 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1496 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1498 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1499 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1500 List<RpcError> errorList = new ArrayList<>();
1502 int failurecount = 0;
1503 int warningcount = 0;
1504 List<Uuid> vpns = input.getId();
1505 for (Uuid vpn : vpns) {
1509 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1510 InstanceIdentifier<VpnInstance> vpnIdentifier =
1511 InstanceIdentifier.builder(VpnInstances.class)
1512 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1513 Optional<VpnInstance> optionalVpn =
1514 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1516 if (optionalVpn.isPresent()) {
1519 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1520 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1523 } catch (ReadFailedException ex) {
1524 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1525 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1530 // if at least one succeeds; result is success
1531 // if none succeeds; result is failure
1532 if (failurecount + warningcount == vpns.size()) {
1533 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1535 List<String> errorResponseList = new ArrayList<>();
1536 if (!errorList.isEmpty()) {
1537 for (RpcError rpcError : errorList) {
1538 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1539 + ", ErrorMessage: " + rpcError.getMessage());
1542 errorResponseList.add("Operation successful with no errors");
1544 opBuilder.setResponse(errorResponseList);
1545 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1550 public void createVpnInstanceForSubnet(Uuid subnetId) {
1551 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1552 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1555 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1556 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1557 removeVpn(subnetId);
1560 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1561 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1562 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1563 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1565 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1566 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1569 if (vpnId != null) {
1570 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1571 if (vpnMap == null) {
1572 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1573 + " cannot add subnet {} to VPN", vpnId.getValue(),
1577 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1578 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1579 if (isVpnOfTypeL2(vpnInstance)) {
1580 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1581 NeutronEvpnUtils.Operation.ADD);
1584 if (internetVpnId != null) {
1585 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1586 if (vpnMap == null) {
1587 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1588 + "subnet {} to VPN", internetVpnId.getValue(),
1593 final Uuid internetId = internetVpnId;
1594 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1595 List<Uuid> portList = sn.getPortList();
1596 if (portList != null) {
1597 for (final Uuid portId : portList) {
1598 String vpnInfName = portId.getValue();
1599 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1600 Port port = neutronvpnUtils.getNeutronPort(portId);
1602 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1603 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1606 final Boolean isRouterInterface = port.getDeviceOwner()
1607 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1608 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1609 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1610 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1612 if (vpnIface == null) {
1613 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1614 Set<Uuid> listVpn = new HashSet<>();
1615 if (vpnId != null) {
1618 if (internetId != null) {
1619 listVpn.add(internetId);
1621 writeVpnInterfaceToDs(listVpn,
1622 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1623 if (sn.getRouterId() != null) {
1624 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1627 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1628 if (vpnId != null) {
1629 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1631 if (internetId != null) {
1632 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1641 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) {
1642 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1643 "removeSubnetFromVpn: at least one VPN must be not null");
1644 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1645 vpnId, internetVpnId);
1646 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1648 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1651 VpnMap vpnMap = null;
1652 VpnInstance vpnInstance = null;
1653 if (vpnId != null) {
1654 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1655 if (vpnMap == null) {
1656 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1657 vpnId.getValue(), subnet.getValue());
1660 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1662 if (internetVpnId == null) {
1663 internetVpnId = sn.getInternetVpnId();
1665 if (internetVpnId != null) {
1666 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1667 if (vpnMap == null) {
1668 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1669 + " from Internet VPN",
1670 internetVpnId.getValue(), subnet.getValue());
1674 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1675 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1676 NeutronEvpnUtils.Operation.DELETE);
1678 boolean subnetVpnAssociation = false;
1679 if (vpnId != null && sn.getVpnId() != null
1680 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1681 subnetVpnAssociation = true;
1682 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1683 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1684 subnetVpnAssociation = true;
1686 if (subnetVpnAssociation == false) {
1687 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1688 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1691 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1692 List<Uuid> portList = sn.getPortList();
1693 final Uuid internetId = internetVpnId;
1694 if (portList != null) {
1695 for (final Uuid portId : portList) {
1696 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1697 final Port port = neutronvpnUtils.getNeutronPort(portId);
1698 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1699 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1700 CONFIGURATION, tx -> {
1702 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1705 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1706 + "port is absent in Neutron config DS", portId.getValue(),
1712 //update subnet-vpn association
1713 removeFromSubnetNode(subnet, null, null, vpnId, null);
1716 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1717 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1718 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1720 Uuid internalVpnId = sm.getVpnId();
1721 if (internalVpnId == null) {
1722 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1723 sm.getId().getValue());
1726 if (isBeingAssociated) {
1727 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1729 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1732 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1733 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1734 if (isBeingAssociated) {
1735 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1736 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn);
1738 removeInternetVpnFromVpnInterface(vpn,
1739 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1744 // Check for ports on this subnet and update association of
1745 // corresponding vpn-interfaces to internet vpn
1746 List<Uuid> portList = sm.getPortList();
1747 if (portList != null) {
1748 for (Uuid port : portList) {
1749 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1750 port.getValue(), isBeingAssociated);
1751 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1752 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1754 if (isBeingAssociated) {
1755 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1758 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1765 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1766 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1767 oldVpnId.getValue(), newVpnId.getValue());
1768 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1769 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1770 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1771 Uuid vpnExtUuid = netIsExternal ? null
1772 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1773 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1775 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1778 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1779 * associated with internet BGP-VPN.
1781 if (vpnExtUuid != null) {
1782 //Update V6 Internet default route match with new VPN metadata
1783 neutronvpnUtils.updateVpnInstanceWithFallback(vpnExtUuid, isBeingAssociated);
1785 //Update Router Interface first synchronously.
1786 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1787 ListenableFuture<Void> future =
1788 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1789 tx -> updateVpnInterface(newVpnId, oldVpnId,
1790 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1791 isBeingAssociated, true, tx));
1792 Futures.addCallback(future, new FutureCallback<Void>() {
1794 public void onSuccess(Void result) {
1795 // Check for ports on this subnet and update association of
1796 // corresponding vpn-interfaces to external vpn
1797 List<Uuid> portList = sn.getPortList();
1798 if (portList != null) {
1799 for (Uuid port : portList) {
1800 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1801 port.getValue(), isBeingAssociated);
1802 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1803 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1804 tx -> updateVpnInterface(newVpnId, oldVpnId,
1805 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1812 public void onFailure(Throwable throwable) {
1814 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1816 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1818 }, MoreExecutors.directExecutor());
1823 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1824 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1825 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1828 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1829 synchronized (routerId.getValue().intern()) {
1830 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1832 Optional<RouterInterfaces> optRouterInterfaces =
1833 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1834 routerInterfacesId);
1835 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1836 .setInterfaceId(interfaceName).build();
1837 if (optRouterInterfaces.isPresent()) {
1838 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1839 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1842 // TODO Shouldn't we be doing something with builder and interfaces?
1843 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1844 // List<Interfaces> interfaces = new ArrayList<>();
1845 // interfaces.add(routerInterface);
1847 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1848 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1851 } catch (ReadFailedException | TransactionCommitFailedException e) {
1852 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1857 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1858 synchronized (routerId.getValue().intern()) {
1859 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1861 Optional<RouterInterfaces> optRouterInterfaces =
1862 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1863 routerInterfacesId);
1864 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1865 .setInterfaceId(interfaceName).build();
1866 if (optRouterInterfaces.isPresent()) {
1867 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1868 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1869 if (interfaces != null && interfaces.remove(routerInterface)) {
1870 if (interfaces.isEmpty()) {
1871 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1872 routerInterfacesId);
1874 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1875 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1879 } catch (ReadFailedException | TransactionCommitFailedException e) {
1880 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1886 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1887 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1888 * route will be ignored.
1890 * @param vpnName the VPN identifier
1891 * @param interVpnLinkRoutes The list of static routes
1892 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1894 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1895 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1896 for (Routes route : interVpnLinkRoutes) {
1897 String nexthop = route.getNexthop().stringValue();
1898 String destination = route.getDestination().stringValue();
1899 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1900 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1901 AddStaticRouteInput rpcInput =
1902 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1903 .setVpnInstanceName(vpnName.getValue())
1905 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1906 RpcResult<AddStaticRouteOutput> rpcResult;
1908 rpcResult = labelOuputFtr.get();
1909 if (rpcResult.isSuccessful()) {
1910 LOG.debug("Label generated for destination {} is: {}",
1911 destination, rpcResult.getResult().getLabel());
1913 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1914 destination, nexthop, rpcResult.getErrors());
1916 } catch (InterruptedException | ExecutionException e) {
1917 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1918 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1921 // Any other case is a fault.
1922 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1923 route.getDestination().stringValue(), nexthop);
1930 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1931 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1933 * @param vpnName the VPN identifier
1934 * @param interVpnLinkRoutes The list of static routes
1935 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1937 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1938 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1939 for (Routes route : interVpnLinkRoutes) {
1940 String nexthop = route.getNexthop().stringValue();
1941 String destination = route.getDestination().stringValue();
1942 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1943 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1944 RemoveStaticRouteInput rpcInput =
1945 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1946 .setVpnInstanceName(vpnName.getValue())
1949 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1950 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1952 // Any other case is a fault.
1953 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1954 route.getDestination().stringValue(), nexthop);
1961 * Returns true if the specified nexthop is the other endpoint in an
1962 * InterVpnLink, regarding one of the VPN's point of view.
1964 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1966 interVpnLink != null
1967 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1968 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1969 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1970 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1974 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
1975 List<Adjacency> adjList = new ArrayList<>();
1976 Map<String, List<String>> adjMap = new HashMap<>();
1977 for (Routes route : routeList) {
1978 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1979 LOG.error("Incorrect input received for extra route. {}", route);
1981 String nextHop = route.getNexthop().stringValue();
1982 String destination = route.getDestination().stringValue();
1983 if (!nextHop.equals(fixedIp)) {
1984 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1987 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
1989 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1990 if (!hops.contains(nextHop)) {
1996 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
1997 final String destination = entry.getKey();
1998 final List<String> ipList = entry.getValue();
1999 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2000 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2001 .withKey(new AdjacencyKey(destination)).build();
2007 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2008 checkAlarmExtraRoutes(vpnId, routeList);
2010 for (Routes route : routeList) {
2011 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2012 LOG.error("Incorrect input received for extra route. {}", route);
2014 String nextHop = route.getNexthop().stringValue();
2015 String destination = route.getDestination().stringValue();
2016 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2018 if (infName != null) {
2019 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2020 destination, vpnId.getValue(), nextHop, infName);
2021 boolean isLockAcquired = false;
2023 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2024 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2025 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2026 .child(Adjacency.class, new AdjacencyKey(destination));
2027 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2028 LogicalDatastoreType.CONFIGURATION, path);
2029 if (existingAdjacency.isPresent()
2030 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2031 LOG.error("The route with destination {} nextHop {} is already present as"
2032 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2033 destination, nextHop, infName);
2036 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2037 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2038 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2039 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2040 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2042 } catch (TransactionCommitFailedException e) {
2043 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2044 destination, nextHop, e);
2045 } catch (ReadFailedException e) {
2046 LOG.error("Exception on reading data-store ", e);
2048 if (isLockAcquired) {
2049 interfaceLock.unlock(infName);
2053 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2054 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2061 * This method setup or down an alarm about extra route fault.
2062 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2063 * available RDs, then an alarm and an error is generated.<br>
2064 * <b>Be careful</b> the routeList could be changed.
2066 * @param vpnId the vpnId of vpn to control.
2067 * @param routeList the list of router to check, it could be modified.
2069 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2070 if (!neutronvpnAlarm.isAlarmEnabled()) {
2071 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2074 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2075 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2076 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2080 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2081 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2082 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2086 for (Routes route : routeList) {
2087 // count the number of nexthops for each same route.getDestingation().getValue()
2088 String destination = route.getDestination().stringValue();
2089 String nextHop = route.getNexthop().stringValue();
2090 List<String> nextHopList = new ArrayList<>();
2091 nextHopList.add(nextHop);
2093 for (Routes routeTmp : routeList) {
2094 String routeDest = routeTmp.getDestination().stringValue();
2095 if (!destination.equals(routeDest)) {
2098 String routeNextH = routeTmp.getNexthop().stringValue();
2099 if (nextHop.equals(routeNextH)) {
2103 nextHopList.add(routeTmp.getNexthop().stringValue());
2105 final List<String> rdList = new ArrayList<>();
2106 if (vpnInstance.getIpv4Family() != null
2107 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2108 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2114 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2115 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2116 if (rd != null && !rdList.contains(rd)) {
2121 // 1. VPN Instance Name
2122 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2125 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2126 Uuid routerUuid = routerUuidList.get(0);
2127 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2128 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2130 // 3. List of RDs associated with the VPN
2131 detailsAlarm.append(" List of RDs associated with the VPN: ");
2132 for (String s : rdList) {
2133 detailsAlarm.append(s);
2134 detailsAlarm.append(", ");
2137 // 4. Prefix in question
2138 detailsAlarm.append(" for prefix: ");
2139 detailsAlarm.append(route.getDestination().stringValue());
2141 // 5. List of NHs for the prefix
2142 detailsAlarm.append(" for nextHops: ");
2143 for (String s : nextHopList) {
2144 detailsAlarm.append(s);
2145 detailsAlarm.append(", ");
2148 if (rdList.size() < nbNextHops) {
2149 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2151 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2156 // TODO Clean up the exception handling
2157 @SuppressWarnings("checkstyle:IllegalCatch")
2158 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2159 for (Routes route : routeList) {
2160 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2161 boolean isLockAcquired = false;
2162 String nextHop = route.getNexthop().stringValue();
2163 String destination = route.getDestination().stringValue();
2164 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2166 if (infName == null) {
2167 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2168 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2169 // Proceed to remove the next extra-route
2172 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2173 destination, vpnId.getValue(), nextHop, infName);
2175 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2176 InstanceIdentifier.builder(VpnInterfaces.class)
2177 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2178 .augmentation(Adjacencies.class)
2179 .child(Adjacency.class, new AdjacencyKey(destination))
2183 // Looking for existing prefix in MDSAL database
2184 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2185 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2186 boolean updateNextHops = false;
2187 List<String> nextHopList = new ArrayList<>();
2188 if (adjacency.isPresent()) {
2189 List<String> nhListRead = adjacency.get().getNextHopIpList();
2190 if (nhListRead.size() > 1) { // ECMP case
2191 for (String nextHopRead : nhListRead) {
2192 if (nextHopRead.equals(nextHop)) {
2193 updateNextHops = true;
2195 nextHopList.add(nextHopRead);
2201 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2202 if (updateNextHops) {
2203 // An update must be done, not including the current next hop
2204 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2205 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2206 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2207 .setNextHopIpList(nextHopList)
2208 .withKey(new AdjacencyKey(destination))
2210 Adjacencies erAdjs =
2211 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2212 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2213 .addAugmentation(Adjacencies.class, erAdjs).build();
2214 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2215 vpnIfIdentifier, vpnIf);
2217 // Remove the whole route
2218 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2219 adjacencyIdentifier);
2220 LOG.trace("extra route {} deleted successfully", route);
2222 } catch (TransactionCommitFailedException | ReadFailedException e) {
2223 LOG.error("exception in deleting extra route with destination {} for interface {}",
2224 destination, infName, e);
2226 if (isLockAcquired) {
2227 interfaceLock.unlock(infName);
2231 LOG.error("Incorrect input received for extra route: {}", route);
2236 public void removeVpn(Uuid vpnId) {
2238 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2239 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2240 List<Uuid> routerUuidList = new ArrayList<>();
2241 // dissociate router
2242 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2243 for (RouterIds router : routerIdsList) {
2244 Uuid routerId = router.getRouterId();
2245 routerUuidList.add(routerId);
2246 dissociateRouterFromVpn(vpnId, routerId);
2249 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2250 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2252 // remove entire vpnMaps node
2253 deleteVpnMapsNode(vpnId);
2255 // remove vpn-instance
2256 deleteVpnInstance(vpnId);
2257 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2260 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2261 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2264 // TODO Clean up the exception handling
2265 @SuppressWarnings("checkstyle:IllegalCatch")
2266 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2267 updateVpnMaps(vpnId, null, routerId, null, null);
2268 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2269 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2270 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2271 for (Subnetmap sn : subMapList) {
2272 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2273 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2274 if (!ipVersion.isIpVersionChosen(ipVers)) {
2275 ipVersion = ipVersion.addVersion(ipVers);
2278 if (ipVersion != IpVersionChoice.UNDEFINED) {
2279 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", ipVersion,
2281 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2285 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2286 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2288 } catch (Exception e) {
2289 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2290 .getValue(), vpnId.getValue(), e);
2294 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2295 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2296 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2297 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2298 for (Uuid subnet : routerSubnets) {
2299 IpVersionChoice version = NeutronvpnUtils
2300 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2301 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2302 addSubnetToVpn(vpnId, subnet, null);
2304 addSubnetToVpn(vpnId, subnet, internetVpnId);
2309 // TODO Clean up the exception handling
2310 @SuppressWarnings("checkstyle:IllegalCatch")
2311 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2313 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2314 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2315 for (Subnetmap sn : subMapList) {
2316 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2317 if (ipVersion.isIpVersionChosen(ipVers)) {
2318 ipVersion = ipVersion.addVersion(ipVers);
2320 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2321 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2323 if (ipVersion != IpVersionChoice.UNDEFINED) {
2324 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2326 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2329 clearFromVpnMaps(vpnId, routerId, null);
2331 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2332 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2334 } catch (Exception e) {
2335 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2336 .getValue(), vpnId.getValue(), e);
2341 * Parses and associates networks list with given VPN.
2343 * @param vpnId Uuid of given VPN.
2344 * @param networkList List list of network Ids (Uuid), which will be associated.
2345 * @return list of formatted strings with detailed error messages.
2348 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2349 List<String> failedNwList = new ArrayList<>();
2350 HashSet<Uuid> passedNwList = new HashSet<>();
2351 if (networkList.isEmpty()) {
2352 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2353 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2355 return failedNwList;
2357 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2358 if (vpnInstance == null) {
2359 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2360 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2361 + "in ConfigDS", vpnId.getValue()));
2362 return failedNwList;
2365 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2366 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2368 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2369 + "associated with", vpnId.getValue()));
2370 return failedNwList;
2372 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2373 for (Uuid nw : networkList) {
2374 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2375 if (network == null) {
2376 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2377 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2381 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2382 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2383 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2384 nw.getValue(), vpnId.getValue());
2385 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2386 nw.getValue(), vpnId.getValue()));
2389 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2390 if (networkVpnId != null) {
2391 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2392 nw.getValue(), networkVpnId.getValue());
2393 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2394 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2397 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2398 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2399 nw.getValue(), vpnId.getValue());
2400 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2401 nw.getValue(), vpnId.getValue()));
2404 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2405 if (subnetmapList == null || subnetmapList.isEmpty()) {
2406 passedNwList.add(nw);
2409 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2412 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2413 for (Subnetmap subnetmap : subnetmapList) {
2414 Uuid subnetId = subnetmap.getId();
2415 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2416 if (subnetVpnId != null) {
2417 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2418 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2419 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2420 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2423 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2424 if (!ipVersion.isIpVersionChosen(ipVers)) {
2425 ipVersion = ipVersion.addVersion(ipVers);
2427 if (!NeutronvpnUtils.getIsExternal(network)) {
2428 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2430 addSubnetToVpn(vpnId, subnetId, null);
2431 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2433 passedNwList.add(nw);
2436 if (ipVersion != IpVersionChoice.UNDEFINED) {
2437 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2439 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2441 passedNwList.add(nw);
2443 } catch (ReadFailedException e) {
2444 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2446 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2449 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2450 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2451 return failedNwList;
2454 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2455 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2458 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2459 if (vpnOpDataEntry == null) {
2460 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2463 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2464 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2465 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2467 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2468 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2469 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2471 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2474 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2475 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2476 updateVpnInternetForSubnet(sm, vpnId, true);
2478 if (!ipVersion.isIpVersionChosen(ipVers)) {
2479 ipVersion = ipVersion.addVersion(ipVers);
2482 if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
2483 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2484 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2485 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, true);
2491 * Parses and disassociates networks list from given VPN.
2493 * @param vpnId Uuid of given VPN.
2494 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2495 * @return list of formatted strings with detailed error messages.
2498 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2499 List<String> failedNwList = new ArrayList<>();
2500 HashSet<Uuid> passedNwList = new HashSet<>();
2501 if (networkList.isEmpty()) {
2502 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2503 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2505 return failedNwList;
2507 for (Uuid nw : networkList) {
2508 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2509 if (networkSubnets == null) {
2510 passedNwList.add(nw);
2513 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2514 if (network == null) {
2515 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2516 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2520 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2521 if (networkVpnId == null) {
2522 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2523 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2527 if (!vpnId.equals(networkVpnId)) {
2528 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2529 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2530 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2531 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2535 if (NeutronvpnUtils.getIsExternal(network)) {
2536 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2537 passedNwList.add(nw);
2540 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2541 nw.getValue(), vpnId.getValue());
2542 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2547 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2548 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2549 for (Uuid subnet : networkSubnets) {
2550 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2551 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2552 if (!ipVersion.isIpVersionChosen(ipVers)) {
2553 ipVersion = ipVersion.addVersion(ipVers);
2555 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2557 removeSubnetFromVpn(vpnId, subnet, null);
2558 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2560 passedNwList.add(nw);
2562 if (ipVersion != IpVersionChoice.UNDEFINED) {
2563 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
2565 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2568 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2569 LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
2571 return failedNwList;
2574 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2575 if (!removeExternalNetworkFromVpn(extNet)) {
2578 // check, if there is another Provider Networks associated with given VPN
2579 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2580 if (vpnNets != null) {
2581 //Remove currently disassociated network from the list
2582 vpnNets.remove(extNet.getUuid());
2583 for (Uuid netId : vpnNets) {
2584 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2585 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2586 + "{}", vpnId.getValue(), netId.getValue());
2591 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2592 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2593 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2594 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2595 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2596 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2597 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2599 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2602 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2603 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2604 updateVpnInternetForSubnet(sm, vpnId, false);
2606 if (!ipVersion.isIpVersionChosen(ipVers)) {
2607 ipVersion = ipVersion.addVersion(ipVers);
2610 if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
2611 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2612 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2614 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, false);
2620 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2623 // TODO Clean up the exception handling
2624 @SuppressWarnings("checkstyle:IllegalCatch")
2625 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2627 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2628 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2629 StringBuilder returnMsg = new StringBuilder();
2630 Uuid vpnId = input.getVpnId();
2633 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2634 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2635 input.getNetworkId().toString());
2636 List<Uuid> netIds = input.getNetworkId();
2637 if (netIds != null && !netIds.isEmpty()) {
2638 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2639 if (!failed.isEmpty()) {
2640 returnMsg.append(failed);
2644 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2646 if (returnMsg.length() != 0) {
2647 opBuilder.setResponse(
2648 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2649 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2650 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2652 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2654 } catch (Exception ex) {
2655 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2656 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2657 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2659 LOG.debug("associateNetworks returns..");
2664 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2667 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2669 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2670 LOG.debug("associateRouter {}", input);
2671 StringBuilder returnMsg = new StringBuilder();
2672 Uuid vpnId = input.getVpnId();
2673 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2674 routerIds = input.getRouterIds();
2675 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2676 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2677 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2678 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2679 .RouterIds routerId : routerIds) {
2680 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2681 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2682 if (vpnMap != null) {
2684 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2685 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2686 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2687 .append(routerId.getRouterId());
2688 } else if (extVpnId != null) {
2689 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2690 + "another VPN ").append(extVpnId.getValue());
2692 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2693 routerId.getRouterId());
2694 associateRouterToVpn(vpnId, routerId.getRouterId());
2697 returnMsg.append("router not found : ").append(routerId.getRouterId());
2700 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2702 if (returnMsg.length() != 0) {
2703 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2704 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2705 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2707 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2710 LOG.debug("associateRouter returns..");
2715 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2718 // TODO Clean up the exception handling
2719 @SuppressWarnings("checkstyle:IllegalCatch")
2720 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2721 GetFixedIPsForNeutronPortInput input) {
2722 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2723 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2724 Uuid portId = input.getPortId();
2725 StringBuilder returnMsg = new StringBuilder();
2727 List<String> fixedIPList = new ArrayList<>();
2728 Port port = neutronvpnUtils.getNeutronPort(portId);
2730 List<FixedIps> fixedIPs = port.getFixedIps();
2731 for (FixedIps ip : fixedIPs) {
2732 fixedIPList.add(ip.getIpAddress().stringValue());
2735 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2737 if (returnMsg.length() != 0) {
2738 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2740 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2741 returnMsg)).build());
2743 opBuilder.setFixedIPs(fixedIPList);
2744 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2746 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2748 } catch (Exception ex) {
2749 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2750 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2751 portId.getValue(), ex.getMessage(), ex)).build());
2757 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2760 // TODO Clean up the exception handling
2761 @SuppressWarnings("checkstyle:IllegalCatch")
2762 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2764 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2765 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2767 LOG.debug("dissociateNetworks {}", input);
2768 StringBuilder returnMsg = new StringBuilder();
2769 Uuid vpnId = input.getVpnId();
2772 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2773 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2774 input.getNetworkId().toString());
2775 List<Uuid> netIds = input.getNetworkId();
2776 if (netIds != null && !netIds.isEmpty()) {
2777 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2778 if (!failed.isEmpty()) {
2779 returnMsg.append(failed);
2783 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2785 if (returnMsg.length() != 0) {
2786 opBuilder.setResponse(
2787 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2788 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2790 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2792 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2794 } catch (Exception ex) {
2795 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2796 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2797 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2799 LOG.debug("dissociateNetworks returns..");
2804 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2807 // TODO Clean up the exception handling
2808 @SuppressWarnings("checkstyle:IllegalCatch")
2809 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2811 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2813 LOG.debug("dissociateRouter {}", input);
2814 StringBuilder returnMsg = new StringBuilder();
2815 Uuid vpnId = input.getVpnId();
2816 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2817 .RouterIds> routerIdList = input.getRouterIds();
2818 String routerIdsString = "";
2819 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2820 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2821 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2822 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2823 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2824 .RouterIds routerId : routerIdList) {
2826 if (routerId != null) {
2827 routerIdsString += routerId.getRouterId() + ", ";
2828 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2830 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2831 if (routerVpnId == null) {
2832 returnMsg.append("input router ").append(routerId.getRouterId())
2833 .append(" not associated to any vpn yet");
2834 } else if (vpnId.equals(routerVpnId)) {
2835 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2837 returnMsg.append("input router ").append(routerId.getRouterId())
2838 .append(" associated to vpn ")
2839 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2842 returnMsg.append("router not found : ").append(routerId.getRouterId());
2845 if (returnMsg.length() != 0) {
2846 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2847 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2848 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2849 returnMsg)).build());
2851 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2853 } catch (Exception ex) {
2854 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2855 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2856 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2860 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2863 LOG.debug("dissociateRouter returns..");
2867 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2868 // check if the router is associated to some VPN
2869 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2870 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2871 if (vpnId != null) {
2872 // remove existing external vpn interfaces
2873 for (Uuid subnetId : routerSubnetIds) {
2874 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2876 clearFromVpnMaps(vpnId, routerId, null);
2878 // remove existing internal vpn interfaces
2879 for (Uuid subnetId : routerSubnetIds) {
2880 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2883 // delete entire vpnMaps node for internal VPN
2884 deleteVpnMapsNode(routerId);
2886 // delete vpn-instance for internal VPN
2887 deleteVpnInstance(routerId);
2890 protected Subnet getNeutronSubnet(Uuid subnetId) {
2891 return neutronvpnUtils.getNeutronSubnet(subnetId);
2894 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2895 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2897 return sn.getGatewayIp();
2903 protected Network getNeutronNetwork(Uuid networkId) {
2904 return neutronvpnUtils.getNeutronNetwork(networkId);
2907 protected Port getNeutronPort(String name) {
2908 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2911 protected Port getNeutronPort(Uuid portId) {
2912 return neutronvpnUtils.getNeutronPort(portId);
2915 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2916 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2919 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2920 return neutronvpnUtils.getNetworksForVpn(vpnId);
2924 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2926 * @return a List of String to be printed on screen
2927 * @throws ReadFailedException if there was a problem reading from the data store
2929 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2930 List<String> result = new ArrayList<>();
2931 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2933 result.add("-------------------------------------------------------------------------------------------");
2934 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2936 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2937 if (ports.isPresent() && ports.get().getPort() != null) {
2938 for (Port port : ports.get().getPort()) {
2939 List<FixedIps> fixedIPs = port.getFixedIps();
2940 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2941 List<String> ipList = new ArrayList<>();
2942 for (FixedIps fixedIp : fixedIPs) {
2943 IpAddress ipAddress = fixedIp.getIpAddress();
2944 if (ipAddress.getIpv4Address() != null) {
2945 ipList.add(ipAddress.getIpv4Address().getValue());
2947 ipList.add(ipAddress.getIpv6Address().getValue());
2950 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2951 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2952 ipList.toString()));
2954 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2955 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2964 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2966 * @param vpnuuid Uuid of the VPN whose config must be shown
2967 * @return formatted output list
2968 * @throws InterruptedException if there was a thread related problem getting the data to display
2969 * @throws ExecutionException if there was any other problem getting the data to display
2971 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2972 List<String> result = new ArrayList<>();
2973 if (vpnuuid == null) {
2975 result.add("Displaying VPN config for all VPNs");
2976 result.add("To display VPN config for a particular VPN, use the following syntax");
2977 result.add(getshowVpnConfigCLIHelp());
2979 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2980 if (rpcResult.isSuccessful()) {
2982 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2984 result.add(String.format(" %-80s ", "Import-RTs"));
2986 result.add(String.format(" %-80s ", "Export-RTs"));
2988 result.add(String.format(" %-76s ", "Subnet IDs"));
2990 result.add("------------------------------------------------------------------------------------");
2992 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2993 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2994 .rev150602.VpnInstance vpn : vpnList) {
2995 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2997 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2998 vpn.getRouteDistinguisher()));
3000 result.add(String.format(" %-80s ", vpn.getImportRT()));
3002 result.add(String.format(" %-80s ", vpn.getExportRT()));
3005 Uuid vpnid = vpn.getId();
3006 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3007 if (!subnetList.isEmpty()) {
3008 for (Uuid subnetuuid : subnetList) {
3009 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3012 result.add(String.format(" %-76s ", "\" \""));
3015 result.add("----------------------------------------");
3019 String errortag = rpcResult.getErrors().iterator().next().getTag();
3020 if (Objects.equals(errortag, "")) {
3022 result.add("No VPN has been configured yet");
3023 } else if (Objects.equals(errortag, "invalid-value")) {
3025 result.add("VPN " + vpnuuid.getValue() + " is not present");
3027 result.add("error getting VPN info : " + rpcResult.getErrors());
3028 result.add(getshowVpnConfigCLIHelp());
3034 protected void createExternalVpnInterfaces(Uuid extNetId) {
3035 if (extNetId == null) {
3036 LOG.error("createExternalVpnInterfaces: external network is null");
3040 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3041 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3042 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3046 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3047 for (String elanInterface : extElanInterfaces) {
3048 createExternalVpnInterface(extNetId, elanInterface, tx);
3050 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3053 // TODO Clean up the exception handling
3054 @SuppressWarnings("checkstyle:IllegalCatch")
3055 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3056 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3057 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3058 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3061 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3062 for (String elanInterface : extElanInterfaces) {
3063 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3064 .buildVpnInterfaceIdentifier(elanInterface);
3065 LOG.info("Removing vpn interface {}", elanInterface);
3066 tx.delete(vpnIfIdentifier);
3068 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3071 private void createExternalVpnInterface(Uuid vpnId, String infName,
3072 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3073 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3074 false /* not a router iface */, wrtConfigTxn);
3077 // TODO Clean up the exception handling
3078 @SuppressWarnings("checkstyle:IllegalCatch")
3079 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
3080 Uuid networkUuid, Boolean isRouterInterface, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3081 if (vpnIdList.isEmpty() || infName == null) {
3082 LOG.error("vpnid is empty or interface({}) is null", infName);
3085 if (wrtConfigTxn == null) {
3086 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3087 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3088 "Error writing VPN interface");
3091 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3092 for (Uuid vpnId: vpnIdList) {
3093 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3094 AssociatedSubnetType.V4AndV6Subnets);
3095 vpnIdListStruct.add(vpnInstance);
3098 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3099 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3101 .setVpnInstanceNames(vpnIdListStruct)
3102 .setRouterInterface(isRouterInterface);
3103 LOG.info("Network Id is {}", networkUuid);
3104 if (networkUuid != null) {
3105 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3106 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3107 NetworkAttributes.NetworkType networkType = (providerType != null)
3108 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3109 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3110 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3111 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3114 if (adjacencies != null) {
3115 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3117 VpnInterface vpnIf = vpnb.build();
3119 LOG.info("Creating vpn interface {}", vpnIf);
3120 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3121 } catch (Exception ex) {
3122 LOG.error("Creation of vpninterface {} failed", infName, ex);
3126 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3127 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3128 if (vpnId == null || infName == null) {
3129 LOG.error("vpn id or interface is null");
3132 if (wrtConfigTxn == null) {
3133 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3134 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3135 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3136 }), LOG, "Error updating VPN interface with adjacencies");
3140 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3141 boolean isLockAcquired = false;
3143 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3144 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3145 .syncReadOptional(dataBroker, LogicalDatastoreType
3146 .CONFIGURATION, vpnIfIdentifier);
3147 if (optionalVpnInterface.isPresent()) {
3148 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3149 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3151 if (adjacencies == null) {
3152 if (isLockAcquired) {
3153 interfaceLock.unlock(infName);
3157 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3158 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3159 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3160 optionalVpnInterface.get().getVpnInstanceNames());
3161 if (listVpnInstances.isEmpty() || !VpnHelper
3162 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3163 VpnInstanceNames vpnInstance = VpnHelper
3164 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3165 listVpnInstances.add(vpnInstance);
3166 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3169 VpnInstanceNames vpnInstance = VpnHelper
3170 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3171 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3172 listVpnInstances.add(vpnInstance);
3173 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3175 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3176 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3178 } catch (IllegalStateException | ReadFailedException ex) {
3179 LOG.error("Update of vpninterface {} failed", infName, ex);
3181 if (isLockAcquired) {
3182 interfaceLock.unlock(infName);
3187 private String getshowVpnConfigCLIHelp() {
3188 StringBuilder help = new StringBuilder("Usage:");
3189 help.append("display vpn-config [-vid/--vpnid <id>]");
3190 return help.toString();
3193 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3194 InterruptedException {
3195 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3196 .setVpnId(vpnId).build();
3197 LOG.info("publishing notification upon association of router to VPN");
3198 notificationPublishService.putNotification(routerAssociatedToVpn);
3201 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3202 InterruptedException {
3203 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3204 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3205 LOG.info("publishing notification upon disassociation of router from VPN");
3206 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3209 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3210 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3214 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3215 return neutronEvpnManager.createEVPN(input);
3219 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3220 return neutronEvpnManager.getEVPN(input);
3224 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3225 return neutronEvpnManager.deleteEVPN(input);
3228 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3229 Uuid extNetId = extNet.getUuid();
3230 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3231 .child(Networks.class, new NetworksKey(extNetId)).build();
3234 Optional<Networks> optionalExtNets =
3235 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3237 if (!optionalExtNets.isPresent()) {
3238 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3239 extNetId.getValue());
3242 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3243 builder.setVpnid(vpnId);
3244 Networks networks = builder.build();
3245 // Add Networks object to the ExternalNetworks list
3246 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3247 extNetId.getValue());
3248 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3251 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3252 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3253 extNetId.getValue(), ex);
3258 private boolean removeExternalNetworkFromVpn(Network extNet) {
3259 Uuid extNetId = extNet.getUuid();
3260 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3261 .child(Networks.class, new NetworksKey(extNetId)).build();
3263 Optional<Networks> optionalNets =
3264 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3266 NetworksBuilder builder = null;
3267 if (optionalNets.isPresent()) {
3268 builder = new NetworksBuilder(optionalNets.get());
3270 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3271 extNetId.getValue());
3274 builder.setVpnid(null);
3275 Networks networks = builder.build();
3276 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3277 extNetId.getValue());
3278 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3280 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3281 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3282 extNetId.getValue(), ex);
3287 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3288 Optional<String> existingVpnName = Optional.of(primaryRd);
3289 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3291 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3292 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3293 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3294 } catch (ReadFailedException e) {
3295 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3297 /*Read failed. We don't know if a VPN exists or not.
3298 * Return primaryRd to halt caller execution, to be safe.*/
3299 return existingVpnName;
3301 if (vpnInstanceOpDataOptional.isPresent()) {
3302 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3304 existingVpnName = Optional.absent();
3306 return existingVpnName;
3309 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3310 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3313 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3314 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3317 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3318 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3321 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3322 String message = tuple.getMessage();
3323 logger.accept(message);
3327 protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3328 @Nonnull Subnetmap subnetMap) {
3329 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3330 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
3331 IpVersionChoice.IPV6, routerId, true)) {
3332 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3333 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3334 subnetMap.getId(), internetVpnId.getValue());
3336 neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, true);
3339 protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3340 @Nonnull Subnetmap subnetMap) {
3341 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3342 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
3343 IpVersionChoice.IPV6, routerId, false)) {
3344 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, false);
3345 LOG.info("removeV6PrivateSubnetToExtNetwork: withdraw IPv6 Private subnet {} from Internet VPN {}",
3346 subnetMap.getId(), internetVpnId.getValue());
3348 neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, false);