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 java.util.stream.Collectors;
40 import javax.annotation.Nonnull;
41 import javax.annotation.Nullable;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
45 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
46 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
50 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
51 import org.opendaylight.genius.infra.Datastore;
52 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
54 import org.opendaylight.genius.infra.TypedWriteTransaction;
55 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
56 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
57 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
58 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
59 import org.opendaylight.netvirt.elanmanager.api.IElanService;
60 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
61 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
62 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
63 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
64 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
65 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
66 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
178 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
179 import org.opendaylight.yangtools.yang.common.RpcError;
180 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
181 import org.opendaylight.yangtools.yang.common.RpcResult;
182 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
183 import org.slf4j.Logger;
184 import org.slf4j.LoggerFactory;
185 import org.slf4j.helpers.FormattingTuple;
186 import org.slf4j.helpers.MessageFormatter;
189 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
191 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
192 private static long LOCK_WAIT_TIME = 10L;
194 private final DataBroker dataBroker;
195 private final ManagedNewTransactionRunner txRunner;
196 private final NotificationPublishService notificationPublishService;
197 private final VpnRpcService vpnRpcService;
198 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
199 private final IElanService elanService;
200 private final NeutronvpnConfig neutronvpnConfig;
201 private final NeutronEvpnManager neutronEvpnManager;
202 private final NeutronEvpnUtils neutronEvpnUtils;
203 private final JobCoordinator jobCoordinator;
204 private final NeutronvpnUtils neutronvpnUtils;
205 private final IVpnManager vpnManager;
206 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
207 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
208 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
209 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
212 public NeutronvpnManager(
213 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
214 final VpnRpcService vpnRpcSrv, final IElanService elanService,
215 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
216 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
217 final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
218 this.dataBroker = dataBroker;
219 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
220 notificationPublishService = notiPublishService;
221 vpnRpcService = vpnRpcSrv;
222 this.elanService = elanService;
223 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
224 this.neutronvpnConfig = neutronvpnConfig;
225 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
226 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
227 this.jobCoordinator = jobCoordinator;
228 this.neutronvpnUtils = neutronvpnUtils;
229 this.vpnManager = vpnManager;
236 public void close() {
237 LOG.info("{} close", getClass().getSimpleName());
240 private void configureFeatures() {
241 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
242 Neutron.class).child(Features.class).child(
243 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
244 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
246 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
247 } catch (TransactionCommitFailedException e) {
248 LOG.warn("Error configuring feature {}", feature, e);
252 public String getOpenDaylightVniRangesConfig() {
253 return neutronvpnConfig.getOpendaylightVniRanges();
256 // TODO Clean up the exception handling
257 @SuppressWarnings("checkstyle:IllegalCatch")
258 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
259 NetworkAttributes.NetworkType networkType, long segmentationId) {
261 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
262 synchronized (subnetId.getValue().intern()) {
263 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
264 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
265 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
266 if (sn.isPresent()) {
267 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
268 subnetId.getValue());
271 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
272 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
273 .setNetworkType(networkType).setSegmentationId(segmentationId);
274 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
275 subnetId.getValue());
276 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
277 subnetMapIdentifier, subnetmapBuilder.build());
279 } catch (TransactionCommitFailedException | ReadFailedException e) {
280 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
282 // check if there are ports to update for already created Subnetmap node
283 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
284 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
285 if (entry.getValue().getValue().equals(subnetId.getValue())) {
286 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
287 unprocessedPortsMap.remove(entry.getKey());
292 protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) {
293 Subnetmap subnetmap = null;
294 SubnetmapBuilder builder = null;
295 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
296 .child(Subnetmap.class, new SubnetmapKey(subnetId))
299 synchronized (subnetId.getValue().intern()) {
300 Optional<Subnetmap> sn =
301 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
303 if (sn.isPresent()) {
304 builder = new SubnetmapBuilder(sn.get());
305 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
307 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
310 if (routerId != null) {
311 builder.setRouterId(routerId);
314 builder.setVpnId(vpnId);
316 builder.setInternetVpnId(internetvpnId);
318 subnetmap = builder.build();
319 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
320 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
322 } catch (ReadFailedException | TransactionCommitFailedException e) {
323 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
328 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
329 Uuid routerInterfacePortId, String fixedIp,
330 String routerIntfMacAddress, Uuid vpnId) {
331 Subnetmap subnetmap = null;
332 SubnetmapBuilder builder = null;
333 InstanceIdentifier<Subnetmap> id =
334 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
336 synchronized (subnetId.getValue().intern()) {
337 Optional<Subnetmap> sn =
338 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
340 if (sn.isPresent()) {
341 builder = new SubnetmapBuilder(sn.get());
342 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
343 subnetId.getValue());
345 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
346 subnetId.getValue());
349 builder.setRouterId(routerId);
350 builder.setRouterInterfacePortId(routerInterfacePortId);
351 builder.setRouterIntfMacAddress(routerIntfMacAddress);
352 builder.setRouterInterfaceFixedIp(fixedIp);
354 builder.setVpnId(vpnId);
356 subnetmap = builder.build();
357 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
358 subnetId.getValue());
359 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
361 } catch (ReadFailedException | TransactionCommitFailedException e) {
362 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
363 subnetId.getValue(), e);
367 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
368 Subnetmap subnetmap = null;
369 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
370 new SubnetmapKey(subnetId)).build();
371 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
373 synchronized (subnetId.getValue().intern()) {
374 Optional<Subnetmap> sn =
375 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
377 if (sn.isPresent()) {
378 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
379 if (null != portId) {
380 List<Uuid> portList = builder.getPortList();
381 if (null == portList) {
382 portList = new ArrayList<>();
384 portList.add(portId);
385 builder.setPortList(portList);
386 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
387 subnetId.getValue(), portId.getValue());
389 if (null != directPortId) {
390 List<Uuid> directPortList = builder.getDirectPortList();
391 if (null == directPortList) {
392 directPortList = new ArrayList<>();
394 directPortList.add(directPortId);
395 builder.setDirectPortList(directPortList);
396 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
397 directPortId.getValue());
399 subnetmap = builder.build();
400 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
403 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
404 + "cache ", subnetId.getValue(), portId.getValue());
405 unprocessedPortsMap.put(portId, subnetId);
408 } catch (ReadFailedException | TransactionCommitFailedException e) {
409 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
414 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId,
415 Uuid vpnId, Uuid portId) {
416 Subnetmap subnetmap = null;
417 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
418 .child(Subnetmap.class, new SubnetmapKey(subnetId))
421 synchronized (subnetId.getValue().intern()) {
422 Optional<Subnetmap> sn =
423 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
425 if (sn.isPresent()) {
426 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
427 if (routerId != null) {
428 builder.setRouterId(null);
430 if (networkId != null) {
431 builder.setNetworkId(null);
434 builder.setVpnId(null);
436 builder.setInternetVpnId(null);
437 if (portId != null && builder.getPortList() != null) {
438 List<Uuid> portList = builder.getPortList();
439 portList.remove(portId);
440 builder.setPortList(portList);
443 subnetmap = builder.build();
444 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
445 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
448 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
451 } catch (ReadFailedException | TransactionCommitFailedException e) {
452 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
457 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
458 Subnetmap subnetmap = null;
459 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
460 new SubnetmapKey(subnetId)).build();
462 synchronized (subnetId.getValue().intern()) {
463 Optional<Subnetmap> sn =
464 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
466 if (sn.isPresent()) {
467 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
468 if (null != portId && null != builder.getPortList()) {
469 List<Uuid> portList = builder.getPortList();
470 portList.remove(portId);
471 builder.setPortList(portList);
472 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
473 subnetId.getValue());
475 if (null != directPortId && null != builder.getDirectPortList()) {
476 List<Uuid> directPortList = builder.getDirectPortList();
477 directPortList.remove(directPortId);
478 builder.setDirectPortList(directPortList);
479 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
480 .getValue(), subnetId.getValue());
482 subnetmap = builder.build();
483 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
486 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
489 } catch (ReadFailedException | TransactionCommitFailedException e) {
490 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
491 subnetId.getValue(), e);
496 // TODO Clean up the exception handling
497 @SuppressWarnings("checkstyle:IllegalCatch")
498 protected void deleteSubnetMapNode(Uuid subnetId) {
499 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
500 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
501 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
503 synchronized (subnetId.getValue().intern()) {
504 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
505 subnetMapIdentifier);
507 } catch (TransactionCommitFailedException e) {
508 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
512 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
513 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
514 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
516 Optional<VpnInstance> vpnInstanceConfig =
517 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
519 if (!vpnInstanceConfig.isPresent()) {
520 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
523 VpnInstance vpnInstance = vpnInstanceConfig.get();
524 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
525 if (vpnInstance.getIpv4Family() != null) {
526 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
527 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
529 if (vpnInstance.getIpv6Family() != null) {
530 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
531 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
533 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
534 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
535 updateVpnInstanceBuilder.build());
536 } catch (ReadFailedException | TransactionCommitFailedException ex) {
537 LOG.warn("Error configuring feature ", ex);
541 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
542 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
543 String vpnName = vpnId.getValue();
544 VpnInstanceBuilder builder = null;
545 List<VpnTarget> vpnTargetList = new ArrayList<>();
546 boolean isLockAcquired = false;
547 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
548 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
550 Optional<VpnInstance> optionalVpn =
551 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
553 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
554 if (optionalVpn.isPresent()) {
555 builder = new VpnInstanceBuilder(optionalVpn.get());
556 LOG.debug("updating existing vpninstance node");
558 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
559 .setType(type).setL3vni(l3vni);
561 if (irt != null && !irt.isEmpty()) {
562 if (ert != null && !ert.isEmpty()) {
563 List<String> commonRT = new ArrayList<>(irt);
564 commonRT.retainAll(ert);
566 for (String common : commonRT) {
569 VpnTarget vpnTarget =
570 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
571 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
572 vpnTargetList.add(vpnTarget);
575 for (String importRT : irt) {
576 VpnTarget vpnTarget =
577 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
578 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
579 vpnTargetList.add(vpnTarget);
583 if (ert != null && !ert.isEmpty()) {
584 for (String exportRT : ert) {
585 VpnTarget vpnTarget =
586 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
587 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
588 vpnTargetList.add(vpnTarget);
592 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
594 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
595 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
597 if (rd != null && !rd.isEmpty()) {
598 ipv4vpnBuilder.setRouteDistinguisher(rd);
599 ipv6vpnBuilder.setRouteDistinguisher(rd);
602 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
603 builder.setIpv4Family(ipv4vpnBuilder.build());
605 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
606 builder.setIpv6Family(ipv6vpnBuilder.build());
608 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
609 builder.setIpv4Family(ipv4vpnBuilder.build());
611 VpnInstance newVpn = builder.build();
612 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
613 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
614 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
616 } catch (ReadFailedException | TransactionCommitFailedException e) {
617 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
619 if (isLockAcquired) {
620 vpnLock.unlock(vpnId);
625 private void deleteVpnMapsNode(Uuid vpnId) {
626 boolean isLockAcquired = false;
627 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
628 .child(VpnMap.class, new VpnMapKey(vpnId))
630 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
632 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
633 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
634 } catch (TransactionCommitFailedException e) {
635 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
637 if (isLockAcquired) {
638 vpnLock.unlock(vpnId);
643 protected void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
644 VpnMapBuilder builder;
645 boolean isLockAcquired = false;
646 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
647 .child(VpnMap.class, new VpnMapKey(vpnId))
650 Optional<VpnMap> optionalVpnMap =
651 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
653 if (optionalVpnMap.isPresent()) {
654 builder = new VpnMapBuilder(optionalVpnMap.get());
656 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
660 builder.setName(name);
662 if (tenantId != null) {
663 builder.setTenantId(tenantId);
665 if (router != null) {
666 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
667 List<RouterIds> rtrIds = builder.getRouterIds();
668 if (rtrIds == null) {
669 rtrIds = Collections.singletonList(vpnRouterId);
671 rtrIds.add(vpnRouterId);
673 builder.setRouterIds(rtrIds);
675 if (networks != null) {
676 List<Uuid> nwList = builder.getNetworkIds();
677 if (nwList == null) {
678 nwList = new ArrayList<>();
680 nwList.addAll(networks);
681 builder.setNetworkIds(nwList);
684 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
685 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
686 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
688 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
689 } catch (ReadFailedException | TransactionCommitFailedException e) {
690 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
692 if (isLockAcquired) {
693 vpnLock.unlock(vpnId);
698 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
699 boolean isLockAcquired = false;
700 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
701 .child(VpnMap.class, new VpnMapKey(vpnId))
703 Optional<VpnMap> optionalVpnMap;
706 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
708 } catch (ReadFailedException e) {
709 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
712 if (optionalVpnMap.isPresent()) {
713 VpnMap vpnMap = optionalVpnMap.get();
714 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
715 List<RouterIds> rtrIds = vpnMap.getRouterIds();
716 if (rtrIds == null) {
717 rtrIds = new ArrayList<>();
719 if (routerId != null) {
720 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
721 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
722 vpnMapBuilder.setRouterIds(rtrIds);
724 // remove entire node in case of internal VPN
725 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
726 LOG.debug("removing vpnMaps node: {} ", vpnId);
727 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
729 } catch (TransactionCommitFailedException e) {
730 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
732 if (isLockAcquired) {
733 vpnLock.unlock(vpnId);
737 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
738 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
739 vpnMapBuilder.setRouterIds(rtrIds);
740 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
743 if (networkIds != null) {
744 List<Uuid> vpnNw = vpnMap.getNetworkIds();
745 vpnNw.removeAll(networkIds);
746 if (vpnNw.isEmpty()) {
747 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
748 vpnMapBuilder.setNetworkIds(null);
750 vpnMapBuilder.setNetworkIds(vpnNw);
755 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
756 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
757 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
758 vpnMapBuilder.build());
759 } catch (TransactionCommitFailedException e) {
760 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
762 if (isLockAcquired) {
763 vpnLock.unlock(vpnId);
767 LOG.error("VPN : {} not found", vpnId.getValue());
769 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
772 private void deleteVpnInstance(Uuid vpnId) {
773 boolean isLockAcquired = false;
774 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
775 .child(VpnInstance.class,
776 new VpnInstanceKey(vpnId.getValue()))
779 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
780 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
781 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
782 } catch (TransactionCommitFailedException e) {
783 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
785 if (isLockAcquired) {
786 vpnLock.unlock(vpnId);
791 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
792 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn,
793 Subnetmap sn, VpnInterface vpnIface) {
794 List<Adjacency> adjList = new ArrayList<>();
795 if (vpnIface != null) {
796 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
798 String infName = port.getUuid().getValue();
799 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
800 for (FixedIps ip : port.getFixedIps()) {
801 String ipValue = ip.getIpAddress().stringValue();
802 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
803 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
806 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
807 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
809 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
810 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
811 //Create Neutron port adjacency if VPN presence is existing for subnet
812 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
813 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
814 .setSubnetId(ip.getSubnetId()).build();
815 if (!adjList.contains(vmAdj)) {
819 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
820 if (snTemp != null && snTemp.getInternetVpnId() != null) {
821 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
822 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
824 if (routerId != null) {
825 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
826 if (rtr != null && rtr.getRoutes() != null) {
827 List<Routes> routeList = rtr.getRoutes();
828 // create extraroute Adjacence for each ipValue,
829 // because router can have IPv4 and IPv6 subnet ports, or can have
830 // more that one IPv4 subnet port or more than one IPv6 subnet port
831 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
832 if (!erAdjList.isEmpty()) {
833 adjList.addAll(erAdjList);
838 return new AdjacenciesBuilder().setAdjacency(adjList).build();
841 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
842 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
843 boolean isRouterInterface = false;
844 if (port.getDeviceOwner() != null) {
845 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
847 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
848 String infName = port.getUuid().getValue();
849 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
850 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
853 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
854 Port port, Subnetmap sn, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
855 String infName = port.getUuid().getValue();
856 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
857 Optional<VpnInterface> optionalVpnInterface = null;
858 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
859 vpnId, internetVpnId, infName);
861 optionalVpnInterface = SingleTransactionDataBroker
862 .syncReadOptional(dataBroker, LogicalDatastoreType
863 .CONFIGURATION, vpnIfIdentifier);
864 } catch (ReadFailedException e) {
865 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
868 if (!optionalVpnInterface.isPresent()) {
871 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
872 sn != null ? sn.getSubnetIp() : "null");
873 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency();
874 List<Adjacency> updatedAdjsList = new ArrayList<>();
875 boolean isIpFromAnotherSubnet = false;
876 for (Adjacency adj : vpnAdjsList) {
877 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
878 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
879 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
880 isIpFromAnotherSubnet = true;
882 updatedAdjsList.add(adj);
885 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
886 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
889 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
890 String.valueOf(adjString), wrtConfigTxn);
892 if (internetVpnId != null) {
893 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
894 String.valueOf(adjString), wrtConfigTxn);
897 if (port.getDeviceOwner()
898 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
899 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
900 if (rtr != null && rtr.getRoutes() != null) {
901 List<Routes> extraRoutesToRemove = new ArrayList<>();
902 for (Routes rt: rtr.getRoutes()) {
903 if (rt.getNexthop().toString().equals(adjString)) {
904 extraRoutesToRemove.add(rt);
908 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
909 extraRoutesToRemove, vpnId);
910 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
912 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
917 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
919 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
921 if (!isIpFromAnotherSubnet) {
922 // no more subnetworks for neutron port
923 if (sn != null && sn.getRouterId() != null) {
924 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
926 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
932 // TODO Clean up the exception handling
933 @SuppressWarnings("checkstyle:IllegalCatch")
934 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
935 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
936 if (wrtConfigTxn == null) {
937 ListenableFutures.addErrorLogging(
938 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
939 tx -> deleteVpnInterface(infName, vpnId, tx)),
940 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
944 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
945 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
946 Optional<VpnInterface> optionalVpnInterface;
948 optionalVpnInterface =
949 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
951 } catch (ReadFailedException ex) {
952 LOG.error("Error during deletion of vpninterface {}", infName, ex);
955 if (!optionalVpnInterface.isPresent()) {
956 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
960 VpnInterface vpnInterface = optionalVpnInterface.get();
961 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
963 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
964 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
965 if (!vpnList.isEmpty()) {
966 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
967 + "List not empty", infName);
970 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
971 .setVpnInstanceNames(vpnList);
972 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
976 LOG.debug("Deleting vpn interface {}", infName);
977 wrtConfigTxn.delete(vpnIfIdentifier);
980 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
981 TypedWriteTransaction<Datastore.Configuration> writeConfigTxn,
983 if (vpnId == null || port == null) {
986 String infName = port.getUuid().getValue();
987 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
989 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
990 .syncReadOptional(dataBroker, LogicalDatastoreType
991 .CONFIGURATION, vpnIfIdentifier);
992 if (optionalVpnInterface.isPresent()) {
993 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
995 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
996 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
998 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
999 .setVpnInstanceNames(listVpn);
1000 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1001 LOG.debug("Updating vpn interface {}", infName);
1002 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1003 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1004 while (adjacencyIter.hasNext()) {
1005 Adjacency adjacency = adjacencyIter.next();
1006 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1009 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1010 InstanceIdentifier<LearntVpnVipToPort> id =
1011 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1012 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1013 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1014 LogicalDatastoreType.OPERATIONAL, id);
1015 if (optionalVpnVipToPort.isPresent()) {
1016 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1018 if (listVpn == null || listVpn.isEmpty()) {
1019 adjacencyIter.remove();
1021 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1022 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1023 mipToQuery, infName, vpnId.getValue());
1026 List<FixedIps> ips = port.getFixedIps();
1027 for (FixedIps ip : ips) {
1028 String ipValue = ip.getIpAddress().stringValue();
1030 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1033 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1034 ipValue, writeConfigTxn);
1036 if (listVpn == null || listVpn.isEmpty()) {
1037 if (sm != null && sm.getRouterId() != null) {
1038 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1040 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1042 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1045 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1047 } catch (ReadFailedException ex) {
1048 LOG.error("Update of vpninterface {} failed", infName, ex);
1052 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
1054 TypedWriteTransaction<Datastore.Configuration> writeConfigTxn) {
1055 if (vpnId == null || port == null) {
1058 boolean isLockAcquired = false;
1059 String infName = port.getUuid().getValue();
1060 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1063 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1064 Optional<VpnInterface> optionalVpnInterface =
1065 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1067 if (optionalVpnInterface.isPresent()) {
1068 VpnInstanceNames vpnInstance = VpnHelper
1069 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1070 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1071 .get().getVpnInstanceNames());
1072 if (oldVpnId != null
1073 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1074 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1076 if (vpnId.getValue() != null
1077 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1078 listVpn.add(vpnInstance);
1080 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1081 .setVpnInstanceNames(listVpn);
1082 LOG.debug("Updating vpn interface {}", infName);
1083 if (!isBeingAssociated) {
1084 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1085 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1086 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1087 while (adjacencyIter.hasNext()) {
1088 Adjacency adjacency = adjacencyIter.next();
1089 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1090 InstanceIdentifier<LearntVpnVipToPort> id =
1091 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1092 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1093 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1094 LogicalDatastoreType.OPERATIONAL, id);
1095 if (optionalVpnVipToPort.isPresent()) {
1096 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1097 + "from VPN {}", infName, vpnId, oldVpnId);
1098 adjacencyIter.remove();
1099 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1101 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1102 mipToQuery, infName, vpnId.getValue());
1105 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1106 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1108 List<FixedIps> ips = port.getFixedIps();
1109 for (FixedIps ip : ips) {
1110 String ipValue = ip.getIpAddress().stringValue();
1111 if (oldVpnId != null) {
1112 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1113 ipValue, writeConfigTxn);
1115 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1116 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1118 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1120 LOG.error("VPN Interface {} not found", infName);
1122 } catch (ReadFailedException ex) {
1123 LOG.error("Updation of vpninterface {} failed", infName, ex);
1125 if (isLockAcquired) {
1126 interfaceLock.unlock(infName);
1131 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
1132 List<String> ert, Uuid router, List<Uuid> networks) {
1134 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1136 // Update VPN Instance node
1137 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1139 // Update local vpn-subnet DS
1140 updateVpnMaps(vpn, name, router, tenant, networks);
1142 if (router != null) {
1143 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1144 if (existingVpn != null) {
1145 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1146 // if before reboot, router was already associated to VPN, should not proceed associating router to
1147 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1148 // preserved upon reboot.
1149 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1150 // RouterInterfacesMap via #createVPNInterface call.
1151 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1152 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1155 associateRouterToInternalVpn(vpn, router);
1160 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1161 * specified Neutron Networks and Routers.
1163 * @param vpnId Uuid of the VPN tp be created
1164 * @param name Representative name of the new VPN
1165 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1166 * @param rdList Route-distinguisher for the VPN
1167 * @param irtList A list of Import Route Targets
1168 * @param ertList A list of Export Route Targets
1169 * @param routerIdsList ist of neutron router Id to associate with created VPN
1170 * @param networkList UUID of the neutron network the VPN may be associated to
1171 * @param type Type of the VPN Instance
1172 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1173 * @throws Exception if association of L3VPN failed
1175 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1176 List<String> ertList, @Nullable List<Uuid> routerIdsList, List<Uuid> networkList,
1177 VpnInstance.Type type, long l3vni) throws Exception {
1179 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1181 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1182 for (Uuid routerId : routerIdsList) {
1183 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1184 ipVersChoices = ipVersChoices.addVersion(vers);
1187 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1189 // Please note that router and networks will be filled into VPNMaps
1190 // by subsequent calls here to associateRouterToVpn and
1191 // associateNetworksToVpn
1192 updateVpnMaps(vpnId, name, null, tenantId, null);
1193 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1194 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1197 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1198 for (Uuid routerId : routerIdsList) {
1199 associateRouterToVpn(vpnId, routerId);
1202 if (networkList != null) {
1203 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1204 if (!failStrings.isEmpty()) {
1205 LOG.error("VPN {} association to networks failed for networks: {}. ",
1206 vpnId.getValue(), failStrings.toString());
1207 throw new Exception(failStrings.toString());
1213 * It handles the invocations to the createVPN RPC method.
1216 // TODO Clean up the exception handling
1217 @SuppressWarnings("checkstyle:IllegalCatch")
1218 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1220 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1221 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1222 List<RpcError> errorList = new ArrayList<>();
1223 int failurecount = 0;
1224 int warningcount = 0;
1226 List<L3vpn> vpns = input.getL3vpn();
1228 vpns = Collections.emptyList();
1230 for (L3vpn vpn : vpns) {
1231 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1232 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1233 formatAndLog(LOG::warn,
1234 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1235 vpn.getId().getValue())));
1239 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1240 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1241 formatAndLog(LOG::warn,
1242 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1243 vpn.getId().getValue())));
1247 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1249 if (vpn.getL3vni() != null) {
1250 l3vni = vpn.getL3vni();
1253 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1254 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1255 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1256 formatAndLog(LOG::warn,
1257 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1258 + "is already configured",
1259 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1263 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1264 if (operationalVpn.isPresent()) {
1265 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1266 formatAndLog(LOG::error,
1267 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1268 + "is still available. Please retry creation of a new vpn with the same RD"
1269 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1270 vpn.getRouteDistinguisher().get(0))));
1274 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1275 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1276 routerIdsList = vpn.getRouterIds();
1277 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1278 routerId : routerIdsList) {
1279 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1280 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1281 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1282 + "{}", vpn.getId(), routerId.getRouterId())));
1286 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1287 if (vpnId != null) {
1288 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1289 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1290 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1291 vpnId.getValue())));
1297 if (vpn.getNetworkIds() != null) {
1298 int initialWarningCount = warningcount;
1299 for (Uuid nw : vpn.getNetworkIds()) {
1300 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1301 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1302 if (network == null) {
1303 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1304 formatAndLog(LOG::warn,
1305 "Creation of L3VPN failed for VPN {} due to network not found {}",
1306 vpn.getId().getValue(), nw.getValue())));
1308 } else if (vpnId != null) {
1309 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1310 formatAndLog(LOG::warn,
1311 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1312 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1313 vpnId.getValue())));
1317 if (warningcount != initialWarningCount) {
1321 List<Uuid> rtrIdsList = new ArrayList<>();
1322 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1323 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1324 rtrId : vpn.getRouterIds()) {
1325 rtrIdsList.add(rtrId.getRouterId());
1329 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1330 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1331 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1332 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1333 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1334 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1335 vpnInstanceType, l3vni);
1336 } catch (Exception ex) {
1337 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1338 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1343 // if at least one succeeds; result is success
1344 // if none succeeds; result is failure
1345 if (failurecount + warningcount == vpns.size()) {
1346 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1348 List<String> errorResponseList = new ArrayList<>();
1349 if (!errorList.isEmpty()) {
1350 for (RpcError rpcError : errorList) {
1351 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1352 + ", ErrorMessage: " + rpcError.getMessage());
1355 errorResponseList.add("Operation successful with no errors");
1357 opBuilder.setResponse(errorResponseList);
1358 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1364 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1367 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1369 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1370 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1371 Uuid inputVpnId = input.getId();
1372 List<VpnInstance> vpns = new ArrayList<>();
1373 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1376 if (inputVpnId == null) {
1378 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1380 Optional<VpnInstances> optionalVpns =
1381 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1383 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1384 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1385 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1386 // from getL3VPN output
1387 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1390 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1396 opBuilder.setL3vpnInstances(l3vpnList);
1397 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1401 String name = inputVpnId.getValue();
1402 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1403 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1404 // read VpnInstance Info
1405 Optional<VpnInstance> optionalVpn =
1406 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1408 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1410 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1411 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1412 vpns.add(optionalVpn.get());
1415 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1416 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1420 for (VpnInstance vpnInstance : vpns) {
1421 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1422 // create VpnMaps id
1423 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1424 List<String> rd = Collections.EMPTY_LIST;
1425 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1426 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1427 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1428 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1430 List<String> ertList = new ArrayList<>();
1431 List<String> irtList = new ArrayList<>();
1433 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1434 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1435 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1436 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1437 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1438 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1439 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1441 if (!vpnTargetList.isEmpty()) {
1442 for (VpnTarget vpnTarget : vpnTargetList) {
1443 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1444 ertList.add(vpnTarget.getVrfRTValue());
1446 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1447 irtList.add(vpnTarget.getVrfRTValue());
1449 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1450 ertList.add(vpnTarget.getVrfRTValue());
1451 irtList.add(vpnTarget.getVrfRTValue());
1457 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1459 if (vpnInstance.getL3vni() != null) {
1460 l3vpn.setL3vni(vpnInstance.getL3vni());
1462 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1463 .class, new VpnMapKey(vpnId)).build();
1464 Optional<VpnMap> optionalVpnMap =
1465 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1467 if (optionalVpnMap.isPresent()) {
1468 VpnMap vpnMap = optionalVpnMap.get();
1469 List<Uuid> rtrIds = new ArrayList<>();
1470 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1471 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1472 rtrIds.add(rtrId.getRouterId());
1475 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1476 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1477 .setName(vpnMap.getName());
1480 l3vpnList.add(l3vpn.build());
1483 opBuilder.setL3vpnInstances(l3vpnList);
1484 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1486 } catch (ReadFailedException ex) {
1487 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1488 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1494 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1497 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1499 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1500 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1501 List<RpcError> errorList = new ArrayList<>();
1503 int failurecount = 0;
1504 int warningcount = 0;
1505 List<Uuid> vpns = input.getId();
1506 for (Uuid vpn : vpns) {
1510 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1511 InstanceIdentifier<VpnInstance> vpnIdentifier =
1512 InstanceIdentifier.builder(VpnInstances.class)
1513 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1514 Optional<VpnInstance> optionalVpn =
1515 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1517 if (optionalVpn.isPresent()) {
1520 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1521 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1524 } catch (ReadFailedException ex) {
1525 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1526 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1531 // if at least one succeeds; result is success
1532 // if none succeeds; result is failure
1533 if (failurecount + warningcount == vpns.size()) {
1534 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1536 List<String> errorResponseList = new ArrayList<>();
1537 if (!errorList.isEmpty()) {
1538 for (RpcError rpcError : errorList) {
1539 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1540 + ", ErrorMessage: " + rpcError.getMessage());
1543 errorResponseList.add("Operation successful with no errors");
1545 opBuilder.setResponse(errorResponseList);
1546 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1551 public void createVpnInstanceForSubnet(Uuid subnetId) {
1552 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1553 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1556 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1557 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1558 removeVpn(subnetId);
1561 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1562 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1563 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1564 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1566 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1567 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1570 if (vpnId != null) {
1571 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1572 if (vpnMap == null) {
1573 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1574 + " cannot add subnet {} to VPN", vpnId.getValue(),
1578 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1579 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1580 if (isVpnOfTypeL2(vpnInstance)) {
1581 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1582 NeutronEvpnUtils.Operation.ADD);
1585 if (internetVpnId != null) {
1586 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1587 if (vpnMap == null) {
1588 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1589 + "subnet {} to VPN", internetVpnId.getValue(),
1594 final Uuid internetId = internetVpnId;
1595 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1596 List<Uuid> portList = sn.getPortList();
1597 if (portList != null) {
1598 for (final Uuid portId : portList) {
1599 String vpnInfName = portId.getValue();
1600 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1601 Port port = neutronvpnUtils.getNeutronPort(portId);
1603 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1604 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1607 final Boolean isRouterInterface = port.getDeviceOwner()
1608 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1609 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1610 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1611 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1613 if (vpnIface == null) {
1614 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1615 Set<Uuid> listVpn = new HashSet<>();
1616 if (vpnId != null) {
1619 if (internetId != null) {
1620 listVpn.add(internetId);
1622 writeVpnInterfaceToDs(listVpn,
1623 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1624 if (sn.getRouterId() != null) {
1625 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1628 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1629 if (vpnId != null) {
1630 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1632 if (internetId != null) {
1633 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1642 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) {
1643 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1644 "removeSubnetFromVpn: at least one VPN must be not null");
1645 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1646 vpnId, internetVpnId);
1647 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1649 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1652 VpnMap vpnMap = null;
1653 VpnInstance vpnInstance = null;
1654 if (vpnId != null) {
1655 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1656 if (vpnMap == null) {
1657 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1658 vpnId.getValue(), subnet.getValue());
1661 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1663 if (internetVpnId == null) {
1664 internetVpnId = sn.getInternetVpnId();
1666 if (internetVpnId != null) {
1667 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1668 if (vpnMap == null) {
1669 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1670 + " from Internet VPN",
1671 internetVpnId.getValue(), subnet.getValue());
1675 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1676 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1677 NeutronEvpnUtils.Operation.DELETE);
1679 boolean subnetVpnAssociation = false;
1680 if (vpnId != null && sn.getVpnId() != null
1681 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1682 subnetVpnAssociation = true;
1683 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1684 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1685 subnetVpnAssociation = true;
1687 if (subnetVpnAssociation == false) {
1688 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1689 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1692 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1693 List<Uuid> portList = sn.getPortList();
1694 final Uuid internetId = internetVpnId;
1695 if (portList != null) {
1696 for (final Uuid portId : portList) {
1697 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1698 final Port port = neutronvpnUtils.getNeutronPort(portId);
1699 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1700 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1701 CONFIGURATION, tx -> {
1703 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1706 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1707 + "port is absent in Neutron config DS", portId.getValue(),
1713 //update subnet-vpn association
1714 removeFromSubnetNode(subnet, null, null, vpnId, null);
1717 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1718 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1719 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1721 Uuid internalVpnId = sm.getVpnId();
1722 if (internalVpnId == null) {
1723 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1724 sm.getId().getValue());
1727 if (isBeingAssociated) {
1728 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1730 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1733 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1734 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1735 if (isBeingAssociated) {
1736 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1737 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn);
1739 removeInternetVpnFromVpnInterface(vpn,
1740 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1745 // Check for ports on this subnet and update association of
1746 // corresponding vpn-interfaces to internet vpn
1747 List<Uuid> portList = sm.getPortList();
1748 if (portList != null) {
1749 for (Uuid port : portList) {
1750 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1751 port.getValue(), isBeingAssociated);
1752 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1753 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1755 if (isBeingAssociated) {
1756 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1759 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1766 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1767 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1768 oldVpnId.getValue(), newVpnId.getValue());
1769 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1770 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1771 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1772 Uuid vpnExtUuid = netIsExternal ? null
1773 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1774 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1776 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1779 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1780 * associated with internet BGP-VPN.
1782 if (vpnExtUuid != null) {
1783 //Update V6 Internet default route match with new VPN metadata
1784 neutronvpnUtils.updateVpnInstanceWithFallback(vpnExtUuid, isBeingAssociated);
1786 //Update Router Interface first synchronously.
1787 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1788 ListenableFuture<Void> future =
1789 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1790 tx -> updateVpnInterface(newVpnId, oldVpnId,
1791 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1792 isBeingAssociated, true, tx));
1793 Futures.addCallback(future, new FutureCallback<Void>() {
1795 public void onSuccess(Void result) {
1796 // Check for ports on this subnet and update association of
1797 // corresponding vpn-interfaces to external vpn
1798 List<Uuid> portList = sn.getPortList();
1799 if (portList != null) {
1800 for (Uuid port : portList) {
1801 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1802 port.getValue(), isBeingAssociated);
1803 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1804 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1805 tx -> updateVpnInterface(newVpnId, oldVpnId,
1806 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1813 public void onFailure(Throwable throwable) {
1815 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1817 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1819 }, MoreExecutors.directExecutor());
1824 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1825 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1826 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1829 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1830 synchronized (routerId.getValue().intern()) {
1831 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1833 Optional<RouterInterfaces> optRouterInterfaces =
1834 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1835 routerInterfacesId);
1836 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1837 .setInterfaceId(interfaceName).build();
1838 if (optRouterInterfaces.isPresent()) {
1839 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1840 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1843 // TODO Shouldn't we be doing something with builder and interfaces?
1844 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1845 // List<Interfaces> interfaces = new ArrayList<>();
1846 // interfaces.add(routerInterface);
1848 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1849 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1852 } catch (ReadFailedException | TransactionCommitFailedException e) {
1853 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1858 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1859 synchronized (routerId.getValue().intern()) {
1860 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1862 Optional<RouterInterfaces> optRouterInterfaces =
1863 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1864 routerInterfacesId);
1865 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1866 .setInterfaceId(interfaceName).build();
1867 if (optRouterInterfaces.isPresent()) {
1868 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1869 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1870 if (interfaces != null && interfaces.remove(routerInterface)) {
1871 if (interfaces.isEmpty()) {
1872 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1873 routerInterfacesId);
1875 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1876 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1880 } catch (ReadFailedException | TransactionCommitFailedException e) {
1881 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1887 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1888 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1889 * route will be ignored.
1891 * @param vpnName the VPN identifier
1892 * @param interVpnLinkRoutes The list of static routes
1893 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1895 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1896 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1897 for (Routes route : interVpnLinkRoutes) {
1898 String nexthop = route.getNexthop().stringValue();
1899 String destination = route.getDestination().stringValue();
1900 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1901 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1902 AddStaticRouteInput rpcInput =
1903 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1904 .setVpnInstanceName(vpnName.getValue())
1906 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1907 RpcResult<AddStaticRouteOutput> rpcResult;
1909 rpcResult = labelOuputFtr.get();
1910 if (rpcResult.isSuccessful()) {
1911 LOG.debug("Label generated for destination {} is: {}",
1912 destination, rpcResult.getResult().getLabel());
1914 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1915 destination, nexthop, rpcResult.getErrors());
1917 } catch (InterruptedException | ExecutionException e) {
1918 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1919 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1922 // Any other case is a fault.
1923 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1924 route.getDestination().stringValue(), nexthop);
1931 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1932 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1934 * @param vpnName the VPN identifier
1935 * @param interVpnLinkRoutes The list of static routes
1936 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1938 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1939 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1940 for (Routes route : interVpnLinkRoutes) {
1941 String nexthop = route.getNexthop().stringValue();
1942 String destination = route.getDestination().stringValue();
1943 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1944 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1945 RemoveStaticRouteInput rpcInput =
1946 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1947 .setVpnInstanceName(vpnName.getValue())
1950 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1951 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1953 // Any other case is a fault.
1954 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1955 route.getDestination().stringValue(), nexthop);
1962 * Returns true if the specified nexthop is the other endpoint in an
1963 * InterVpnLink, regarding one of the VPN's point of view.
1965 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1967 interVpnLink != null
1968 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1969 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1970 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1971 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1975 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
1976 List<Adjacency> adjList = new ArrayList<>();
1977 Map<String, List<String>> adjMap = new HashMap<>();
1978 for (Routes route : routeList) {
1979 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1980 LOG.error("Incorrect input received for extra route. {}", route);
1982 String nextHop = route.getNexthop().stringValue();
1983 String destination = route.getDestination().stringValue();
1984 if (!nextHop.equals(fixedIp)) {
1985 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1988 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
1990 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1991 if (!hops.contains(nextHop)) {
1997 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
1998 final String destination = entry.getKey();
1999 final List<String> ipList = entry.getValue();
2000 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2001 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2002 .withKey(new AdjacencyKey(destination)).build();
2008 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2009 checkAlarmExtraRoutes(vpnId, routeList);
2011 for (Routes route : routeList) {
2012 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2013 LOG.error("Incorrect input received for extra route. {}", route);
2015 String nextHop = route.getNexthop().stringValue();
2016 String destination = route.getDestination().stringValue();
2017 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2019 if (infName != null) {
2020 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2021 destination, vpnId.getValue(), nextHop, infName);
2022 boolean isLockAcquired = false;
2024 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2025 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2026 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2027 .child(Adjacency.class, new AdjacencyKey(destination));
2028 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2029 LogicalDatastoreType.CONFIGURATION, path);
2030 if (existingAdjacency.isPresent()
2031 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2032 LOG.error("The route with destination {} nextHop {} is already present as"
2033 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2034 destination, nextHop, infName);
2037 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2038 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2039 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2040 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2041 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2043 } catch (TransactionCommitFailedException e) {
2044 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2045 destination, nextHop, e);
2046 } catch (ReadFailedException e) {
2047 LOG.error("Exception on reading data-store ", e);
2049 if (isLockAcquired) {
2050 interfaceLock.unlock(infName);
2054 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2055 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2062 * This method setup or down an alarm about extra route fault.
2063 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2064 * available RDs, then an alarm and an error is generated.<br>
2065 * <b>Be careful</b> the routeList could be changed.
2067 * @param vpnId the vpnId of vpn to control.
2068 * @param routeList the list of router to check, it could be modified.
2070 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2071 if (!neutronvpnAlarm.isAlarmEnabled()) {
2072 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2075 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2076 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2077 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2081 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2082 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2083 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2087 for (Routes route : routeList) {
2088 // count the number of nexthops for each same route.getDestingation().getValue()
2089 String destination = route.getDestination().stringValue();
2090 String nextHop = route.getNexthop().stringValue();
2091 List<String> nextHopList = new ArrayList<>();
2092 nextHopList.add(nextHop);
2094 for (Routes routeTmp : routeList) {
2095 String routeDest = routeTmp.getDestination().stringValue();
2096 if (!destination.equals(routeDest)) {
2099 String routeNextH = routeTmp.getNexthop().stringValue();
2100 if (nextHop.equals(routeNextH)) {
2104 nextHopList.add(routeTmp.getNexthop().stringValue());
2106 final List<String> rdList = new ArrayList<>();
2107 if (vpnInstance.getIpv4Family() != null
2108 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2109 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2115 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2116 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2117 if (rd != null && !rdList.contains(rd)) {
2122 // 1. VPN Instance Name
2123 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2126 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2127 Uuid routerUuid = routerUuidList.get(0);
2128 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2129 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2131 // 3. List of RDs associated with the VPN
2132 detailsAlarm.append(" List of RDs associated with the VPN: ");
2133 for (String s : rdList) {
2134 detailsAlarm.append(s);
2135 detailsAlarm.append(", ");
2138 // 4. Prefix in question
2139 detailsAlarm.append(" for prefix: ");
2140 detailsAlarm.append(route.getDestination().stringValue());
2142 // 5. List of NHs for the prefix
2143 detailsAlarm.append(" for nextHops: ");
2144 for (String s : nextHopList) {
2145 detailsAlarm.append(s);
2146 detailsAlarm.append(", ");
2149 if (rdList.size() < nbNextHops) {
2150 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2152 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2157 // TODO Clean up the exception handling
2158 @SuppressWarnings("checkstyle:IllegalCatch")
2159 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2160 for (Routes route : routeList) {
2161 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2162 boolean isLockAcquired = false;
2163 String nextHop = route.getNexthop().stringValue();
2164 String destination = route.getDestination().stringValue();
2165 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2167 if (infName == null) {
2168 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2169 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2170 // Proceed to remove the next extra-route
2173 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2174 destination, vpnId.getValue(), nextHop, infName);
2176 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2177 InstanceIdentifier.builder(VpnInterfaces.class)
2178 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2179 .augmentation(Adjacencies.class)
2180 .child(Adjacency.class, new AdjacencyKey(destination))
2184 // Looking for existing prefix in MDSAL database
2185 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2186 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2187 boolean updateNextHops = false;
2188 List<String> nextHopList = new ArrayList<>();
2189 if (adjacency.isPresent()) {
2190 List<String> nhListRead = adjacency.get().getNextHopIpList();
2191 if (nhListRead.size() > 1) { // ECMP case
2192 for (String nextHopRead : nhListRead) {
2193 if (nextHopRead.equals(nextHop)) {
2194 updateNextHops = true;
2196 nextHopList.add(nextHopRead);
2202 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2203 if (updateNextHops) {
2204 // An update must be done, not including the current next hop
2205 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2206 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2207 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2208 .setNextHopIpList(nextHopList)
2209 .withKey(new AdjacencyKey(destination))
2211 Adjacencies erAdjs =
2212 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2213 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2214 .addAugmentation(Adjacencies.class, erAdjs).build();
2215 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2216 vpnIfIdentifier, vpnIf);
2218 // Remove the whole route
2219 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2220 adjacencyIdentifier);
2221 LOG.trace("extra route {} deleted successfully", route);
2223 } catch (TransactionCommitFailedException | ReadFailedException e) {
2224 LOG.error("exception in deleting extra route with destination {} for interface {}",
2225 destination, infName, e);
2227 if (isLockAcquired) {
2228 interfaceLock.unlock(infName);
2232 LOG.error("Incorrect input received for extra route: {}", route);
2237 public void removeVpn(Uuid vpnId) {
2239 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2240 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2241 // dissociate router
2242 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2243 for (RouterIds routerId : routerIdsList) {
2244 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2246 List<Uuid> rtrIdsList = routerIdsList.stream().map(routerId -> routerId.getRouterId())
2247 .collect(Collectors.toList());
2248 if (rtrIdsList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2249 // dissociate networks
2250 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2253 // remove entire vpnMaps node
2254 deleteVpnMapsNode(vpnId);
2256 // remove vpn-instance
2257 deleteVpnInstance(vpnId);
2258 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2261 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2262 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2265 // TODO Clean up the exception handling
2266 @SuppressWarnings("checkstyle:IllegalCatch")
2267 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2268 updateVpnMaps(vpnId, null, routerId, null, null);
2269 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2270 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2271 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2272 for (Subnetmap sn : subMapList) {
2273 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2274 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2275 if (!ipVersion.isIpVersionChosen(ipVers)) {
2276 ipVersion = ipVersion.addVersion(ipVers);
2279 if (ipVersion != IpVersionChoice.UNDEFINED) {
2280 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", ipVersion,
2282 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2286 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2287 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2289 } catch (Exception e) {
2290 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2291 .getValue(), vpnId.getValue(), e);
2295 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2296 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2297 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2298 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2299 for (Uuid subnet : routerSubnets) {
2300 IpVersionChoice version = NeutronvpnUtils
2301 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2302 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2303 addSubnetToVpn(vpnId, subnet, null);
2305 addSubnetToVpn(vpnId, subnet, internetVpnId);
2310 // TODO Clean up the exception handling
2311 @SuppressWarnings("checkstyle:IllegalCatch")
2312 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2314 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2315 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2316 for (Subnetmap sn : subMapList) {
2317 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2318 if (ipVersion.isIpVersionChosen(ipVers)) {
2319 ipVersion = ipVersion.addVersion(ipVers);
2321 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2322 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2324 if (ipVersion != IpVersionChoice.UNDEFINED) {
2325 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2327 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2330 clearFromVpnMaps(vpnId, routerId, null);
2332 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2333 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2335 } catch (Exception e) {
2336 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2337 .getValue(), vpnId.getValue(), e);
2342 * Parses and associates networks list with given VPN.
2344 * @param vpnId Uuid of given VPN.
2345 * @param networkList List list of network Ids (Uuid), which will be associated.
2346 * @return list of formatted strings with detailed error messages.
2349 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2350 List<String> failedNwList = new ArrayList<>();
2351 HashSet<Uuid> passedNwList = new HashSet<>();
2352 if (networkList.isEmpty()) {
2353 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2354 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2356 return failedNwList;
2358 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2359 if (vpnInstance == null) {
2360 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2361 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2362 + "in ConfigDS", vpnId.getValue()));
2363 return failedNwList;
2366 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2367 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2369 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2370 + "associated with", vpnId.getValue()));
2371 return failedNwList;
2373 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2374 for (Uuid nw : networkList) {
2375 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2376 if (network == null) {
2377 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2378 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2382 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2383 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2384 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2385 nw.getValue(), vpnId.getValue());
2386 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2387 nw.getValue(), vpnId.getValue()));
2390 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2391 if (networkVpnId != null) {
2392 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2393 nw.getValue(), networkVpnId.getValue());
2394 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2395 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2398 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2399 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2400 nw.getValue(), vpnId.getValue());
2401 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2402 nw.getValue(), vpnId.getValue()));
2405 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2406 if (subnetmapList == null || subnetmapList.isEmpty()) {
2407 passedNwList.add(nw);
2410 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2413 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2414 for (Subnetmap subnetmap : subnetmapList) {
2415 Uuid subnetId = subnetmap.getId();
2416 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2417 if (subnetVpnId != null) {
2418 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2419 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2420 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2421 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2424 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2425 if (!ipVersion.isIpVersionChosen(ipVers)) {
2426 ipVersion = ipVersion.addVersion(ipVers);
2428 if (!NeutronvpnUtils.getIsExternal(network)) {
2429 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2431 addSubnetToVpn(vpnId, subnetId, null);
2432 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2434 passedNwList.add(nw);
2437 if (ipVersion != IpVersionChoice.UNDEFINED) {
2438 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2440 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2442 passedNwList.add(nw);
2444 } catch (ReadFailedException e) {
2445 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2447 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2450 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2451 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2452 return failedNwList;
2455 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2456 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2459 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2460 if (vpnOpDataEntry == null) {
2461 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2464 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2465 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2466 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2468 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2469 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2470 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2472 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2475 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2476 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2477 updateVpnInternetForSubnet(sm, vpnId, true);
2479 if (!ipVersion.isIpVersionChosen(ipVers)) {
2480 ipVersion = ipVersion.addVersion(ipVers);
2483 if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
2484 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2485 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2486 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, true);
2492 * Parses and disassociates networks list from given VPN.
2494 * @param vpnId Uuid of given VPN.
2495 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2496 * @return list of formatted strings with detailed error messages.
2499 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2500 List<String> failedNwList = new ArrayList<>();
2501 HashSet<Uuid> passedNwList = new HashSet<>();
2502 if (networkList.isEmpty()) {
2503 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2504 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2506 return failedNwList;
2508 for (Uuid nw : networkList) {
2509 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2510 if (networkSubnets == null) {
2511 passedNwList.add(nw);
2514 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2515 if (network == null) {
2516 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2517 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2521 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2522 if (networkVpnId == null) {
2523 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2524 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2528 if (!vpnId.equals(networkVpnId)) {
2529 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2530 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2531 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2532 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2536 if (NeutronvpnUtils.getIsExternal(network)) {
2537 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2538 passedNwList.add(nw);
2541 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2542 nw.getValue(), vpnId.getValue());
2543 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2548 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2549 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2550 for (Uuid subnet : networkSubnets) {
2551 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2552 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2553 if (!ipVersion.isIpVersionChosen(ipVers)) {
2554 ipVersion = ipVersion.addVersion(ipVers);
2556 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2558 removeSubnetFromVpn(vpnId, subnet, null);
2559 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2561 passedNwList.add(nw);
2563 if (ipVersion != IpVersionChoice.UNDEFINED) {
2564 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
2566 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2569 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2570 LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
2572 return failedNwList;
2575 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2576 if (!removeExternalNetworkFromVpn(extNet)) {
2579 // check, if there is another Provider Networks associated with given VPN
2580 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2581 if (vpnNets != null) {
2582 //Remove currently disassociated network from the list
2583 vpnNets.remove(extNet.getUuid());
2584 for (Uuid netId : vpnNets) {
2585 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2586 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2587 + "{}", vpnId.getValue(), netId.getValue());
2592 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2593 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2594 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2595 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2596 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2597 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2598 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2600 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2603 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2604 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2605 updateVpnInternetForSubnet(sm, vpnId, false);
2607 if (!ipVersion.isIpVersionChosen(ipVers)) {
2608 ipVersion = ipVersion.addVersion(ipVers);
2611 if (!ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
2612 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2613 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2615 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId, false);
2621 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2624 // TODO Clean up the exception handling
2625 @SuppressWarnings("checkstyle:IllegalCatch")
2626 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2628 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2629 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2630 StringBuilder returnMsg = new StringBuilder();
2631 Uuid vpnId = input.getVpnId();
2634 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2635 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2636 input.getNetworkId().toString());
2637 List<Uuid> netIds = input.getNetworkId();
2638 if (netIds != null && !netIds.isEmpty()) {
2639 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2640 if (!failed.isEmpty()) {
2641 returnMsg.append(failed);
2645 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2647 if (returnMsg.length() != 0) {
2648 opBuilder.setResponse(
2649 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2650 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2651 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2653 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2655 } catch (Exception ex) {
2656 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2657 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2658 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2660 LOG.debug("associateNetworks returns..");
2665 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2668 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2670 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2671 LOG.debug("associateRouter {}", input);
2672 StringBuilder returnMsg = new StringBuilder();
2673 Uuid vpnId = input.getVpnId();
2674 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2675 routerIds = input.getRouterIds();
2676 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2677 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2678 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2679 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2680 .RouterIds routerId : routerIds) {
2681 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2682 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2683 if (vpnMap != null) {
2685 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2686 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2687 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2688 .append(routerId.getRouterId());
2689 } else if (extVpnId != null) {
2690 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2691 + "another VPN ").append(extVpnId.getValue());
2693 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2694 routerId.getRouterId());
2695 associateRouterToVpn(vpnId, routerId.getRouterId());
2698 returnMsg.append("router not found : ").append(routerId.getRouterId());
2701 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2703 if (returnMsg.length() != 0) {
2704 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2705 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2706 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2708 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2711 LOG.debug("associateRouter returns..");
2716 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2719 // TODO Clean up the exception handling
2720 @SuppressWarnings("checkstyle:IllegalCatch")
2721 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2722 GetFixedIPsForNeutronPortInput input) {
2723 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2724 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2725 Uuid portId = input.getPortId();
2726 StringBuilder returnMsg = new StringBuilder();
2728 List<String> fixedIPList = new ArrayList<>();
2729 Port port = neutronvpnUtils.getNeutronPort(portId);
2731 List<FixedIps> fixedIPs = port.getFixedIps();
2732 for (FixedIps ip : fixedIPs) {
2733 fixedIPList.add(ip.getIpAddress().stringValue());
2736 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2738 if (returnMsg.length() != 0) {
2739 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2741 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2742 returnMsg)).build());
2744 opBuilder.setFixedIPs(fixedIPList);
2745 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2747 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2749 } catch (Exception ex) {
2750 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2751 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2752 portId.getValue(), ex.getMessage(), ex)).build());
2758 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2761 // TODO Clean up the exception handling
2762 @SuppressWarnings("checkstyle:IllegalCatch")
2763 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2765 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2766 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2768 LOG.debug("dissociateNetworks {}", input);
2769 StringBuilder returnMsg = new StringBuilder();
2770 Uuid vpnId = input.getVpnId();
2773 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2774 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2775 input.getNetworkId().toString());
2776 List<Uuid> netIds = input.getNetworkId();
2777 if (netIds != null && !netIds.isEmpty()) {
2778 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2779 if (!failed.isEmpty()) {
2780 returnMsg.append(failed);
2784 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2786 if (returnMsg.length() != 0) {
2787 opBuilder.setResponse(
2788 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2789 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2791 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2793 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2795 } catch (Exception ex) {
2796 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2797 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2798 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2800 LOG.debug("dissociateNetworks returns..");
2805 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2808 // TODO Clean up the exception handling
2809 @SuppressWarnings("checkstyle:IllegalCatch")
2810 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2812 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2814 LOG.debug("dissociateRouter {}", input);
2815 StringBuilder returnMsg = new StringBuilder();
2816 Uuid vpnId = input.getVpnId();
2817 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2818 .RouterIds> routerIdList = input.getRouterIds();
2819 String routerIdsString = "";
2820 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2821 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2822 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2823 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2824 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2825 .RouterIds routerId : routerIdList) {
2827 if (routerId != null) {
2828 routerIdsString += routerId.getRouterId() + ", ";
2829 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2831 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2832 if (routerVpnId == null) {
2833 returnMsg.append("input router ").append(routerId.getRouterId())
2834 .append(" not associated to any vpn yet");
2835 } else if (vpnId.equals(routerVpnId)) {
2836 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2838 returnMsg.append("input router ").append(routerId.getRouterId())
2839 .append(" associated to vpn ")
2840 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2843 returnMsg.append("router not found : ").append(routerId.getRouterId());
2846 if (returnMsg.length() != 0) {
2847 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2848 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2849 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2850 returnMsg)).build());
2852 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2854 } catch (Exception ex) {
2855 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2856 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2857 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2861 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2864 LOG.debug("dissociateRouter returns..");
2868 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2869 // check if the router is associated to some VPN
2870 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2871 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2872 if (vpnId != null) {
2873 // remove existing external vpn interfaces
2874 for (Uuid subnetId : routerSubnetIds) {
2875 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2877 clearFromVpnMaps(vpnId, routerId, null);
2879 // remove existing internal vpn interfaces
2880 for (Uuid subnetId : routerSubnetIds) {
2881 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2884 // delete entire vpnMaps node for internal VPN
2885 deleteVpnMapsNode(routerId);
2887 // delete vpn-instance for internal VPN
2888 deleteVpnInstance(routerId);
2891 protected Subnet getNeutronSubnet(Uuid subnetId) {
2892 return neutronvpnUtils.getNeutronSubnet(subnetId);
2895 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2896 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2898 return sn.getGatewayIp();
2904 protected Network getNeutronNetwork(Uuid networkId) {
2905 return neutronvpnUtils.getNeutronNetwork(networkId);
2908 protected Port getNeutronPort(String name) {
2909 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2912 protected Port getNeutronPort(Uuid portId) {
2913 return neutronvpnUtils.getNeutronPort(portId);
2916 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2917 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2920 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2921 return neutronvpnUtils.getNetworksForVpn(vpnId);
2925 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2927 * @return a List of String to be printed on screen
2928 * @throws ReadFailedException if there was a problem reading from the data store
2930 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2931 List<String> result = new ArrayList<>();
2932 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2934 result.add("-------------------------------------------------------------------------------------------");
2935 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2937 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2938 if (ports.isPresent() && ports.get().getPort() != null) {
2939 for (Port port : ports.get().getPort()) {
2940 List<FixedIps> fixedIPs = port.getFixedIps();
2941 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2942 List<String> ipList = new ArrayList<>();
2943 for (FixedIps fixedIp : fixedIPs) {
2944 IpAddress ipAddress = fixedIp.getIpAddress();
2945 if (ipAddress.getIpv4Address() != null) {
2946 ipList.add(ipAddress.getIpv4Address().getValue());
2948 ipList.add(ipAddress.getIpv6Address().getValue());
2951 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2952 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2953 ipList.toString()));
2955 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2956 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2965 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2967 * @param vpnuuid Uuid of the VPN whose config must be shown
2968 * @return formatted output list
2969 * @throws InterruptedException if there was a thread related problem getting the data to display
2970 * @throws ExecutionException if there was any other problem getting the data to display
2972 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2973 List<String> result = new ArrayList<>();
2974 if (vpnuuid == null) {
2976 result.add("Displaying VPN config for all VPNs");
2977 result.add("To display VPN config for a particular VPN, use the following syntax");
2978 result.add(getshowVpnConfigCLIHelp());
2980 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2981 if (rpcResult.isSuccessful()) {
2983 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2985 result.add(String.format(" %-80s ", "Import-RTs"));
2987 result.add(String.format(" %-80s ", "Export-RTs"));
2989 result.add(String.format(" %-76s ", "Subnet IDs"));
2991 result.add("------------------------------------------------------------------------------------");
2993 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2994 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2995 .rev150602.VpnInstance vpn : vpnList) {
2996 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2998 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2999 vpn.getRouteDistinguisher()));
3001 result.add(String.format(" %-80s ", vpn.getImportRT()));
3003 result.add(String.format(" %-80s ", vpn.getExportRT()));
3006 Uuid vpnid = vpn.getId();
3007 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3008 if (!subnetList.isEmpty()) {
3009 for (Uuid subnetuuid : subnetList) {
3010 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3013 result.add(String.format(" %-76s ", "\" \""));
3016 result.add("----------------------------------------");
3020 String errortag = rpcResult.getErrors().iterator().next().getTag();
3021 if (Objects.equals(errortag, "")) {
3023 result.add("No VPN has been configured yet");
3024 } else if (Objects.equals(errortag, "invalid-value")) {
3026 result.add("VPN " + vpnuuid.getValue() + " is not present");
3028 result.add("error getting VPN info : " + rpcResult.getErrors());
3029 result.add(getshowVpnConfigCLIHelp());
3035 protected void createExternalVpnInterfaces(Uuid extNetId) {
3036 if (extNetId == null) {
3037 LOG.error("createExternalVpnInterfaces: external network is null");
3041 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3042 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3043 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3047 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3048 for (String elanInterface : extElanInterfaces) {
3049 createExternalVpnInterface(extNetId, elanInterface, tx);
3051 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3054 // TODO Clean up the exception handling
3055 @SuppressWarnings("checkstyle:IllegalCatch")
3056 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3057 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3058 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3059 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3062 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3063 for (String elanInterface : extElanInterfaces) {
3064 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3065 .buildVpnInterfaceIdentifier(elanInterface);
3066 LOG.info("Removing vpn interface {}", elanInterface);
3067 tx.delete(vpnIfIdentifier);
3069 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3072 private void createExternalVpnInterface(Uuid vpnId, String infName,
3073 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3074 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3075 false /* not a router iface */, wrtConfigTxn);
3078 // TODO Clean up the exception handling
3079 @SuppressWarnings("checkstyle:IllegalCatch")
3080 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
3081 Uuid networkUuid, Boolean isRouterInterface, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3082 if (vpnIdList.isEmpty() || infName == null) {
3083 LOG.error("vpnid is empty or interface({}) is null", infName);
3086 if (wrtConfigTxn == null) {
3087 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3088 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3089 "Error writing VPN interface");
3092 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3093 for (Uuid vpnId: vpnIdList) {
3094 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3095 AssociatedSubnetType.V4AndV6Subnets);
3096 vpnIdListStruct.add(vpnInstance);
3099 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3100 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3102 .setVpnInstanceNames(vpnIdListStruct)
3103 .setRouterInterface(isRouterInterface);
3104 LOG.info("Network Id is {}", networkUuid);
3105 if (networkUuid != null) {
3106 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3107 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3108 NetworkAttributes.NetworkType networkType = (providerType != null)
3109 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3110 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3111 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3112 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3115 if (adjacencies != null) {
3116 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3118 VpnInterface vpnIf = vpnb.build();
3120 LOG.info("Creating vpn interface {}", vpnIf);
3121 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3122 } catch (Exception ex) {
3123 LOG.error("Creation of vpninterface {} failed", infName, ex);
3127 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3128 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3129 if (vpnId == null || infName == null) {
3130 LOG.error("vpn id or interface is null");
3133 if (wrtConfigTxn == null) {
3134 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3135 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3136 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3137 }), LOG, "Error updating VPN interface with adjacencies");
3141 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3142 boolean isLockAcquired = false;
3144 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3145 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3146 .syncReadOptional(dataBroker, LogicalDatastoreType
3147 .CONFIGURATION, vpnIfIdentifier);
3148 if (optionalVpnInterface.isPresent()) {
3149 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3150 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3152 if (adjacencies == null) {
3153 if (isLockAcquired) {
3154 interfaceLock.unlock(infName);
3158 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3159 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3160 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3161 optionalVpnInterface.get().getVpnInstanceNames());
3162 if (listVpnInstances.isEmpty() || !VpnHelper
3163 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3164 VpnInstanceNames vpnInstance = VpnHelper
3165 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3166 listVpnInstances.add(vpnInstance);
3167 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3170 VpnInstanceNames vpnInstance = VpnHelper
3171 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3172 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3173 listVpnInstances.add(vpnInstance);
3174 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3176 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3177 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3179 } catch (IllegalStateException | ReadFailedException ex) {
3180 LOG.error("Update of vpninterface {} failed", infName, ex);
3182 if (isLockAcquired) {
3183 interfaceLock.unlock(infName);
3188 private String getshowVpnConfigCLIHelp() {
3189 StringBuilder help = new StringBuilder("Usage:");
3190 help.append("display vpn-config [-vid/--vpnid <id>]");
3191 return help.toString();
3194 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3195 InterruptedException {
3196 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3197 .setVpnId(vpnId).build();
3198 LOG.info("publishing notification upon association of router to VPN");
3199 notificationPublishService.putNotification(routerAssociatedToVpn);
3202 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3203 InterruptedException {
3204 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3205 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3206 LOG.info("publishing notification upon disassociation of router from VPN");
3207 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3210 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3211 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3215 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3216 return neutronEvpnManager.createEVPN(input);
3220 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3221 return neutronEvpnManager.getEVPN(input);
3225 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3226 return neutronEvpnManager.deleteEVPN(input);
3229 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3230 Uuid extNetId = extNet.getUuid();
3231 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3232 .child(Networks.class, new NetworksKey(extNetId)).build();
3235 Optional<Networks> optionalExtNets =
3236 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3238 if (!optionalExtNets.isPresent()) {
3239 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3240 extNetId.getValue());
3243 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3244 builder.setVpnid(vpnId);
3245 Networks networks = builder.build();
3246 // Add Networks object to the ExternalNetworks list
3247 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3248 extNetId.getValue());
3249 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3252 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3253 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3254 extNetId.getValue(), ex);
3259 private boolean removeExternalNetworkFromVpn(Network extNet) {
3260 Uuid extNetId = extNet.getUuid();
3261 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3262 .child(Networks.class, new NetworksKey(extNetId)).build();
3264 Optional<Networks> optionalNets =
3265 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3267 NetworksBuilder builder = null;
3268 if (optionalNets.isPresent()) {
3269 builder = new NetworksBuilder(optionalNets.get());
3271 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3272 extNetId.getValue());
3275 builder.setVpnid(null);
3276 Networks networks = builder.build();
3277 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3278 extNetId.getValue());
3279 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3281 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3282 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3283 extNetId.getValue(), ex);
3288 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3289 Optional<String> existingVpnName = Optional.of(primaryRd);
3290 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3292 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3293 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3294 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3295 } catch (ReadFailedException e) {
3296 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3298 /*Read failed. We don't know if a VPN exists or not.
3299 * Return primaryRd to halt caller execution, to be safe.*/
3300 return existingVpnName;
3302 if (vpnInstanceOpDataOptional.isPresent()) {
3303 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3305 existingVpnName = Optional.absent();
3307 return existingVpnName;
3310 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3311 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3314 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3315 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3318 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3319 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3322 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3323 String message = tuple.getMessage();
3324 logger.accept(message);
3328 protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3329 @Nonnull Subnetmap subnetMap) {
3330 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3331 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
3332 IpVersionChoice.IPV6, routerId, true)) {
3333 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3334 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3335 subnetMap.getId(), internetVpnId.getValue());
3337 neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, true);
3340 protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3341 @Nonnull Subnetmap subnetMap) {
3342 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3343 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
3344 IpVersionChoice.IPV6, routerId, false)) {
3345 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, false);
3346 LOG.info("removeV6PrivateSubnetToExtNetwork: withdraw IPv6 Private subnet {} from Internet VPN {}",
3347 subnetMap.getId(), internetVpnId.getValue());
3349 neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, false);