2 * Copyright © 2015, 2017 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.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
12 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
13 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.JdkFutureAdapters;
20 import com.google.common.util.concurrent.ListenableFuture;
21 import com.google.common.util.concurrent.MoreExecutors;
22 import com.google.common.util.concurrent.SettableFuture;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.EventListener;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Iterator;
31 import java.util.List;
33 import java.util.Map.Entry;
34 import java.util.Objects;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.Future;
39 import java.util.concurrent.TimeUnit;
40 import java.util.function.Consumer;
41 import javax.annotation.Nonnull;
42 import javax.annotation.Nullable;
43 import javax.annotation.PreDestroy;
44 import javax.inject.Inject;
45 import javax.inject.Singleton;
46 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
47 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
48 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
49 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
50 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
51 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
52 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
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.external.networks.Networks;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
171 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
172 import org.opendaylight.yangtools.yang.common.RpcError;
173 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
174 import org.opendaylight.yangtools.yang.common.RpcResult;
175 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
176 import org.slf4j.Logger;
177 import org.slf4j.LoggerFactory;
178 import org.slf4j.helpers.FormattingTuple;
179 import org.slf4j.helpers.MessageFormatter;
182 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
184 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
185 private static long LOCK_WAIT_TIME = 10L;
187 private final DataBroker dataBroker;
188 private final ManagedNewTransactionRunner txRunner;
189 private final NotificationPublishService notificationPublishService;
190 private final VpnRpcService vpnRpcService;
191 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
192 private final IElanService elanService;
193 private final NeutronvpnConfig neutronvpnConfig;
194 private final NeutronEvpnManager neutronEvpnManager;
195 private final NeutronEvpnUtils neutronEvpnUtils;
196 private final JobCoordinator jobCoordinator;
197 private final NeutronvpnUtils neutronvpnUtils;
198 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
199 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
200 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
201 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
204 public NeutronvpnManager(
205 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
206 final VpnRpcService vpnRpcSrv, final IElanService elanService,
207 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
208 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
209 final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
210 this.dataBroker = dataBroker;
211 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
212 notificationPublishService = notiPublishService;
213 vpnRpcService = vpnRpcSrv;
214 this.elanService = elanService;
215 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
216 this.neutronvpnConfig = neutronvpnConfig;
217 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
218 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
219 this.jobCoordinator = jobCoordinator;
220 this.neutronvpnUtils = neutronvpnUtils;
227 public void close() {
228 LOG.info("{} close", getClass().getSimpleName());
231 private void configureFeatures() {
232 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
233 Neutron.class).child(Features.class).child(
234 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
235 Feature feature = new FeatureBuilder().setKey(new FeatureKey(OperationalPortStatus.class)).build();
237 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
238 } catch (TransactionCommitFailedException e) {
239 LOG.warn("Error configuring feature {}", feature, e);
243 public String getOpenDaylightVniRangesConfig() {
244 return neutronvpnConfig.getOpendaylightVniRanges();
247 // TODO Clean up the exception handling
248 @SuppressWarnings("checkstyle:IllegalCatch")
249 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
250 NetworkAttributes.NetworkType networkType, long segmentationId) {
252 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
253 synchronized (subnetId.getValue().intern()) {
254 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
255 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
256 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
257 if (sn.isPresent()) {
258 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
259 subnetId.getValue());
262 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId))
263 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
264 .setNetworkType(networkType).setSegmentationId(segmentationId);
265 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
266 subnetId.getValue());
267 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
268 subnetMapIdentifier, subnetmapBuilder.build());
270 } catch (TransactionCommitFailedException | ReadFailedException e) {
271 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
273 // check if there are ports to update for already created Subnetmap node
274 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
275 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
276 if (entry.getValue().getValue().equals(subnetId.getValue())) {
277 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
278 unprocessedPortsMap.remove(entry.getKey());
283 protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) {
284 Subnetmap subnetmap = null;
285 SubnetmapBuilder builder = null;
286 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
287 .child(Subnetmap.class, new SubnetmapKey(subnetId))
290 synchronized (subnetId.getValue().intern()) {
291 Optional<Subnetmap> sn =
292 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
294 if (sn.isPresent()) {
295 builder = new SubnetmapBuilder(sn.get());
296 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
298 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
301 if (routerId != null) {
302 builder.setRouterId(routerId);
305 builder.setVpnId(vpnId);
307 builder.setInternetVpnId(internetvpnId);
309 subnetmap = builder.build();
310 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
311 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
313 } catch (ReadFailedException | TransactionCommitFailedException e) {
314 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
319 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
320 Uuid routerInterfacePortId, String fixedIp,
321 String routerIntfMacAddress, Uuid vpnId) {
322 Subnetmap subnetmap = null;
323 SubnetmapBuilder builder = null;
324 InstanceIdentifier<Subnetmap> id =
325 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
327 synchronized (subnetId.getValue().intern()) {
328 Optional<Subnetmap> sn =
329 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
331 if (sn.isPresent()) {
332 builder = new SubnetmapBuilder(sn.get());
333 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
334 subnetId.getValue());
336 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
337 subnetId.getValue());
340 builder.setRouterId(routerId);
341 builder.setRouterInterfacePortId(routerInterfacePortId);
342 builder.setRouterIntfMacAddress(routerIntfMacAddress);
343 builder.setRouterInterfaceFixedIp(fixedIp);
345 builder.setVpnId(vpnId);
347 subnetmap = builder.build();
348 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
349 subnetId.getValue());
350 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
352 } catch (ReadFailedException | TransactionCommitFailedException e) {
353 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
354 subnetId.getValue(), e);
358 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
359 Subnetmap subnetmap = null;
360 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
361 new SubnetmapKey(subnetId)).build();
362 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
364 synchronized (subnetId.getValue().intern()) {
365 Optional<Subnetmap> sn =
366 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
368 if (sn.isPresent()) {
369 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
370 if (null != portId) {
371 List<Uuid> portList = builder.getPortList();
372 if (null == portList) {
373 portList = new ArrayList<>();
375 portList.add(portId);
376 builder.setPortList(portList);
377 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
378 subnetId.getValue(), portId.getValue());
380 if (null != directPortId) {
381 List<Uuid> directPortList = builder.getDirectPortList();
382 if (null == directPortList) {
383 directPortList = new ArrayList<>();
385 directPortList.add(directPortId);
386 builder.setDirectPortList(directPortList);
387 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
388 directPortId.getValue());
390 subnetmap = builder.build();
391 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
394 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
395 + "cache ", subnetId.getValue(), portId.getValue());
396 unprocessedPortsMap.put(portId, subnetId);
399 } catch (ReadFailedException | TransactionCommitFailedException e) {
400 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
405 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId,
406 Uuid vpnId, Uuid portId) {
407 Subnetmap subnetmap = null;
408 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
409 .child(Subnetmap.class, new SubnetmapKey(subnetId))
412 synchronized (subnetId.getValue().intern()) {
413 Optional<Subnetmap> sn =
414 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
416 if (sn.isPresent()) {
417 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
418 if (routerId != null) {
419 builder.setRouterId(null);
421 if (networkId != null) {
422 builder.setNetworkId(null);
425 builder.setVpnId(null);
427 builder.setInternetVpnId(null);
428 if (portId != null && builder.getPortList() != null) {
429 List<Uuid> portList = builder.getPortList();
430 portList.remove(portId);
431 builder.setPortList(portList);
434 subnetmap = builder.build();
435 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
436 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
439 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
442 } catch (ReadFailedException | TransactionCommitFailedException e) {
443 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
448 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
449 Subnetmap subnetmap = null;
450 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
451 new SubnetmapKey(subnetId)).build();
453 synchronized (subnetId.getValue().intern()) {
454 Optional<Subnetmap> sn =
455 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
457 if (sn.isPresent()) {
458 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
459 if (null != portId && null != builder.getPortList()) {
460 List<Uuid> portList = builder.getPortList();
461 portList.remove(portId);
462 builder.setPortList(portList);
463 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
464 subnetId.getValue());
466 if (null != directPortId && null != builder.getDirectPortList()) {
467 List<Uuid> directPortList = builder.getDirectPortList();
468 directPortList.remove(directPortId);
469 builder.setDirectPortList(directPortList);
470 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
471 .getValue(), subnetId.getValue());
473 subnetmap = builder.build();
474 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
477 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
480 } catch (ReadFailedException | TransactionCommitFailedException e) {
481 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
482 subnetId.getValue(), e);
487 // TODO Clean up the exception handling
488 @SuppressWarnings("checkstyle:IllegalCatch")
489 protected void deleteSubnetMapNode(Uuid subnetId) {
490 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
491 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
492 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
494 synchronized (subnetId.getValue().intern()) {
495 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
496 subnetMapIdentifier);
498 } catch (TransactionCommitFailedException e) {
499 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
503 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
504 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
505 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
507 Optional<VpnInstance> vpnInstanceConfig =
508 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
510 if (!vpnInstanceConfig.isPresent()) {
511 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
514 VpnInstance vpnInstance = vpnInstanceConfig.get();
515 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
516 if (vpnInstance.getIpv4Family() != null) {
517 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
518 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
520 if (vpnInstance.getIpv6Family() != null) {
521 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
522 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
524 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
525 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
526 updateVpnInstanceBuilder.build());
527 } catch (ReadFailedException | TransactionCommitFailedException ex) {
528 LOG.warn("Error configuring feature ", ex);
532 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
533 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
534 String vpnName = vpnId.getValue();
535 VpnInstanceBuilder builder = null;
536 List<VpnTarget> vpnTargetList = new ArrayList<>();
537 boolean isLockAcquired = false;
538 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
539 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
541 Optional<VpnInstance> optionalVpn =
542 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
544 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
545 if (optionalVpn.isPresent()) {
546 builder = new VpnInstanceBuilder(optionalVpn.get());
547 LOG.debug("updating existing vpninstance node");
549 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
550 .setType(type).setL3vni(l3vni);
552 if (irt != null && !irt.isEmpty()) {
553 if (ert != null && !ert.isEmpty()) {
554 List<String> commonRT = new ArrayList<>(irt);
555 commonRT.retainAll(ert);
557 for (String common : commonRT) {
560 VpnTarget vpnTarget =
561 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
562 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
563 vpnTargetList.add(vpnTarget);
566 for (String importRT : irt) {
567 VpnTarget vpnTarget =
568 new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
569 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
570 vpnTargetList.add(vpnTarget);
574 if (ert != null && !ert.isEmpty()) {
575 for (String exportRT : ert) {
576 VpnTarget vpnTarget =
577 new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
578 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
579 vpnTargetList.add(vpnTarget);
583 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
585 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
586 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
588 if (rd != null && !rd.isEmpty()) {
589 ipv4vpnBuilder.setRouteDistinguisher(rd);
590 ipv6vpnBuilder.setRouteDistinguisher(rd);
593 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
594 builder.setIpv4Family(ipv4vpnBuilder.build());
596 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
597 builder.setIpv6Family(ipv6vpnBuilder.build());
599 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
600 builder.setIpv4Family(ipv4vpnBuilder.build());
602 VpnInstance newVpn = builder.build();
603 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
604 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
605 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
607 } catch (ReadFailedException | TransactionCommitFailedException e) {
608 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
610 if (isLockAcquired) {
611 vpnLock.unlock(vpnId);
616 private void deleteVpnMapsNode(Uuid vpnId) {
617 boolean isLockAcquired = false;
618 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
619 .child(VpnMap.class, new VpnMapKey(vpnId))
621 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
623 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
624 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
625 } catch (TransactionCommitFailedException e) {
626 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
628 if (isLockAcquired) {
629 vpnLock.unlock(vpnId);
634 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
635 VpnMapBuilder builder;
636 boolean isLockAcquired = false;
637 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
638 .child(VpnMap.class, new VpnMapKey(vpnId))
641 Optional<VpnMap> optionalVpnMap =
642 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
644 if (optionalVpnMap.isPresent()) {
645 builder = new VpnMapBuilder(optionalVpnMap.get());
647 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
651 builder.setName(name);
653 if (tenantId != null) {
654 builder.setTenantId(tenantId);
656 if (router != null) {
657 builder.setRouterId(router);
659 if (networks != null) {
660 List<Uuid> nwList = builder.getNetworkIds();
661 if (nwList == null) {
662 nwList = new ArrayList<>();
664 nwList.addAll(networks);
665 builder.setNetworkIds(nwList);
668 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
669 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
670 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
672 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
673 } catch (ReadFailedException | TransactionCommitFailedException e) {
674 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
676 if (isLockAcquired) {
677 vpnLock.unlock(vpnId);
682 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
683 boolean isLockAcquired = false;
684 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
685 .child(VpnMap.class, new VpnMapKey(vpnId))
687 Optional<VpnMap> optionalVpnMap;
690 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
692 } catch (ReadFailedException e) {
693 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
696 if (optionalVpnMap.isPresent()) {
697 VpnMap vpnMap = optionalVpnMap.get();
698 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
699 if (routerId != null) {
700 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
702 // remove entire node in case of internal VPN
703 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
704 LOG.debug("removing vpnMaps node: {} ", vpnId);
705 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
707 } catch (TransactionCommitFailedException e) {
708 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
710 if (isLockAcquired) {
711 vpnLock.unlock(vpnId);
716 vpnMapBuilder.setRouterId(null);
718 if (networkIds != null) {
719 List<Uuid> vpnNw = vpnMap.getNetworkIds();
720 vpnNw.removeAll(networkIds);
721 if (vpnNw.isEmpty()) {
722 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
723 vpnMapBuilder.setNetworkIds(null);
725 vpnMapBuilder.setNetworkIds(vpnNw);
730 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
731 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
732 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
733 vpnMapBuilder.build());
734 } catch (TransactionCommitFailedException e) {
735 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
737 if (isLockAcquired) {
738 vpnLock.unlock(vpnId);
742 LOG.error("VPN : {} not found", vpnId.getValue());
744 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
747 private void deleteVpnInstance(Uuid vpnId) {
748 boolean isLockAcquired = false;
749 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
750 .child(VpnInstance.class,
751 new VpnInstanceKey(vpnId.getValue()))
754 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
755 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
756 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
757 } catch (TransactionCommitFailedException e) {
758 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
760 if (isLockAcquired) {
761 vpnLock.unlock(vpnId);
766 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
767 WriteTransaction wrtConfigTxn, Subnetmap sn, VpnInterface vpnIface) {
768 List<Adjacency> adjList = new ArrayList<>();
769 if (vpnIface != null) {
770 adjList = vpnIface.getAugmentation(Adjacencies.class).getAdjacency();
772 String infName = port.getUuid().getValue();
773 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
774 for (FixedIps ip : port.getFixedIps()) {
775 String ipValue = String.valueOf(ip.getIpAddress().getValue());
776 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
777 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
780 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
781 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
783 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
784 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
785 //Create Neutron port adjacency if VPN presence is existing for subnet
786 Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
787 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
788 .setSubnetId(ip.getSubnetId()).build();
789 if (!adjList.contains(vmAdj)) {
793 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
794 if (snTemp != null && snTemp.getInternetVpnId() != null) {
795 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
796 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
798 if (routerId != null) {
799 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
800 if (rtr != null && rtr.getRoutes() != null) {
801 List<Routes> routeList = rtr.getRoutes();
802 // create extraroute Adjacence for each ipValue,
803 // because router can have IPv4 and IPv6 subnet ports, or can have
804 // more that one IPv4 subnet port or more than one IPv6 subnet port
805 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
806 if (!erAdjList.isEmpty()) {
807 adjList.addAll(erAdjList);
812 return new AdjacenciesBuilder().setAdjacency(adjList).build();
815 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port, WriteTransaction wrtConfigTxn) {
816 boolean isRouterInterface = false;
817 if (port.getDeviceOwner() != null) {
818 isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
820 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
821 String infName = port.getUuid().getValue();
822 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
823 writeVpnInterfaceToDs(vpnIds, infName, adjs, isRouterInterface, wrtConfigTxn);
826 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
827 Port port, Subnetmap sn, WriteTransaction wrtConfigTxn) {
828 String infName = port.getUuid().getValue();
829 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
830 Optional<VpnInterface> optionalVpnInterface = null;
831 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
832 vpnId, internetVpnId, infName);
834 optionalVpnInterface = SingleTransactionDataBroker
835 .syncReadOptional(dataBroker, LogicalDatastoreType
836 .CONFIGURATION, vpnIfIdentifier);
837 } catch (ReadFailedException e) {
838 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
841 if (!optionalVpnInterface.isPresent()) {
844 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
845 sn != null ? sn.getSubnetIp() : "null");
846 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().getAugmentation(Adjacencies.class).getAdjacency();
847 List<Adjacency> updatedAdjsList = new ArrayList<>();
848 boolean isIpFromAnotherSubnet = false;
849 for (Adjacency adj : vpnAdjsList) {
850 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
851 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
852 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
853 isIpFromAnotherSubnet = true;
855 updatedAdjsList.add(adj);
858 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
859 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
862 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
863 String.valueOf(adjString), wrtConfigTxn);
865 if (internetVpnId != null) {
866 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
867 String.valueOf(adjString), wrtConfigTxn);
870 if (port.getDeviceOwner()
871 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
872 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
873 if (rtr != null && rtr.getRoutes() != null) {
874 List<Routes> extraRoutesToRemove = new ArrayList<>();
875 for (Routes rt: rtr.getRoutes()) {
876 if (rt.getNexthop().toString().equals(adjString)) {
877 extraRoutesToRemove.add(rt);
881 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
882 extraRoutesToRemove, vpnId);
883 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
885 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
890 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
892 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
894 if (internetVpnId != null) {
895 updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn);
897 if (!isIpFromAnotherSubnet) {
898 // no more subnetworks for neutron port
899 if (sn != null && sn.getRouterId() != null) {
900 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
902 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
908 // TODO Clean up the exception handling
909 @SuppressWarnings("checkstyle:IllegalCatch")
910 protected void deleteVpnInterface(String infName, @Nullable String vpnId, WriteTransaction wrtConfigTxn) {
911 if (wrtConfigTxn == null) {
912 ListenableFutures.addErrorLogging(
913 txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> deleteVpnInterface(infName, vpnId, tx)),
914 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
918 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
919 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
920 Optional<VpnInterface> optionalVpnInterface;
922 optionalVpnInterface =
923 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
925 } catch (ReadFailedException ex) {
926 LOG.error("Error during deletion of vpninterface {}", infName, ex);
929 if (!optionalVpnInterface.isPresent()) {
930 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
934 VpnInterface vpnInterface = optionalVpnInterface.get();
935 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
937 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
938 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
939 if (!vpnList.isEmpty()) {
940 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
941 + "List not empty", infName);
944 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
945 .setVpnInstanceNames(vpnList);
946 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
950 LOG.debug("Deleting vpn interface {}", infName);
951 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
954 protected void removeVpnFromVpnInterface(Uuid vpnId, Port port,
955 WriteTransaction writeConfigTxn, Subnetmap sm) {
956 if (vpnId == null || port == null) {
959 String infName = port.getUuid().getValue();
960 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
962 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
963 .syncReadOptional(dataBroker, LogicalDatastoreType
964 .CONFIGURATION, vpnIfIdentifier);
965 if (optionalVpnInterface.isPresent()) {
966 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
968 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
969 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
971 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
972 .setVpnInstanceNames(listVpn);
973 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
974 LOG.debug("Updating vpn interface {}", infName);
975 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
976 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
977 while (adjacencyIter.hasNext()) {
978 Adjacency adjacency = adjacencyIter.next();
979 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
982 String mipToQuery = adjacency.getIpAddress().split("/")[0];
983 InstanceIdentifier<LearntVpnVipToPort> id =
984 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
985 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
986 SingleTransactionDataBroker.syncReadOptional(dataBroker,
987 LogicalDatastoreType.OPERATIONAL, id);
988 if (optionalVpnVipToPort.isPresent()) {
989 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
991 if (listVpn == null || listVpn.isEmpty()) {
992 adjacencyIter.remove();
994 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
995 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
996 mipToQuery, infName, vpnId.getValue());
999 List<FixedIps> ips = port.getFixedIps();
1000 for (FixedIps ip : ips) {
1001 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1002 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1003 ipValue, writeConfigTxn);
1005 if (listVpn == null || listVpn.isEmpty()) {
1006 if (sm != null && sm.getRouterId() != null) {
1007 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1009 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1011 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1015 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1017 } catch (ReadFailedException ex) {
1018 LOG.error("Update of vpninterface {} failed", infName, ex);
1022 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
1023 boolean isSubnetIp, WriteTransaction writeConfigTxn) {
1024 if (vpnId == null || port == null) {
1027 boolean isLockAcquired = false;
1028 String infName = port.getUuid().getValue();
1029 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1032 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1033 Optional<VpnInterface> optionalVpnInterface =
1034 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1036 if (optionalVpnInterface.isPresent()) {
1037 VpnInstanceNames vpnInstance = VpnHelper
1038 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1039 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1040 .get().getVpnInstanceNames());
1041 if (oldVpnId != null
1042 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1043 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1045 if (vpnId.getValue() != null
1046 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1047 listVpn.add(vpnInstance);
1049 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1050 .setVpnInstanceNames(listVpn);
1051 LOG.debug("Updating vpn interface {}", infName);
1052 if (!isBeingAssociated) {
1053 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
1054 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1055 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1056 while (adjacencyIter.hasNext()) {
1057 Adjacency adjacency = adjacencyIter.next();
1058 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1059 InstanceIdentifier<LearntVpnVipToPort> id =
1060 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1061 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1062 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1063 LogicalDatastoreType.OPERATIONAL, id);
1064 if (optionalVpnVipToPort.isPresent()) {
1065 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1066 + "from VPN {}", infName, vpnId, oldVpnId);
1067 adjacencyIter.remove();
1068 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1070 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1071 mipToQuery, infName, vpnId.getValue());
1074 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1075 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1077 List<FixedIps> ips = port.getFixedIps();
1078 for (FixedIps ip : ips) {
1079 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1080 if (oldVpnId != null) {
1081 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1082 ipValue, writeConfigTxn);
1084 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1085 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1087 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1090 LOG.error("VPN Interface {} not found", infName);
1092 } catch (ReadFailedException ex) {
1093 LOG.error("Updation of vpninterface {} failed", infName, ex);
1095 if (isLockAcquired) {
1096 interfaceLock.unlock(infName);
1101 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
1102 List<String> ert, Uuid router, List<Uuid> networks) {
1104 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1106 // Update VPN Instance node
1107 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1109 // Update local vpn-subnet DS
1110 updateVpnMaps(vpn, name, router, tenant, networks);
1112 if (router != null) {
1113 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1114 if (existingVpn != null) {
1115 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1116 // if before reboot, router was already associated to VPN, should not proceed associating router to
1117 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1118 // preserved upon reboot.
1119 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1120 // RouterInterfacesMap via #createVPNInterface call.
1121 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1122 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1125 associateRouterToInternalVpn(vpn, router);
1130 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1131 * specified Neutron Networks and Routers.
1133 * @param vpn Uuid of the VPN tp be created
1134 * @param name Representative name of the new VPN
1135 * @param tenant Uuid of the Tenant under which the VPN is going to be created
1136 * @param rd Route-distinguisher for the VPN
1137 * @param irt A list of Import Route Targets
1138 * @param ert A list of Export Route Targets
1139 * @param router neutron router Id to associate with created VPN
1140 * @param networks UUID of the neutron network the VPN may be associated to
1141 * @param type Type of the VPN Instance
1142 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1143 * @throws Exception if association of L3VPN failed
1145 public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
1146 Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni)
1149 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1151 if (router != null) {
1152 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1153 ipVersChoices = ipVersChoices.addVersion(vers);
1155 updateVpnInstanceNode(vpn, rd, irt, ert, type, l3vni, ipVersChoices);
1157 // Please note that router and networks will be filled into VPNMaps
1158 // by subsequent calls here to associateRouterToVpn and
1159 // associateNetworksToVpn
1160 updateVpnMaps(vpn, name, null, tenant, null);
1162 if (router != null) {
1163 associateRouterToVpn(vpn, router);
1165 if (networks != null) {
1166 List<String> failStrings = associateNetworksToVpn(vpn, networks);
1167 if (!failStrings.isEmpty()) {
1168 LOG.error("VPN {} association to networks failed for networks: {}. ",
1169 vpn.getValue(), failStrings.toString());
1170 throw new Exception(failStrings.toString());
1176 * It handles the invocations to the createVPN RPC method.
1179 // TODO Clean up the exception handling
1180 @SuppressWarnings("checkstyle:IllegalCatch")
1181 public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1183 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1184 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1185 List<RpcError> errorList = new ArrayList<>();
1186 int failurecount = 0;
1187 int warningcount = 0;
1189 List<L3vpn> vpns = input.getL3vpn();
1190 for (L3vpn vpn : vpns) {
1191 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1192 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1193 formatAndLog(LOG::warn,
1194 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1195 vpn.getId().getValue())));
1199 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1200 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1201 formatAndLog(LOG::warn,
1202 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1203 vpn.getId().getValue())));
1207 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1209 if (vpn.getL3vni() != null) {
1210 l3vni = vpn.getL3vni();
1213 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1214 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1215 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1216 formatAndLog(LOG::warn,
1217 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1218 + "is already configured",
1219 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1223 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1224 if (operationalVpn.isPresent()) {
1225 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1226 formatAndLog(LOG::error,
1227 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1228 + "is still available. Please retry creation of a new vpn with the same RD"
1229 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1230 vpn.getRouteDistinguisher().get(0))));
1234 if (vpn.getRouterId() != null) {
1235 if (neutronvpnUtils.getNeutronRouter(vpn.getRouterId()) == null) {
1236 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1237 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router not found {}",
1238 vpn.getId().getValue(), vpn.getRouterId().getValue())));
1242 Uuid vpnId = neutronvpnUtils.getVpnForRouter(vpn.getRouterId(), true);
1243 if (vpnId != null) {
1244 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1245 formatAndLog(LOG::warn,
1246 "Creation of L3VPN failed for VPN {} due to router {} already associated to "
1247 + "another VPN {}", vpn.getId().getValue(), vpn.getRouterId().getValue(),
1248 vpnId.getValue())));
1253 if (vpn.getNetworkIds() != null) {
1254 int initialWarningCount = warningcount;
1255 for (Uuid nw : vpn.getNetworkIds()) {
1256 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1257 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1258 if (network == null) {
1259 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1260 formatAndLog(LOG::warn,
1261 "Creation of L3VPN failed for VPN {} due to network not found {}",
1262 vpn.getId().getValue(), nw.getValue())));
1264 } else if (vpnId != null) {
1265 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1266 formatAndLog(LOG::warn,
1267 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1268 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1269 vpnId.getValue())));
1273 if (warningcount != initialWarningCount) {
1278 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1279 vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
1280 vpnInstanceType, l3vni);
1281 } catch (Exception ex) {
1282 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1283 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1288 // if at least one succeeds; result is success
1289 // if none succeeds; result is failure
1290 if (failurecount + warningcount == vpns.size()) {
1291 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1293 List<String> errorResponseList = new ArrayList<>();
1294 if (!errorList.isEmpty()) {
1295 for (RpcError rpcError : errorList) {
1296 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1297 + ", ErrorMessage: " + rpcError.getMessage());
1300 errorResponseList.add("Operation successful with no errors");
1302 opBuilder.setResponse(errorResponseList);
1303 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1309 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1312 public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1314 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1315 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1316 Uuid inputVpnId = input.getId();
1317 List<VpnInstance> vpns = new ArrayList<>();
1318 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1321 if (inputVpnId == null) {
1323 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1325 Optional<VpnInstances> optionalVpns =
1326 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1328 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1329 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1330 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1331 // from getL3VPN output
1332 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1338 opBuilder.setL3vpnInstances(l3vpnList);
1339 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1343 String name = inputVpnId.getValue();
1344 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1345 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1346 // read VpnInstance Info
1347 Optional<VpnInstance> optionalVpn =
1348 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1350 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1352 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1353 vpns.add(optionalVpn.get());
1356 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1357 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1361 for (VpnInstance vpnInstance : vpns) {
1362 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1363 // create VpnMaps id
1364 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1365 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1366 List<String> ertList = new ArrayList<>();
1367 List<String> irtList = new ArrayList<>();
1369 if (vpnInstance.getIpv4Family().getVpnTargets() != null) {
1370 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1371 for (VpnTarget vpnTarget : vpnTargetList) {
1372 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1373 ertList.add(vpnTarget.getVrfRTValue());
1375 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1376 irtList.add(vpnTarget.getVrfRTValue());
1378 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1379 ertList.add(vpnTarget.getVrfRTValue());
1380 irtList.add(vpnTarget.getVrfRTValue());
1385 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1387 if (vpnInstance.getL3vni() != null) {
1388 l3vpn.setL3vni(vpnInstance.getL3vni());
1390 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1391 .class, new VpnMapKey(vpnId)).build();
1392 Optional<VpnMap> optionalVpnMap =
1393 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1395 if (optionalVpnMap.isPresent()) {
1396 VpnMap vpnMap = optionalVpnMap.get();
1397 l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1398 .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1400 l3vpnList.add(l3vpn.build());
1403 opBuilder.setL3vpnInstances(l3vpnList);
1404 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1406 } catch (ReadFailedException ex) {
1407 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1408 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1414 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1417 public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1419 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1420 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1421 List<RpcError> errorList = new ArrayList<>();
1423 int failurecount = 0;
1424 int warningcount = 0;
1425 List<Uuid> vpns = input.getId();
1426 for (Uuid vpn : vpns) {
1430 InstanceIdentifier<VpnInstance> vpnIdentifier =
1431 InstanceIdentifier.builder(VpnInstances.class)
1432 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1433 Optional<VpnInstance> optionalVpn =
1434 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1436 if (optionalVpn.isPresent()) {
1439 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1440 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1443 } catch (ReadFailedException ex) {
1444 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1445 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1450 // if at least one succeeds; result is success
1451 // if none succeeds; result is failure
1452 if (failurecount + warningcount == vpns.size()) {
1453 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1455 List<String> errorResponseList = new ArrayList<>();
1456 if (!errorList.isEmpty()) {
1457 for (RpcError rpcError : errorList) {
1458 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1459 + ", ErrorMessage: " + rpcError.getMessage());
1462 errorResponseList.add("Operation successful with no errors");
1464 opBuilder.setResponse(errorResponseList);
1465 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1470 public void createVpnInstanceForSubnet(Uuid subnetId) {
1471 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1472 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1475 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1476 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1477 removeVpn(subnetId);
1480 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1481 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1482 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1483 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1485 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1486 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1489 if (vpnId != null) {
1490 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1491 if (vpnMap == null) {
1492 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1493 + " cannot add subnet {} to VPN", vpnId.getValue(),
1497 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1498 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1499 if (isVpnOfTypeL2(vpnInstance)) {
1500 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1501 NeutronEvpnUtils.Operation.ADD);
1504 if (internetVpnId != null) {
1505 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1506 if (vpnMap == null) {
1507 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1508 + "subnet {} to VPN", internetVpnId.getValue(),
1513 final Uuid internetId = internetVpnId;
1514 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1515 List<Uuid> portList = sn.getPortList();
1516 if (portList != null) {
1517 for (final Uuid portId : portList) {
1518 String vpnInfName = portId.getValue();
1519 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1520 Port port = neutronvpnUtils.getNeutronPort(portId);
1522 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1523 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1526 final Boolean isRouterInterface = port.getDeviceOwner()
1527 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1528 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1529 txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1530 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1532 if (vpnIface == null) {
1533 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1534 Set<Uuid> listVpn = new HashSet<>();
1535 if (vpnId != null) {
1538 if (internetId != null) {
1539 listVpn.add(internetId);
1541 writeVpnInterfaceToDs(listVpn,
1542 vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
1543 if (sn.getRouterId() != null) {
1544 addToNeutronRouterInterfacesMap(sn.getRouterId(),portId.getValue());
1547 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1548 if (vpnId != null) {
1549 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1551 if (internetId != null) {
1552 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1561 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) {
1562 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1563 "removeSubnetFromVpn: at least one VPN must be not null");
1564 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1565 vpnId, internetVpnId);
1566 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1568 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1571 VpnMap vpnMap = null;
1572 VpnInstance vpnInstance = null;
1573 if (vpnId != null) {
1574 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1575 if (vpnMap == null) {
1576 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1577 vpnId.getValue(), subnet.getValue());
1580 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1582 if (internetVpnId == null) {
1583 internetVpnId = sn.getInternetVpnId();
1585 if (internetVpnId != null) {
1586 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1587 if (vpnMap == null) {
1588 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1589 + " from Internet VPN",
1590 internetVpnId.getValue(), subnet.getValue());
1594 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1595 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1596 NeutronEvpnUtils.Operation.DELETE);
1598 boolean subnetVpnAssociation = false;
1599 if (vpnId != null && sn.getVpnId() != null
1600 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1601 subnetVpnAssociation = true;
1602 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1603 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1604 subnetVpnAssociation = true;
1606 if (subnetVpnAssociation == false) {
1607 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1608 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1611 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1612 List<Uuid> portList = sn.getPortList();
1613 final Uuid internetId = internetVpnId;
1614 if (portList != null) {
1615 for (final Uuid portId : portList) {
1616 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1617 final Port port = neutronvpnUtils.getNeutronPort(portId);
1618 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1619 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1621 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1624 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1625 + "port is absent in Neutron config DS", portId.getValue(),
1631 //update subnet-vpn association
1632 removeFromSubnetNode(subnet, null, null, vpnId, null);
1635 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1636 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1637 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1639 Uuid internalVpnId = sm.getVpnId();
1640 if (internalVpnId == null) {
1641 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1642 sm.getId().getValue());
1645 if (isBeingAssociated) {
1646 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1648 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1651 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1652 txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1653 if (isBeingAssociated) {
1654 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1655 true, true, wrtConfigTxn);
1657 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1663 // Check for ports on this subnet and update association of
1664 // corresponding vpn-interfaces to internet vpn
1665 List<Uuid> portList = sm.getPortList();
1666 if (portList != null) {
1667 for (Uuid port : portList) {
1668 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1669 port.getValue(), isBeingAssociated);
1670 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1671 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1672 if (isBeingAssociated) {
1673 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1676 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1683 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1684 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1685 oldVpnId.getValue(), newVpnId.getValue());
1686 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1687 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1688 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1689 Uuid vpnExtUuid = netIsExternal ? null
1690 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1691 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1693 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1697 //Update Router Interface first synchronously.
1698 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1699 ListenableFuture<Void> future =
1700 txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> updateVpnInterface(newVpnId, oldVpnId,
1701 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1702 isBeingAssociated, true, tx));
1703 Futures.addCallback(future, new FutureCallback<Void>() {
1705 public void onSuccess(Void result) {
1706 // Check for ports on this subnet and update association of
1707 // corresponding vpn-interfaces to external vpn
1708 List<Uuid> portList = sn.getPortList();
1709 if (portList != null) {
1710 for (Uuid port : portList) {
1711 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1712 port.getValue(), isBeingAssociated);
1713 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1714 txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1715 tx -> updateVpnInterface(newVpnId, oldVpnId,
1716 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1723 public void onFailure(Throwable throwable) {
1725 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1727 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1729 }, MoreExecutors.directExecutor());
1734 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1735 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1736 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1739 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1740 synchronized (routerId.getValue().intern()) {
1741 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1743 Optional<RouterInterfaces> optRouterInterfaces =
1744 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1745 routerInterfacesId);
1746 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1747 .setInterfaceId(interfaceName).build();
1748 if (optRouterInterfaces.isPresent()) {
1749 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1750 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1753 // TODO Shouldn't we be doing something with builder and interfaces?
1754 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1755 // List<Interfaces> interfaces = new ArrayList<>();
1756 // interfaces.add(routerInterface);
1758 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1759 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1762 } catch (ReadFailedException | TransactionCommitFailedException e) {
1763 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1768 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1769 synchronized (routerId.getValue().intern()) {
1770 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1772 Optional<RouterInterfaces> optRouterInterfaces =
1773 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1774 routerInterfacesId);
1775 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1776 .setInterfaceId(interfaceName).build();
1777 if (optRouterInterfaces.isPresent()) {
1778 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1779 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1780 if (interfaces != null && interfaces.remove(routerInterface)) {
1781 if (interfaces.isEmpty()) {
1782 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1783 routerInterfacesId);
1785 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1786 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1790 } catch (ReadFailedException | TransactionCommitFailedException e) {
1791 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1797 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1798 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1799 * route will be ignored.
1801 * @param vpnName the VPN identifier
1802 * @param interVpnLinkRoutes The list of static routes
1803 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1805 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1806 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1807 for (Routes route : interVpnLinkRoutes) {
1808 String nexthop = String.valueOf(route.getNexthop().getValue());
1809 String destination = String.valueOf(route.getDestination().getValue());
1810 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1811 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1812 AddStaticRouteInput rpcInput =
1813 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1814 .setVpnInstanceName(vpnName.getValue())
1816 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1817 RpcResult<AddStaticRouteOutput> rpcResult;
1819 rpcResult = labelOuputFtr.get();
1820 if (rpcResult.isSuccessful()) {
1821 LOG.debug("Label generated for destination {} is: {}",
1822 destination, rpcResult.getResult().getLabel());
1824 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1825 destination, nexthop, rpcResult.getErrors());
1827 } catch (InterruptedException | ExecutionException e) {
1828 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1829 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1832 // Any other case is a fault.
1833 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1834 String.valueOf(route.getDestination().getValue()), nexthop);
1841 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1842 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1844 * @param vpnName the VPN identifier
1845 * @param interVpnLinkRoutes The list of static routes
1846 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1848 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1849 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1850 for (Routes route : interVpnLinkRoutes) {
1851 String nexthop = String.valueOf(route.getNexthop().getValue());
1852 String destination = String.valueOf(route.getDestination().getValue());
1853 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1854 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1855 RemoveStaticRouteInput rpcInput =
1856 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1857 .setVpnInstanceName(vpnName.getValue())
1860 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1861 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1863 // Any other case is a fault.
1864 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1865 String.valueOf(route.getDestination().getValue()), nexthop);
1872 * Returns true if the specified nexthop is the other endpoint in an
1873 * InterVpnLink, regarding one of the VPN's point of view.
1875 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1877 interVpnLink != null
1878 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1879 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1880 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1881 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1885 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
1886 List<Adjacency> adjList = new ArrayList<>();
1887 Map<String, List<String>> adjMap = new HashMap<>();
1888 for (Routes route : routeList) {
1889 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1890 LOG.error("Incorrect input received for extra route. {}", route);
1892 String nextHop = String.valueOf(route.getNexthop().getValue());
1893 String destination = String.valueOf(route.getDestination().getValue());
1894 if (!nextHop.equals(fixedIp)) {
1895 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1898 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
1900 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1901 if (!hops.contains(nextHop)) {
1907 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
1908 final String destination = entry.getKey();
1909 final List<String> ipList = entry.getValue();
1910 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1911 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
1912 .setKey(new AdjacencyKey(destination)).build();
1918 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1919 checkAlarmExtraRoutes(vpnId, routeList);
1921 for (Routes route : routeList) {
1922 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1923 LOG.error("Incorrect input received for extra route. {}", route);
1925 String nextHop = String.valueOf(route.getNexthop().getValue());
1926 String destination = String.valueOf(route.getDestination().getValue());
1927 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
1929 if (infName != null) {
1930 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
1931 destination, vpnId.getValue(), nextHop, infName);
1932 boolean isLockAcquired = false;
1934 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
1935 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1936 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
1937 .child(Adjacency.class, new AdjacencyKey(destination));
1938 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1939 LogicalDatastoreType.CONFIGURATION, path);
1940 if (existingAdjacency.isPresent()
1941 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1942 LOG.error("The route with destination {} nextHop {} is already present as"
1943 + " a primary adjacency for interface {}. Skipping adjacency addition.",
1944 destination, nextHop, infName);
1947 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1948 .setNextHopIpList(Collections.singletonList(nextHop)).setKey(new AdjacencyKey(destination))
1949 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
1950 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1951 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1953 } catch (TransactionCommitFailedException e) {
1954 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
1955 destination, nextHop, e);
1956 } catch (ReadFailedException e) {
1957 LOG.error("Exception on reading data-store ", e);
1959 if (isLockAcquired) {
1960 interfaceLock.unlock(infName);
1964 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1965 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1972 * This method setup or down an alarm about extra route fault.
1973 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
1974 * available RDs, then an alarm and an error is generated.<br>
1975 * <b>Be careful</b> the routeList could be changed.
1977 * @param vpnId the vpnId of vpn to control.
1978 * @param routeList the list of router to check, it could be modified.
1980 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
1981 if (!neutronvpnAlarm.isAlarmEnabled()) {
1982 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
1985 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
1986 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
1987 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
1991 List<Routes> routesError = new ArrayList();
1992 for (Routes route : routeList) {
1993 // count the number of nexthops for each same route.getDestingation().getValue()
1994 String destination = String.valueOf(route.getDestination().getValue());
1995 String nextHop = String.valueOf(route.getNexthop().getValue());
1996 List<String> nextHopList = new ArrayList();
1997 nextHopList.add(nextHop);
1999 for (Routes routeTmp : routeList) {
2000 String routeDest = String.valueOf(routeTmp.getDestination().getValue());
2001 if (!destination.equals(routeDest)) {
2004 String routeNextH = String.valueOf(routeTmp.getNexthop().getValue());
2005 if (nextHop.equals(routeNextH)) {
2009 nextHopList.add(new String(routeTmp.getNexthop().getValue()));
2011 final List<String> rdList = new ArrayList<>();
2012 if (vpnInstance.getIpv4Family() != null
2013 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2014 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2020 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2021 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2022 if (rd != null && !rdList.contains(rd)) {
2027 // 1. VPN Instance Name
2028 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2031 Uuid routerUuid = neutronvpnUtils.getRouterforVpn(vpnId);
2032 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2033 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2035 // 3. List of RDs associated with the VPN
2036 detailsAlarm.append(" List of RDs associated with the VPN: ");
2037 for (String s : rdList) {
2038 detailsAlarm.append(s);
2039 detailsAlarm.append(", ");
2042 // 4. Prefix in question
2043 detailsAlarm.append(" for prefix: ");
2044 detailsAlarm.append(route.getDestination().getValue());
2046 // 5. List of NHs for the prefix
2047 detailsAlarm.append(" for nextHops: ");
2048 for (String s : nextHopList) {
2049 detailsAlarm.append(s);
2050 detailsAlarm.append(", ");
2053 if (rdList.size() < nbNextHops) {
2054 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2055 LOG.error("there are too many next hops for prefixe in vpn {}", vpnId);
2056 routesError.add(route);
2058 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2061 //in routesError there are a few route raised in alarm, so they have not to be used
2062 routeList.removeAll(routesError);
2065 // TODO Clean up the exception handling
2066 @SuppressWarnings("checkstyle:IllegalCatch")
2067 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2068 for (Routes route : routeList) {
2069 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2070 boolean isLockAcquired = false;
2071 String nextHop = String.valueOf(route.getNexthop().getValue());
2072 String destination = String.valueOf(route.getDestination().getValue());
2073 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2075 if (infName == null) {
2076 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2077 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2078 // Proceed to remove the next extra-route
2081 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2082 destination, vpnId.getValue(), nextHop, infName);
2084 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2085 InstanceIdentifier.builder(VpnInterfaces.class)
2086 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2087 .augmentation(Adjacencies.class)
2088 .child(Adjacency.class, new AdjacencyKey(destination))
2092 // Looking for existing prefix in MDSAL database
2093 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2094 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2095 boolean updateNextHops = false;
2096 List<String> nextHopList = new ArrayList<>();
2097 if (adjacency.isPresent()) {
2098 List<String> nhListRead = adjacency.get().getNextHopIpList();
2099 if (nhListRead.size() > 1) { // ECMP case
2100 for (String nextHopRead : nhListRead) {
2101 if (nextHopRead.equals(nextHop)) {
2102 updateNextHops = true;
2104 nextHopList.add(nextHopRead);
2110 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2111 if (updateNextHops) {
2112 // An update must be done, not including the current next hop
2113 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2114 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2115 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2116 .setNextHopIpList(nextHopList)
2117 .setKey(new AdjacencyKey(destination))
2119 Adjacencies erAdjs =
2120 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2121 VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2122 .addAugmentation(Adjacencies.class, erAdjs).build();
2123 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2124 vpnIfIdentifier, vpnIf);
2126 // Remove the whole route
2127 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2128 adjacencyIdentifier);
2129 LOG.trace("extra route {} deleted successfully", route);
2131 } catch (TransactionCommitFailedException | ReadFailedException e) {
2132 LOG.error("exception in deleting extra route with destination {} for interface {}",
2133 destination, infName, e);
2135 if (isLockAcquired) {
2136 interfaceLock.unlock(infName);
2140 LOG.error("Incorrect input received for extra route: {}", route);
2145 public void removeVpn(Uuid id) {
2147 VpnMap vpnMap = neutronvpnUtils.getVpnMap(id);
2148 Uuid router = vpnMap != null ? vpnMap.getRouterId() : null;
2149 // dissociate router
2150 if (router != null) {
2151 dissociateRouterFromVpn(id, router);
2153 // dissociate networks
2154 if (!id.equals(router) && vpnMap.getNetworkIds() != null) {
2155 dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
2157 // remove entire vpnMaps node
2158 deleteVpnMapsNode(id);
2160 // remove vpn-instance
2161 deleteVpnInstance(id);
2164 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2165 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2168 // TODO Clean up the exception handling
2169 @SuppressWarnings("checkstyle:IllegalCatch")
2170 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2171 updateVpnMaps(vpnId, null, routerId, null, null);
2172 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2173 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2174 for (Uuid subnetId : routerSubnets) {
2175 Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
2176 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) {
2177 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2178 NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
2183 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2184 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2186 } catch (Exception e) {
2187 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2188 .getValue(), vpnId.getValue(), e);
2192 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2193 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2194 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2195 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2196 for (Uuid subnet : routerSubnets) {
2197 IpVersionChoice version = NeutronvpnUtils
2198 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2199 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2200 addSubnetToVpn(vpnId, subnet, null);
2202 addSubnetToVpn(vpnId, subnet, internetVpnId);
2207 // TODO Clean up the exception handling
2208 @SuppressWarnings("checkstyle:IllegalCatch")
2209 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2211 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2212 boolean vpnInstanceIpVersionsRemoved = false;
2213 IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
2214 for (Uuid subnetId : routerSubnets) {
2215 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
2216 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
2217 vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
2218 .getIpVersionFromString(sn.getSubnetIp()));
2219 vpnInstanceIpVersionsRemoved = true;
2221 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2222 updateVpnForSubnet(vpnId, routerId, subnetId, false);
2225 if (vpnInstanceIpVersionsRemoved) {
2226 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false);
2228 clearFromVpnMaps(vpnId, routerId, null);
2230 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2231 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2233 } catch (Exception e) {
2234 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2235 .getValue(), vpnId.getValue(), e);
2240 * Parses and associates networks list with given VPN.
2242 * @param vpnId Uuid of given VPN.
2243 * @param networks List list of network Ids (Uuid), which will be associated.
2244 * @return list of formatted strings with detailed error messages.
2247 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networks) {
2248 List<String> failedNwList = new ArrayList<>();
2249 HashSet<Uuid> passedNwList = new HashSet<>();
2250 if (networks.isEmpty()) {
2251 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2252 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2254 return failedNwList;
2256 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2257 if (vpnInstance == null) {
2258 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2259 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2260 + "in ConfigDS", vpnId.getValue()));
2261 return failedNwList;
2264 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2265 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2267 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2268 + "associated with", vpnId.getValue()));
2269 return failedNwList;
2271 for (Uuid nw : networks) {
2272 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2273 if (network == null) {
2274 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2275 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2279 NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
2280 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2281 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2282 nw.getValue(), vpnId.getValue());
2283 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2284 nw.getValue(), vpnId.getValue()));
2287 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2288 if (networkVpnId != null) {
2289 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2290 nw.getValue(), networkVpnId.getValue());
2291 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2292 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2295 if (neutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2296 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2297 nw.getValue(), vpnId.getValue());
2298 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2299 nw.getValue(), vpnId.getValue()));
2302 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2303 if (networkSubnets == null) {
2304 passedNwList.add(nw);
2307 for (Uuid subnet : networkSubnets) {
2308 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnet);
2309 if (subnetVpnId != null) {
2310 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {} as it is already "
2311 + "associated", subnet.getValue(), subnetVpnId.getValue());
2312 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s as it is already "
2313 + "associated", subnet.getValue(), vpnId.getValue()));
2316 Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
2317 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sm, vpnId)) {
2318 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2319 NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()), true);
2321 if (!neutronvpnUtils.getIsExternal(network)) {
2322 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnet.getValue(),
2324 addSubnetToVpn(vpnId, subnet, null);
2327 passedNwList.add(nw);
2329 } catch (ReadFailedException e) {
2330 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2332 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2335 LOG.info("associateNetworksToVpn: update VPN {} with networks list: {}", vpnId.getValue(),
2336 passedNwList.toString());
2337 updateVpnMaps(vpnId, null, null, null, new ArrayList<Uuid>(passedNwList));
2338 return failedNwList;
2341 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2342 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2343 if (vpnOpDataEntry == null) {
2344 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2347 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2350 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2351 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2352 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2354 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2355 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2357 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2360 updateVpnInternetForSubnet(sm, vpnId, true);
2361 if (!(vpnOpDataEntry.isIpv6Configured())
2362 && (NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6)) {
2363 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2364 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true);
2371 * Parses and disassociates networks list from given VPN.
2373 * @param vpnId Uuid of given VPN.
2374 * @param networks List list of network Ids (Uuid), which will be disassociated.
2375 * @return list of formatted strings with detailed error messages.
2378 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networks) {
2379 List<String> failedNwList = new ArrayList<>();
2380 HashSet<Uuid> passedNwList = new HashSet<>();
2381 if (networks.isEmpty()) {
2382 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2383 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2385 return failedNwList;
2387 for (Uuid nw : networks) {
2388 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2389 if (network == null) {
2390 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2391 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2395 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2396 if (networkVpnId == null) {
2397 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2398 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2402 if (!vpnId.equals(networkVpnId)) {
2403 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2404 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2405 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2406 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2410 if (neutronvpnUtils.getIsExternal(network)) {
2411 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2412 passedNwList.add(nw);
2415 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2416 nw.getValue(), vpnId.getValue());
2417 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2422 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2423 if (networkSubnets == null) {
2424 passedNwList.add(nw);
2427 for (Uuid subnet : networkSubnets) {
2428 Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
2429 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sm, vpnId)) {
2430 IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
2431 IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2432 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2433 ipVersionsToRemove.addVersion(ipVersion), false);
2435 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2437 removeSubnetFromVpn(vpnId, subnet, null);
2438 passedNwList.add(nw);
2441 LOG.info("dissociateNetworksFromVpn: Withdraw networks list {} from VPN {}", networks.toString(),
2443 clearFromVpnMaps(vpnId, null, new ArrayList<Uuid>(passedNwList));
2444 return failedNwList;
2447 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2448 if (!removeExternalNetworkFromVpn(extNet)) {
2451 // check, if there is another Provider Networks associated with given VPN
2452 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2453 if (vpnNets != null) {
2454 for (Uuid netId : vpnNets) {
2455 if (neutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2456 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2457 + "{}", vpnId.getValue(), netId.getValue());
2462 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2463 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2464 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2465 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2466 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2468 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2471 updateVpnInternetForSubnet(sm, vpnId, false);
2473 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2474 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue());
2475 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false);
2480 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2483 // TODO Clean up the exception handling
2484 @SuppressWarnings("checkstyle:IllegalCatch")
2485 public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2487 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2488 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2489 LOG.debug("associateNetworks {}", input);
2490 StringBuilder returnMsg = new StringBuilder();
2491 Uuid vpnId = input.getVpnId();
2494 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2495 List<Uuid> netIds = input.getNetworkId();
2496 if (netIds != null && !netIds.isEmpty()) {
2497 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2498 if (!failed.isEmpty()) {
2499 returnMsg.append(failed);
2503 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2505 if (returnMsg.length() != 0) {
2506 opBuilder.setResponse(
2507 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2508 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2509 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2511 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2513 } catch (Exception ex) {
2514 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2515 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2516 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2518 LOG.debug("associateNetworks returns..");
2523 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2526 // TODO Clean up the exception handling
2527 @SuppressWarnings("checkstyle:IllegalCatch")
2528 public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
2530 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
2531 LOG.debug("associateRouter {}", input);
2532 StringBuilder returnMsg = new StringBuilder();
2533 Uuid vpnId = input.getVpnId();
2534 Uuid routerId = input.getRouterId();
2536 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2537 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
2538 if (vpnMap != null) {
2540 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2541 if (vpnMap.getRouterId() != null) {
2542 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2543 .append(vpnMap.getRouterId().getValue());
2544 } else if (extVpnId != null) {
2545 returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
2546 + "another VPN ").append(extVpnId.getValue());
2548 associateRouterToVpn(vpnId, routerId);
2551 returnMsg.append("router not found : ").append(routerId.getValue());
2554 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2556 if (returnMsg.length() != 0) {
2557 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
2558 formatAndLog(LOG::error, "associate router to vpn {} failed due to {}", routerId.getValue(),
2559 returnMsg)).build());
2561 result.set(RpcResultBuilder.<Void>success().build());
2563 } catch (Exception ex) {
2564 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION,
2565 formatAndLog(LOG::error, "associate router {} to vpn {} failed due to {}", routerId.getValue(),
2566 vpnId.getValue(), ex.getMessage(), ex)).build());
2568 LOG.debug("associateRouter returns..");
2572 /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2575 // TODO Clean up the exception handling
2576 @SuppressWarnings("checkstyle:IllegalCatch")
2577 public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2578 GetFixedIPsForNeutronPortInput input) {
2579 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2580 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2581 Uuid portId = input.getPortId();
2582 StringBuilder returnMsg = new StringBuilder();
2584 List<String> fixedIPList = new ArrayList<>();
2585 Port port = neutronvpnUtils.getNeutronPort(portId);
2587 List<FixedIps> fixedIPs = port.getFixedIps();
2588 for (FixedIps ip : fixedIPs) {
2589 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
2592 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2594 if (returnMsg.length() != 0) {
2595 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2597 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2598 returnMsg)).build());
2600 opBuilder.setFixedIPs(fixedIPList);
2601 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2603 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2605 } catch (Exception ex) {
2606 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2607 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2608 portId.getValue(), ex.getMessage(), ex)).build());
2614 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2617 // TODO Clean up the exception handling
2618 @SuppressWarnings("checkstyle:IllegalCatch")
2619 public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2621 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2622 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2624 LOG.debug("dissociateNetworks {}", input);
2625 StringBuilder returnMsg = new StringBuilder();
2626 Uuid vpnId = input.getVpnId();
2629 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2630 List<Uuid> netIds = input.getNetworkId();
2631 if (netIds != null && !netIds.isEmpty()) {
2632 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2633 if (!failed.isEmpty()) {
2634 returnMsg.append(failed);
2638 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2640 if (returnMsg.length() != 0) {
2641 opBuilder.setResponse(
2642 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2643 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2644 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2646 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2648 } catch (Exception ex) {
2649 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2650 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2651 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2653 LOG.debug("dissociateNetworks returns..");
2658 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2661 // TODO Clean up the exception handling
2662 @SuppressWarnings("checkstyle:IllegalCatch")
2663 public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
2665 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
2667 LOG.debug("dissociateRouter {}", input);
2668 StringBuilder returnMsg = new StringBuilder();
2669 Uuid vpnId = input.getVpnId();
2670 Uuid routerId = input.getRouterId();
2672 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2673 if (routerId != null) {
2674 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
2676 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2677 if (vpnId.equals(routerVpnId)) {
2678 dissociateRouterFromVpn(vpnId, routerId);
2680 if (routerVpnId == null) {
2681 returnMsg.append("input router ").append(routerId.getValue())
2682 .append(" not associated to any vpn yet");
2684 returnMsg.append("input router ").append(routerId.getValue())
2685 .append(" associated to vpn ")
2686 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2690 returnMsg.append("router not found : ").append(routerId.getValue());
2694 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2696 if (returnMsg.length() != 0) {
2697 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
2698 formatAndLog(LOG::error, "dissociate router {} to vpn {} failed due to {}", routerId.getValue(),
2699 vpnId.getValue(), returnMsg)).build());
2701 result.set(RpcResultBuilder.<Void>success().build());
2703 } catch (Exception ex) {
2704 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION,
2705 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}", routerId.getValue(),
2706 vpnId.getValue(), ex.getMessage(), ex)).build());
2708 LOG.debug("dissociateRouter returns..");
2713 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2714 // check if the router is associated to some VPN
2715 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2716 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2717 if (vpnId != null) {
2718 // remove existing external vpn interfaces
2719 for (Uuid subnetId : routerSubnetIds) {
2720 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2722 clearFromVpnMaps(vpnId, routerId, null);
2724 // remove existing internal vpn interfaces
2725 for (Uuid subnetId : routerSubnetIds) {
2726 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2729 // delete entire vpnMaps node for internal VPN
2730 deleteVpnMapsNode(routerId);
2732 // delete vpn-instance for internal VPN
2733 deleteVpnInstance(routerId);
2736 protected Subnet getNeutronSubnet(Uuid subnetId) {
2737 return neutronvpnUtils.getNeutronSubnet(subnetId);
2740 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2741 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2743 return sn.getGatewayIp();
2749 protected Network getNeutronNetwork(Uuid networkId) {
2750 return neutronvpnUtils.getNeutronNetwork(networkId);
2753 protected Port getNeutronPort(String name) {
2754 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2757 protected Port getNeutronPort(Uuid portId) {
2758 return neutronvpnUtils.getNeutronPort(portId);
2761 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2762 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2765 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2766 return neutronvpnUtils.getNetworksForVpn(vpnId);
2770 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2772 * @return a List of String to be printed on screen
2773 * @throws ReadFailedException if there was a problem reading from the data store
2775 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2776 List<String> result = new ArrayList<>();
2777 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2779 result.add("-------------------------------------------------------------------------------------------");
2780 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2782 Optional<Ports> ports = syncReadOptional(dataBroker, CONFIGURATION, portidentifier);
2783 if (ports.isPresent() && ports.get().getPort() != null) {
2784 for (Port port : ports.get().getPort()) {
2785 List<FixedIps> fixedIPs = port.getFixedIps();
2786 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2787 List<String> ipList = new ArrayList<>();
2788 for (FixedIps fixedIp : fixedIPs) {
2789 IpAddress ipAddress = fixedIp.getIpAddress();
2790 if (ipAddress.getIpv4Address() != null) {
2791 ipList.add(ipAddress.getIpv4Address().getValue());
2793 ipList.add(ipAddress.getIpv6Address().getValue());
2796 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2797 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2798 ipList.toString()));
2800 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2801 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2810 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2812 * @param vpnuuid Uuid of the VPN whose config must be shown
2813 * @return formatted output list
2814 * @throws InterruptedException if there was a thread related problem getting the data to display
2815 * @throws ExecutionException if there was any other problem getting the data to display
2817 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2818 List<String> result = new ArrayList<>();
2819 if (vpnuuid == null) {
2821 result.add("Displaying VPN config for all VPNs");
2822 result.add("To display VPN config for a particular VPN, use the following syntax");
2823 result.add(getshowVpnConfigCLIHelp());
2825 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2826 if (rpcResult.isSuccessful()) {
2828 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2830 result.add(String.format(" %-80s ", "Import-RTs"));
2832 result.add(String.format(" %-80s ", "Export-RTs"));
2834 result.add(String.format(" %-76s ", "Subnet IDs"));
2836 result.add("------------------------------------------------------------------------------------");
2838 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2839 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2840 .rev150602.VpnInstance vpn : vpnList) {
2841 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2843 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2844 vpn.getRouteDistinguisher()));
2846 result.add(String.format(" %-80s ", vpn.getImportRT()));
2848 result.add(String.format(" %-80s ", vpn.getExportRT()));
2851 Uuid vpnid = vpn.getId();
2852 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
2853 if (!subnetList.isEmpty()) {
2854 for (Uuid subnetuuid : subnetList) {
2855 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2858 result.add(String.format(" %-76s ", "\" \""));
2861 result.add("----------------------------------------");
2865 String errortag = rpcResult.getErrors().iterator().next().getTag();
2866 if (Objects.equals(errortag, "")) {
2868 result.add("No VPN has been configured yet");
2869 } else if (Objects.equals(errortag, "invalid-value")) {
2871 result.add("VPN " + vpnuuid.getValue() + " is not present");
2873 result.add("error getting VPN info : " + rpcResult.getErrors());
2874 result.add(getshowVpnConfigCLIHelp());
2880 protected void createExternalVpnInterfaces(Uuid extNetId) {
2881 if (extNetId == null) {
2882 LOG.error("createExternalVpnInterfaces: external network is null");
2886 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2887 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2888 LOG.error("No external ports attached to external network {}", extNetId.getValue());
2892 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
2893 for (String elanInterface : extElanInterfaces) {
2894 createExternalVpnInterface(extNetId, elanInterface, tx);
2896 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
2899 // TODO Clean up the exception handling
2900 @SuppressWarnings("checkstyle:IllegalCatch")
2901 protected void removeExternalVpnInterfaces(Uuid extNetId) {
2902 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2903 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2904 LOG.error("No external ports attached for external network {}", extNetId.getValue());
2907 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
2908 for (String elanInterface : extElanInterfaces) {
2909 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2910 .buildVpnInterfaceIdentifier(elanInterface);
2911 LOG.info("Removing vpn interface {}", elanInterface);
2912 tx.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2914 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
2917 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2918 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null,
2919 false /* not a router iface */, wrtConfigTxn);
2922 // TODO Clean up the exception handling
2923 @SuppressWarnings("checkstyle:IllegalCatch")
2924 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
2925 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2926 if (vpnIdList.isEmpty() || infName == null) {
2927 LOG.error("vpn id or interface is null");
2930 if (wrtConfigTxn == null) {
2931 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
2932 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, isRouterInterface, tx)), LOG,
2933 "Error writing VPN interface");
2936 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
2937 for (Uuid vpnId: vpnIdList) {
2938 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
2939 AssociatedSubnetType.V4AndV6Subnets);
2940 vpnIdListStruct.add(vpnInstance);
2943 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2944 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2946 .setVpnInstanceNames(vpnIdListStruct)
2947 .setRouterInterface(isRouterInterface);
2948 if (adjacencies != null) {
2949 vpnb.addAugmentation(Adjacencies.class, adjacencies);
2951 VpnInterface vpnIf = vpnb.build();
2953 LOG.info("Creating vpn interface {}", vpnIf);
2954 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2955 } catch (Exception ex) {
2956 LOG.error("Creation of vpninterface {} failed", infName, ex);
2960 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
2961 WriteTransaction wrtConfigTxn) {
2962 if (vpnId == null || infName == null) {
2963 LOG.error("vpn id or interface is null");
2966 if (wrtConfigTxn == null) {
2967 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
2968 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
2969 }), LOG, "Error updating VPN interface with adjacencies");
2973 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2974 boolean isLockAcquired = false;
2976 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2977 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
2978 .syncReadOptional(dataBroker, LogicalDatastoreType
2979 .CONFIGURATION, vpnIfIdentifier);
2980 if (optionalVpnInterface.isPresent()) {
2981 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
2982 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
2984 if (adjacencies == null) {
2985 if (isLockAcquired) {
2986 interfaceLock.unlock(infName);
2990 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
2991 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
2992 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
2993 optionalVpnInterface.get().getVpnInstanceNames());
2994 if (listVpnInstances.isEmpty() || !VpnHelper
2995 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),listVpnInstances)) {
2996 VpnInstanceNames vpnInstance = VpnHelper
2997 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
2998 listVpnInstances.add(vpnInstance);
2999 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3002 VpnInstanceNames vpnInstance = VpnHelper
3003 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3004 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3005 listVpnInstances.add(vpnInstance);
3006 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3008 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3009 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder.build());
3011 } catch (IllegalStateException | ReadFailedException ex) {
3012 LOG.error("Update of vpninterface {} failed", infName, ex);
3014 if (isLockAcquired) {
3015 interfaceLock.unlock(infName);
3020 private String getshowVpnConfigCLIHelp() {
3021 StringBuilder help = new StringBuilder("Usage:");
3022 help.append("display vpn-config [-vid/--vpnid <id>]");
3023 return help.toString();
3026 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3027 InterruptedException {
3028 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3029 .setVpnId(vpnId).build();
3030 LOG.info("publishing notification upon association of router to VPN");
3031 notificationPublishService.putNotification(routerAssociatedToVpn);
3034 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3035 InterruptedException {
3036 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3037 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3038 LOG.info("publishing notification upon disassociation of router from VPN");
3039 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3042 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3043 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3047 public Future<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3048 return neutronEvpnManager.createEVPN(input);
3052 public Future<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3053 return neutronEvpnManager.getEVPN(input);
3057 public Future<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3058 return neutronEvpnManager.deleteEVPN(input);
3061 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3062 Uuid extNetId = extNet.getUuid();
3063 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3064 .child(Networks.class, new NetworksKey(extNetId)).build();
3067 Optional<Networks> optionalExtNets =
3068 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3070 if (!optionalExtNets.isPresent()) {
3071 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3072 extNetId.getValue());
3075 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3076 builder.setVpnid(vpnId);
3077 Networks networks = builder.build();
3078 // Add Networks object to the ExternalNetworks list
3079 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3080 extNetId.getValue());
3081 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3084 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3085 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3086 extNetId.getValue(), ex);
3091 private boolean removeExternalNetworkFromVpn(Network extNet) {
3092 Uuid extNetId = extNet.getUuid();
3093 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3094 .child(Networks.class, new NetworksKey(extNetId)).build();
3096 Optional<Networks> optionalNets =
3097 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3099 NetworksBuilder builder = null;
3100 if (optionalNets.isPresent()) {
3101 builder = new NetworksBuilder(optionalNets.get());
3103 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3104 extNetId.getValue());
3107 builder.setVpnid(null);
3108 Networks networks = builder.build();
3109 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3110 extNetId.getValue());
3111 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3113 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3114 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3115 extNetId.getValue(), ex);
3120 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3121 Optional<String> existingVpnName = Optional.of(primaryRd);
3122 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3124 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3125 .syncReadOptional(dataBroker, OPERATIONAL, neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3126 } catch (ReadFailedException e) {
3127 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3129 /*Read failed. We don't know if a VPN exists or not.
3130 * Return primaryRd to halt caller execution, to be safe.*/
3131 return existingVpnName;
3133 if (vpnInstanceOpDataOptional.isPresent()) {
3134 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3136 existingVpnName = Optional.absent();
3138 return existingVpnName;
3141 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3142 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3145 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3146 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3149 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3150 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3153 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3154 String message = tuple.getMessage();
3155 logger.accept(message);