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;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.Map.Entry;
33 import java.util.Objects;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.function.Consumer;
40 import javax.annotation.Nonnull;
41 import javax.annotation.Nullable;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
45 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
46 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
47 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
48 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
49 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
50 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
51 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
52 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
54 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
55 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
56 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
57 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
58 import org.opendaylight.netvirt.elanmanager.api.IElanService;
59 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
60 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
61 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
62 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
63 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
64 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
65 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
174 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
175 import org.opendaylight.yangtools.yang.common.RpcError;
176 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
177 import org.opendaylight.yangtools.yang.common.RpcResult;
178 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
179 import org.slf4j.Logger;
180 import org.slf4j.LoggerFactory;
181 import org.slf4j.helpers.FormattingTuple;
182 import org.slf4j.helpers.MessageFormatter;
185 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
187 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
188 private static long LOCK_WAIT_TIME = 10L;
190 private final DataBroker dataBroker;
191 private final ManagedNewTransactionRunner txRunner;
192 private final NotificationPublishService notificationPublishService;
193 private final VpnRpcService vpnRpcService;
194 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
195 private final IElanService elanService;
196 private final NeutronvpnConfig neutronvpnConfig;
197 private final NeutronEvpnManager neutronEvpnManager;
198 private final NeutronEvpnUtils neutronEvpnUtils;
199 private final JobCoordinator jobCoordinator;
200 private final NeutronvpnUtils neutronvpnUtils;
201 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
202 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
203 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
204 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
207 public NeutronvpnManager(
208 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
209 final VpnRpcService vpnRpcSrv, final IElanService elanService,
210 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
211 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
212 final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
213 this.dataBroker = dataBroker;
214 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
215 notificationPublishService = notiPublishService;
216 vpnRpcService = vpnRpcSrv;
217 this.elanService = elanService;
218 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
219 this.neutronvpnConfig = neutronvpnConfig;
220 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
221 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
222 this.jobCoordinator = jobCoordinator;
223 this.neutronvpnUtils = neutronvpnUtils;
230 public void close() {
231 LOG.info("{} close", getClass().getSimpleName());
234 private void configureFeatures() {
235 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
236 Neutron.class).child(Features.class).child(
237 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
238 Feature feature = new FeatureBuilder().setKey(new FeatureKey(OperationalPortStatus.class)).build();
240 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
241 } catch (TransactionCommitFailedException e) {
242 LOG.warn("Error configuring feature {}", feature, e);
246 public String getOpenDaylightVniRangesConfig() {
247 return neutronvpnConfig.getOpendaylightVniRanges();
250 // TODO Clean up the exception handling
251 @SuppressWarnings("checkstyle:IllegalCatch")
252 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
253 NetworkAttributes.NetworkType networkType, long segmentationId) {
255 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
256 synchronized (subnetId.getValue().intern()) {
257 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
258 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
259 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
260 if (sn.isPresent()) {
261 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
262 subnetId.getValue());
265 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId))
266 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
267 .setNetworkType(networkType).setSegmentationId(segmentationId);
268 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
269 subnetId.getValue());
270 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
271 subnetMapIdentifier, subnetmapBuilder.build());
273 } catch (TransactionCommitFailedException | ReadFailedException e) {
274 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
276 // check if there are ports to update for already created Subnetmap node
277 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
278 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
279 if (entry.getValue().getValue().equals(subnetId.getValue())) {
280 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
281 unprocessedPortsMap.remove(entry.getKey());
286 protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) {
287 Subnetmap subnetmap = null;
288 SubnetmapBuilder builder = null;
289 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
290 .child(Subnetmap.class, new SubnetmapKey(subnetId))
293 synchronized (subnetId.getValue().intern()) {
294 Optional<Subnetmap> sn =
295 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
297 if (sn.isPresent()) {
298 builder = new SubnetmapBuilder(sn.get());
299 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
301 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
304 if (routerId != null) {
305 builder.setRouterId(routerId);
308 builder.setVpnId(vpnId);
310 builder.setInternetVpnId(internetvpnId);
312 subnetmap = builder.build();
313 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
314 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
316 } catch (ReadFailedException | TransactionCommitFailedException e) {
317 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
322 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
323 Uuid routerInterfacePortId, String fixedIp,
324 String routerIntfMacAddress, Uuid vpnId) {
325 Subnetmap subnetmap = null;
326 SubnetmapBuilder builder = null;
327 InstanceIdentifier<Subnetmap> id =
328 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
330 synchronized (subnetId.getValue().intern()) {
331 Optional<Subnetmap> sn =
332 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
334 if (sn.isPresent()) {
335 builder = new SubnetmapBuilder(sn.get());
336 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
337 subnetId.getValue());
339 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
340 subnetId.getValue());
343 builder.setRouterId(routerId);
344 builder.setRouterInterfacePortId(routerInterfacePortId);
345 builder.setRouterIntfMacAddress(routerIntfMacAddress);
346 builder.setRouterInterfaceFixedIp(fixedIp);
348 builder.setVpnId(vpnId);
350 subnetmap = builder.build();
351 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
352 subnetId.getValue());
353 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
355 } catch (ReadFailedException | TransactionCommitFailedException e) {
356 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
357 subnetId.getValue(), e);
361 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
362 Subnetmap subnetmap = null;
363 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
364 new SubnetmapKey(subnetId)).build();
365 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
367 synchronized (subnetId.getValue().intern()) {
368 Optional<Subnetmap> sn =
369 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
371 if (sn.isPresent()) {
372 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
373 if (null != portId) {
374 List<Uuid> portList = builder.getPortList();
375 if (null == portList) {
376 portList = new ArrayList<>();
378 portList.add(portId);
379 builder.setPortList(portList);
380 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
381 subnetId.getValue(), portId.getValue());
383 if (null != directPortId) {
384 List<Uuid> directPortList = builder.getDirectPortList();
385 if (null == directPortList) {
386 directPortList = new ArrayList<>();
388 directPortList.add(directPortId);
389 builder.setDirectPortList(directPortList);
390 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
391 directPortId.getValue());
393 subnetmap = builder.build();
394 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
397 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
398 + "cache ", subnetId.getValue(), portId.getValue());
399 unprocessedPortsMap.put(portId, subnetId);
402 } catch (ReadFailedException | TransactionCommitFailedException e) {
403 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
408 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId,
409 Uuid vpnId, Uuid portId) {
410 Subnetmap subnetmap = null;
411 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
412 .child(Subnetmap.class, new SubnetmapKey(subnetId))
415 synchronized (subnetId.getValue().intern()) {
416 Optional<Subnetmap> sn =
417 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
419 if (sn.isPresent()) {
420 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
421 if (routerId != null) {
422 builder.setRouterId(null);
424 if (networkId != null) {
425 builder.setNetworkId(null);
428 builder.setVpnId(null);
430 builder.setInternetVpnId(null);
431 if (portId != null && builder.getPortList() != null) {
432 List<Uuid> portList = builder.getPortList();
433 portList.remove(portId);
434 builder.setPortList(portList);
437 subnetmap = builder.build();
438 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
439 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
442 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
445 } catch (ReadFailedException | TransactionCommitFailedException e) {
446 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
451 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
452 Subnetmap subnetmap = null;
453 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
454 new SubnetmapKey(subnetId)).build();
456 synchronized (subnetId.getValue().intern()) {
457 Optional<Subnetmap> sn =
458 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
460 if (sn.isPresent()) {
461 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
462 if (null != portId && null != builder.getPortList()) {
463 List<Uuid> portList = builder.getPortList();
464 portList.remove(portId);
465 builder.setPortList(portList);
466 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
467 subnetId.getValue());
469 if (null != directPortId && null != builder.getDirectPortList()) {
470 List<Uuid> directPortList = builder.getDirectPortList();
471 directPortList.remove(directPortId);
472 builder.setDirectPortList(directPortList);
473 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
474 .getValue(), subnetId.getValue());
476 subnetmap = builder.build();
477 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
480 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
483 } catch (ReadFailedException | TransactionCommitFailedException e) {
484 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
485 subnetId.getValue(), e);
490 // TODO Clean up the exception handling
491 @SuppressWarnings("checkstyle:IllegalCatch")
492 protected void deleteSubnetMapNode(Uuid subnetId) {
493 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
494 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
495 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
497 synchronized (subnetId.getValue().intern()) {
498 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
499 subnetMapIdentifier);
501 } catch (TransactionCommitFailedException e) {
502 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
506 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
507 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
508 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
510 Optional<VpnInstance> vpnInstanceConfig =
511 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
513 if (!vpnInstanceConfig.isPresent()) {
514 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
517 VpnInstance vpnInstance = vpnInstanceConfig.get();
518 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
519 if (vpnInstance.getIpv4Family() != null) {
520 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
521 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
523 if (vpnInstance.getIpv6Family() != null) {
524 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
525 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
527 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
528 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
529 updateVpnInstanceBuilder.build());
530 } catch (ReadFailedException | TransactionCommitFailedException ex) {
531 LOG.warn("Error configuring feature ", ex);
535 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
536 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
537 String vpnName = vpnId.getValue();
538 VpnInstanceBuilder builder = null;
539 List<VpnTarget> vpnTargetList = new ArrayList<>();
540 boolean isLockAcquired = false;
541 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
542 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
544 Optional<VpnInstance> optionalVpn =
545 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
547 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
548 if (optionalVpn.isPresent()) {
549 builder = new VpnInstanceBuilder(optionalVpn.get());
550 LOG.debug("updating existing vpninstance node");
552 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
553 .setType(type).setL3vni(l3vni);
555 if (irt != null && !irt.isEmpty()) {
556 if (ert != null && !ert.isEmpty()) {
557 List<String> commonRT = new ArrayList<>(irt);
558 commonRT.retainAll(ert);
560 for (String common : commonRT) {
563 VpnTarget vpnTarget =
564 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
565 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
566 vpnTargetList.add(vpnTarget);
569 for (String importRT : irt) {
570 VpnTarget vpnTarget =
571 new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
572 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
573 vpnTargetList.add(vpnTarget);
577 if (ert != null && !ert.isEmpty()) {
578 for (String exportRT : ert) {
579 VpnTarget vpnTarget =
580 new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
581 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
582 vpnTargetList.add(vpnTarget);
586 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
588 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
589 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
591 if (rd != null && !rd.isEmpty()) {
592 ipv4vpnBuilder.setRouteDistinguisher(rd);
593 ipv6vpnBuilder.setRouteDistinguisher(rd);
596 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
597 builder.setIpv4Family(ipv4vpnBuilder.build());
599 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
600 builder.setIpv6Family(ipv6vpnBuilder.build());
602 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
603 builder.setIpv4Family(ipv4vpnBuilder.build());
605 VpnInstance newVpn = builder.build();
606 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
607 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
608 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
610 } catch (ReadFailedException | TransactionCommitFailedException e) {
611 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
613 if (isLockAcquired) {
614 vpnLock.unlock(vpnId);
619 private void deleteVpnMapsNode(Uuid vpnId) {
620 boolean isLockAcquired = false;
621 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
622 .child(VpnMap.class, new VpnMapKey(vpnId))
624 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
626 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
627 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
628 } catch (TransactionCommitFailedException e) {
629 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
631 if (isLockAcquired) {
632 vpnLock.unlock(vpnId);
637 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
638 VpnMapBuilder builder;
639 boolean isLockAcquired = false;
640 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
641 .child(VpnMap.class, new VpnMapKey(vpnId))
644 Optional<VpnMap> optionalVpnMap =
645 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
647 if (optionalVpnMap.isPresent()) {
648 builder = new VpnMapBuilder(optionalVpnMap.get());
650 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
654 builder.setName(name);
656 if (tenantId != null) {
657 builder.setTenantId(tenantId);
659 if (router != null) {
660 builder.setRouterId(router);
662 if (networks != null) {
663 List<Uuid> nwList = builder.getNetworkIds();
664 if (nwList == null) {
665 nwList = new ArrayList<>();
667 nwList.addAll(networks);
668 builder.setNetworkIds(nwList);
671 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
672 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
673 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
675 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
676 } catch (ReadFailedException | TransactionCommitFailedException e) {
677 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
679 if (isLockAcquired) {
680 vpnLock.unlock(vpnId);
685 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
686 boolean isLockAcquired = false;
687 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
688 .child(VpnMap.class, new VpnMapKey(vpnId))
690 Optional<VpnMap> optionalVpnMap;
693 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
695 } catch (ReadFailedException e) {
696 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
699 if (optionalVpnMap.isPresent()) {
700 VpnMap vpnMap = optionalVpnMap.get();
701 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
702 if (routerId != null) {
703 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
705 // remove entire node in case of internal VPN
706 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
707 LOG.debug("removing vpnMaps node: {} ", vpnId);
708 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
710 } catch (TransactionCommitFailedException e) {
711 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
713 if (isLockAcquired) {
714 vpnLock.unlock(vpnId);
719 vpnMapBuilder.setRouterId(null);
721 if (networkIds != null) {
722 List<Uuid> vpnNw = vpnMap.getNetworkIds();
723 vpnNw.removeAll(networkIds);
724 if (vpnNw.isEmpty()) {
725 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
726 vpnMapBuilder.setNetworkIds(null);
728 vpnMapBuilder.setNetworkIds(vpnNw);
733 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
734 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
735 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
736 vpnMapBuilder.build());
737 } catch (TransactionCommitFailedException e) {
738 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
740 if (isLockAcquired) {
741 vpnLock.unlock(vpnId);
745 LOG.error("VPN : {} not found", vpnId.getValue());
747 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
750 private void deleteVpnInstance(Uuid vpnId) {
751 boolean isLockAcquired = false;
752 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
753 .child(VpnInstance.class,
754 new VpnInstanceKey(vpnId.getValue()))
757 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
758 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
759 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
760 } catch (TransactionCommitFailedException e) {
761 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
763 if (isLockAcquired) {
764 vpnLock.unlock(vpnId);
769 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
770 WriteTransaction wrtConfigTxn, Subnetmap sn, VpnInterface vpnIface) {
771 List<Adjacency> adjList = new ArrayList<>();
772 if (vpnIface != null) {
773 adjList = vpnIface.getAugmentation(Adjacencies.class).getAdjacency();
775 String infName = port.getUuid().getValue();
776 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
777 for (FixedIps ip : port.getFixedIps()) {
778 String ipValue = String.valueOf(ip.getIpAddress().getValue());
779 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
780 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
783 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
784 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
786 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
787 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
788 //Create Neutron port adjacency if VPN presence is existing for subnet
789 Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
790 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
791 .setSubnetId(ip.getSubnetId()).build();
792 if (!adjList.contains(vmAdj)) {
796 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
797 if (snTemp != null && snTemp.getInternetVpnId() != null) {
798 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
799 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
801 if (routerId != null) {
802 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
803 if (rtr != null && rtr.getRoutes() != null) {
804 List<Routes> routeList = rtr.getRoutes();
805 // create extraroute Adjacence for each ipValue,
806 // because router can have IPv4 and IPv6 subnet ports, or can have
807 // more that one IPv4 subnet port or more than one IPv6 subnet port
808 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
809 if (!erAdjList.isEmpty()) {
810 adjList.addAll(erAdjList);
815 return new AdjacenciesBuilder().setAdjacency(adjList).build();
818 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port, WriteTransaction wrtConfigTxn) {
819 boolean isRouterInterface = false;
820 if (port.getDeviceOwner() != null) {
821 isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
823 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
824 String infName = port.getUuid().getValue();
825 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
826 writeVpnInterfaceToDs(vpnIds, infName, adjs, isRouterInterface, wrtConfigTxn);
829 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
830 Port port, Subnetmap sn, WriteTransaction wrtConfigTxn) {
831 String infName = port.getUuid().getValue();
832 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
833 Optional<VpnInterface> optionalVpnInterface = null;
834 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
835 vpnId, internetVpnId, infName);
837 optionalVpnInterface = SingleTransactionDataBroker
838 .syncReadOptional(dataBroker, LogicalDatastoreType
839 .CONFIGURATION, vpnIfIdentifier);
840 } catch (ReadFailedException e) {
841 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
844 if (!optionalVpnInterface.isPresent()) {
847 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
848 sn != null ? sn.getSubnetIp() : "null");
849 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().getAugmentation(Adjacencies.class).getAdjacency();
850 List<Adjacency> updatedAdjsList = new ArrayList<>();
851 boolean isIpFromAnotherSubnet = false;
852 for (Adjacency adj : vpnAdjsList) {
853 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
854 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
855 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
856 isIpFromAnotherSubnet = true;
858 updatedAdjsList.add(adj);
861 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
862 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
865 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
866 String.valueOf(adjString), wrtConfigTxn);
868 if (internetVpnId != null) {
869 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
870 String.valueOf(adjString), wrtConfigTxn);
873 if (port.getDeviceOwner()
874 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
875 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
876 if (rtr != null && rtr.getRoutes() != null) {
877 List<Routes> extraRoutesToRemove = new ArrayList<>();
878 for (Routes rt: rtr.getRoutes()) {
879 if (rt.getNexthop().toString().equals(adjString)) {
880 extraRoutesToRemove.add(rt);
884 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
885 extraRoutesToRemove, vpnId);
886 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
888 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
893 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
895 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
897 if (internetVpnId != null) {
898 updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn);
900 if (!isIpFromAnotherSubnet) {
901 // no more subnetworks for neutron port
902 if (sn != null && sn.getRouterId() != null) {
903 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
905 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
911 // TODO Clean up the exception handling
912 @SuppressWarnings("checkstyle:IllegalCatch")
913 protected void deleteVpnInterface(String infName, @Nullable String vpnId, WriteTransaction wrtConfigTxn) {
914 if (wrtConfigTxn == null) {
915 ListenableFutures.addErrorLogging(
916 txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> deleteVpnInterface(infName, vpnId, tx)),
917 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
921 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
922 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
923 Optional<VpnInterface> optionalVpnInterface;
925 optionalVpnInterface =
926 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
928 } catch (ReadFailedException ex) {
929 LOG.error("Error during deletion of vpninterface {}", infName, ex);
932 if (!optionalVpnInterface.isPresent()) {
933 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
937 VpnInterface vpnInterface = optionalVpnInterface.get();
938 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
940 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
941 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
942 if (!vpnList.isEmpty()) {
943 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
944 + "List not empty", infName);
947 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
948 .setVpnInstanceNames(vpnList);
949 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
953 LOG.debug("Deleting vpn interface {}", infName);
954 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
957 protected void removeVpnFromVpnInterface(Uuid vpnId, Port port,
958 WriteTransaction writeConfigTxn, Subnetmap sm) {
959 if (vpnId == null || port == null) {
962 String infName = port.getUuid().getValue();
963 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
965 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
966 .syncReadOptional(dataBroker, LogicalDatastoreType
967 .CONFIGURATION, vpnIfIdentifier);
968 if (optionalVpnInterface.isPresent()) {
969 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
971 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
972 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
974 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
975 .setVpnInstanceNames(listVpn);
976 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
977 LOG.debug("Updating vpn interface {}", infName);
978 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
979 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
980 while (adjacencyIter.hasNext()) {
981 Adjacency adjacency = adjacencyIter.next();
982 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
985 String mipToQuery = adjacency.getIpAddress().split("/")[0];
986 InstanceIdentifier<LearntVpnVipToPort> id =
987 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
988 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
989 SingleTransactionDataBroker.syncReadOptional(dataBroker,
990 LogicalDatastoreType.OPERATIONAL, id);
991 if (optionalVpnVipToPort.isPresent()) {
992 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
994 if (listVpn == null || listVpn.isEmpty()) {
995 adjacencyIter.remove();
997 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
998 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
999 mipToQuery, infName, vpnId.getValue());
1002 List<FixedIps> ips = port.getFixedIps();
1003 for (FixedIps ip : ips) {
1004 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1005 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1006 ipValue, writeConfigTxn);
1008 if (listVpn == null || listVpn.isEmpty()) {
1009 if (sm != null && sm.getRouterId() != null) {
1010 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1012 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1014 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1018 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1020 } catch (ReadFailedException ex) {
1021 LOG.error("Update of vpninterface {} failed", infName, ex);
1025 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
1026 boolean isSubnetIp, WriteTransaction writeConfigTxn) {
1027 if (vpnId == null || port == null) {
1030 boolean isLockAcquired = false;
1031 String infName = port.getUuid().getValue();
1032 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1035 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1036 Optional<VpnInterface> optionalVpnInterface =
1037 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1039 if (optionalVpnInterface.isPresent()) {
1040 VpnInstanceNames vpnInstance = VpnHelper
1041 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1042 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1043 .get().getVpnInstanceNames());
1044 if (oldVpnId != null
1045 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1046 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1048 if (vpnId.getValue() != null
1049 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1050 listVpn.add(vpnInstance);
1052 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1053 .setVpnInstanceNames(listVpn);
1054 LOG.debug("Updating vpn interface {}", infName);
1055 if (!isBeingAssociated) {
1056 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
1057 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1058 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1059 while (adjacencyIter.hasNext()) {
1060 Adjacency adjacency = adjacencyIter.next();
1061 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1062 InstanceIdentifier<LearntVpnVipToPort> id =
1063 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1064 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1065 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1066 LogicalDatastoreType.OPERATIONAL, id);
1067 if (optionalVpnVipToPort.isPresent()) {
1068 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1069 + "from VPN {}", infName, vpnId, oldVpnId);
1070 adjacencyIter.remove();
1071 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1073 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1074 mipToQuery, infName, vpnId.getValue());
1077 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1078 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1080 List<FixedIps> ips = port.getFixedIps();
1081 for (FixedIps ip : ips) {
1082 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1083 if (oldVpnId != null) {
1084 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1085 ipValue, writeConfigTxn);
1087 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1088 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1090 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1093 LOG.error("VPN Interface {} not found", infName);
1095 } catch (ReadFailedException ex) {
1096 LOG.error("Updation of vpninterface {} failed", infName, ex);
1098 if (isLockAcquired) {
1099 interfaceLock.unlock(infName);
1104 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
1105 List<String> ert, Uuid router, List<Uuid> networks) {
1107 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1109 // Update VPN Instance node
1110 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1112 // Update local vpn-subnet DS
1113 updateVpnMaps(vpn, name, router, tenant, networks);
1115 if (router != null) {
1116 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1117 if (existingVpn != null) {
1118 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1119 // if before reboot, router was already associated to VPN, should not proceed associating router to
1120 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1121 // preserved upon reboot.
1122 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1123 // RouterInterfacesMap via #createVPNInterface call.
1124 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1125 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1128 associateRouterToInternalVpn(vpn, router);
1133 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1134 * specified Neutron Networks and Routers.
1136 * @param vpn Uuid of the VPN tp be created
1137 * @param name Representative name of the new VPN
1138 * @param tenant Uuid of the Tenant under which the VPN is going to be created
1139 * @param rd Route-distinguisher for the VPN
1140 * @param irt A list of Import Route Targets
1141 * @param ert A list of Export Route Targets
1142 * @param router neutron router Id to associate with created VPN
1143 * @param networks UUID of the neutron network the VPN may be associated to
1144 * @param type Type of the VPN Instance
1145 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1146 * @throws Exception if association of L3VPN failed
1148 public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
1149 Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni)
1152 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1154 if (router != null) {
1155 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1156 ipVersChoices = ipVersChoices.addVersion(vers);
1158 updateVpnInstanceNode(vpn, rd, irt, ert, type, l3vni, ipVersChoices);
1160 // Please note that router and networks will be filled into VPNMaps
1161 // by subsequent calls here to associateRouterToVpn and
1162 // associateNetworksToVpn
1163 updateVpnMaps(vpn, name, null, tenant, null);
1165 if (router != null) {
1166 associateRouterToVpn(vpn, router);
1168 if (networks != null) {
1169 List<String> failStrings = associateNetworksToVpn(vpn, networks);
1170 if (!failStrings.isEmpty()) {
1171 LOG.error("VPN {} association to networks failed for networks: {}. ",
1172 vpn.getValue(), failStrings.toString());
1173 throw new Exception(failStrings.toString());
1179 * It handles the invocations to the createVPN RPC method.
1182 // TODO Clean up the exception handling
1183 @SuppressWarnings("checkstyle:IllegalCatch")
1184 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1186 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1187 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1188 List<RpcError> errorList = new ArrayList<>();
1189 int failurecount = 0;
1190 int warningcount = 0;
1192 List<L3vpn> vpns = input.getL3vpn();
1193 for (L3vpn vpn : vpns) {
1194 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1195 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1196 formatAndLog(LOG::warn,
1197 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1198 vpn.getId().getValue())));
1202 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1203 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1204 formatAndLog(LOG::warn,
1205 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1206 vpn.getId().getValue())));
1210 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1212 if (vpn.getL3vni() != null) {
1213 l3vni = vpn.getL3vni();
1216 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1217 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1218 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1219 formatAndLog(LOG::warn,
1220 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1221 + "is already configured",
1222 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1226 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1227 if (operationalVpn.isPresent()) {
1228 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1229 formatAndLog(LOG::error,
1230 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1231 + "is still available. Please retry creation of a new vpn with the same RD"
1232 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1233 vpn.getRouteDistinguisher().get(0))));
1237 if (vpn.getRouterId() != null) {
1238 if (neutronvpnUtils.getNeutronRouter(vpn.getRouterId()) == null) {
1239 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1240 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router not found {}",
1241 vpn.getId().getValue(), vpn.getRouterId().getValue())));
1245 Uuid vpnId = neutronvpnUtils.getVpnForRouter(vpn.getRouterId(), true);
1246 if (vpnId != null) {
1247 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1248 formatAndLog(LOG::warn,
1249 "Creation of L3VPN failed for VPN {} due to router {} already associated to "
1250 + "another VPN {}", vpn.getId().getValue(), vpn.getRouterId().getValue(),
1251 vpnId.getValue())));
1256 if (vpn.getNetworkIds() != null) {
1257 int initialWarningCount = warningcount;
1258 for (Uuid nw : vpn.getNetworkIds()) {
1259 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1260 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1261 if (network == null) {
1262 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1263 formatAndLog(LOG::warn,
1264 "Creation of L3VPN failed for VPN {} due to network not found {}",
1265 vpn.getId().getValue(), nw.getValue())));
1267 } else if (vpnId != null) {
1268 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1269 formatAndLog(LOG::warn,
1270 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1271 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1272 vpnId.getValue())));
1276 if (warningcount != initialWarningCount) {
1281 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1282 vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
1283 vpnInstanceType, l3vni);
1284 } catch (Exception ex) {
1285 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1286 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1291 // if at least one succeeds; result is success
1292 // if none succeeds; result is failure
1293 if (failurecount + warningcount == vpns.size()) {
1294 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1296 List<String> errorResponseList = new ArrayList<>();
1297 if (!errorList.isEmpty()) {
1298 for (RpcError rpcError : errorList) {
1299 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1300 + ", ErrorMessage: " + rpcError.getMessage());
1303 errorResponseList.add("Operation successful with no errors");
1305 opBuilder.setResponse(errorResponseList);
1306 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1312 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1315 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1317 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1318 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1319 Uuid inputVpnId = input.getId();
1320 List<VpnInstance> vpns = new ArrayList<>();
1321 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1324 if (inputVpnId == null) {
1326 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1328 Optional<VpnInstances> optionalVpns =
1329 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1331 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1332 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1333 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1334 // from getL3VPN output
1335 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1341 opBuilder.setL3vpnInstances(l3vpnList);
1342 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1346 String name = inputVpnId.getValue();
1347 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1348 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1349 // read VpnInstance Info
1350 Optional<VpnInstance> optionalVpn =
1351 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1353 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1355 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1356 vpns.add(optionalVpn.get());
1359 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1360 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1364 for (VpnInstance vpnInstance : vpns) {
1365 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1366 // create VpnMaps id
1367 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1368 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1369 List<String> ertList = new ArrayList<>();
1370 List<String> irtList = new ArrayList<>();
1372 if (vpnInstance.getIpv4Family().getVpnTargets() != null) {
1373 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1374 for (VpnTarget vpnTarget : vpnTargetList) {
1375 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1376 ertList.add(vpnTarget.getVrfRTValue());
1378 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1379 irtList.add(vpnTarget.getVrfRTValue());
1381 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1382 ertList.add(vpnTarget.getVrfRTValue());
1383 irtList.add(vpnTarget.getVrfRTValue());
1388 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1390 if (vpnInstance.getL3vni() != null) {
1391 l3vpn.setL3vni(vpnInstance.getL3vni());
1393 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1394 .class, new VpnMapKey(vpnId)).build();
1395 Optional<VpnMap> optionalVpnMap =
1396 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1398 if (optionalVpnMap.isPresent()) {
1399 VpnMap vpnMap = optionalVpnMap.get();
1400 l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1401 .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1403 l3vpnList.add(l3vpn.build());
1406 opBuilder.setL3vpnInstances(l3vpnList);
1407 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1409 } catch (ReadFailedException ex) {
1410 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1411 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1417 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1420 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1422 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1423 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1424 List<RpcError> errorList = new ArrayList<>();
1426 int failurecount = 0;
1427 int warningcount = 0;
1428 List<Uuid> vpns = input.getId();
1429 for (Uuid vpn : vpns) {
1433 InstanceIdentifier<VpnInstance> vpnIdentifier =
1434 InstanceIdentifier.builder(VpnInstances.class)
1435 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1436 Optional<VpnInstance> optionalVpn =
1437 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1439 if (optionalVpn.isPresent()) {
1442 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1443 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1446 } catch (ReadFailedException ex) {
1447 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1448 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1453 // if at least one succeeds; result is success
1454 // if none succeeds; result is failure
1455 if (failurecount + warningcount == vpns.size()) {
1456 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1458 List<String> errorResponseList = new ArrayList<>();
1459 if (!errorList.isEmpty()) {
1460 for (RpcError rpcError : errorList) {
1461 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1462 + ", ErrorMessage: " + rpcError.getMessage());
1465 errorResponseList.add("Operation successful with no errors");
1467 opBuilder.setResponse(errorResponseList);
1468 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1473 public void createVpnInstanceForSubnet(Uuid subnetId) {
1474 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1475 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1478 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1479 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1480 removeVpn(subnetId);
1483 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1484 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1485 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1486 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1488 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1489 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1492 if (vpnId != null) {
1493 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1494 if (vpnMap == null) {
1495 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1496 + " cannot add subnet {} to VPN", vpnId.getValue(),
1500 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1501 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1502 if (isVpnOfTypeL2(vpnInstance)) {
1503 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1504 NeutronEvpnUtils.Operation.ADD);
1507 if (internetVpnId != null) {
1508 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1509 if (vpnMap == null) {
1510 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1511 + "subnet {} to VPN", internetVpnId.getValue(),
1516 final Uuid internetId = internetVpnId;
1517 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1518 List<Uuid> portList = sn.getPortList();
1519 if (portList != null) {
1520 for (final Uuid portId : portList) {
1521 String vpnInfName = portId.getValue();
1522 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1523 Port port = neutronvpnUtils.getNeutronPort(portId);
1525 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1526 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1529 final Boolean isRouterInterface = port.getDeviceOwner()
1530 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1531 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1532 txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1533 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1535 if (vpnIface == null) {
1536 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1537 Set<Uuid> listVpn = new HashSet<>();
1538 if (vpnId != null) {
1541 if (internetId != null) {
1542 listVpn.add(internetId);
1544 writeVpnInterfaceToDs(listVpn,
1545 vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
1546 if (sn.getRouterId() != null) {
1547 addToNeutronRouterInterfacesMap(sn.getRouterId(),portId.getValue());
1550 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1551 if (vpnId != null) {
1552 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1554 if (internetId != null) {
1555 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1564 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) {
1565 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1566 "removeSubnetFromVpn: at least one VPN must be not null");
1567 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1568 vpnId, internetVpnId);
1569 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1571 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1574 VpnMap vpnMap = null;
1575 VpnInstance vpnInstance = null;
1576 if (vpnId != null) {
1577 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1578 if (vpnMap == null) {
1579 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1580 vpnId.getValue(), subnet.getValue());
1583 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1585 if (internetVpnId == null) {
1586 internetVpnId = sn.getInternetVpnId();
1588 if (internetVpnId != null) {
1589 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1590 if (vpnMap == null) {
1591 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1592 + " from Internet VPN",
1593 internetVpnId.getValue(), subnet.getValue());
1597 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1598 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1599 NeutronEvpnUtils.Operation.DELETE);
1601 boolean subnetVpnAssociation = false;
1602 if (vpnId != null && sn.getVpnId() != null
1603 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1604 subnetVpnAssociation = true;
1605 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1606 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1607 subnetVpnAssociation = true;
1609 if (subnetVpnAssociation == false) {
1610 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1611 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1614 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1615 List<Uuid> portList = sn.getPortList();
1616 final Uuid internetId = internetVpnId;
1617 if (portList != null) {
1618 for (final Uuid portId : portList) {
1619 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1620 final Port port = neutronvpnUtils.getNeutronPort(portId);
1621 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1622 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1624 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1627 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1628 + "port is absent in Neutron config DS", portId.getValue(),
1634 //update subnet-vpn association
1635 removeFromSubnetNode(subnet, null, null, vpnId, null);
1638 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1639 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1640 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1642 Uuid internalVpnId = sm.getVpnId();
1643 if (internalVpnId == null) {
1644 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1645 sm.getId().getValue());
1648 if (isBeingAssociated) {
1649 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1651 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1654 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1655 txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1656 if (isBeingAssociated) {
1657 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1658 true, true, wrtConfigTxn);
1660 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1666 // Check for ports on this subnet and update association of
1667 // corresponding vpn-interfaces to internet vpn
1668 List<Uuid> portList = sm.getPortList();
1669 if (portList != null) {
1670 for (Uuid port : portList) {
1671 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1672 port.getValue(), isBeingAssociated);
1673 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1674 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1675 if (isBeingAssociated) {
1676 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1679 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1686 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1687 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1688 oldVpnId.getValue(), newVpnId.getValue());
1689 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1690 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1691 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1692 Uuid vpnExtUuid = netIsExternal ? null
1693 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1694 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1696 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1700 //Update Router Interface first synchronously.
1701 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1702 ListenableFuture<Void> future =
1703 txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> updateVpnInterface(newVpnId, oldVpnId,
1704 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1705 isBeingAssociated, true, tx));
1706 Futures.addCallback(future, new FutureCallback<Void>() {
1708 public void onSuccess(Void result) {
1709 // Check for ports on this subnet and update association of
1710 // corresponding vpn-interfaces to external vpn
1711 List<Uuid> portList = sn.getPortList();
1712 if (portList != null) {
1713 for (Uuid port : portList) {
1714 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1715 port.getValue(), isBeingAssociated);
1716 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1717 txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1718 tx -> updateVpnInterface(newVpnId, oldVpnId,
1719 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1726 public void onFailure(Throwable throwable) {
1728 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1730 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1732 }, MoreExecutors.directExecutor());
1737 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1738 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1739 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1742 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1743 synchronized (routerId.getValue().intern()) {
1744 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1746 Optional<RouterInterfaces> optRouterInterfaces =
1747 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1748 routerInterfacesId);
1749 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1750 .setInterfaceId(interfaceName).build();
1751 if (optRouterInterfaces.isPresent()) {
1752 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1753 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1756 // TODO Shouldn't we be doing something with builder and interfaces?
1757 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1758 // List<Interfaces> interfaces = new ArrayList<>();
1759 // interfaces.add(routerInterface);
1761 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1762 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1765 } catch (ReadFailedException | TransactionCommitFailedException e) {
1766 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1771 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1772 synchronized (routerId.getValue().intern()) {
1773 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1775 Optional<RouterInterfaces> optRouterInterfaces =
1776 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1777 routerInterfacesId);
1778 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1779 .setInterfaceId(interfaceName).build();
1780 if (optRouterInterfaces.isPresent()) {
1781 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1782 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1783 if (interfaces != null && interfaces.remove(routerInterface)) {
1784 if (interfaces.isEmpty()) {
1785 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1786 routerInterfacesId);
1788 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1789 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1793 } catch (ReadFailedException | TransactionCommitFailedException e) {
1794 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1800 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1801 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1802 * route will be ignored.
1804 * @param vpnName the VPN identifier
1805 * @param interVpnLinkRoutes The list of static routes
1806 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1808 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1809 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1810 for (Routes route : interVpnLinkRoutes) {
1811 String nexthop = String.valueOf(route.getNexthop().getValue());
1812 String destination = String.valueOf(route.getDestination().getValue());
1813 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1814 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1815 AddStaticRouteInput rpcInput =
1816 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1817 .setVpnInstanceName(vpnName.getValue())
1819 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1820 RpcResult<AddStaticRouteOutput> rpcResult;
1822 rpcResult = labelOuputFtr.get();
1823 if (rpcResult.isSuccessful()) {
1824 LOG.debug("Label generated for destination {} is: {}",
1825 destination, rpcResult.getResult().getLabel());
1827 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1828 destination, nexthop, rpcResult.getErrors());
1830 } catch (InterruptedException | ExecutionException e) {
1831 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1832 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1835 // Any other case is a fault.
1836 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1837 String.valueOf(route.getDestination().getValue()), nexthop);
1844 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1845 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1847 * @param vpnName the VPN identifier
1848 * @param interVpnLinkRoutes The list of static routes
1849 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1851 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1852 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1853 for (Routes route : interVpnLinkRoutes) {
1854 String nexthop = String.valueOf(route.getNexthop().getValue());
1855 String destination = String.valueOf(route.getDestination().getValue());
1856 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1857 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1858 RemoveStaticRouteInput rpcInput =
1859 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1860 .setVpnInstanceName(vpnName.getValue())
1863 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1864 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1866 // Any other case is a fault.
1867 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1868 String.valueOf(route.getDestination().getValue()), nexthop);
1875 * Returns true if the specified nexthop is the other endpoint in an
1876 * InterVpnLink, regarding one of the VPN's point of view.
1878 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1880 interVpnLink != null
1881 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1882 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1883 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1884 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1888 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
1889 List<Adjacency> adjList = new ArrayList<>();
1890 Map<String, List<String>> adjMap = new HashMap<>();
1891 for (Routes route : routeList) {
1892 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1893 LOG.error("Incorrect input received for extra route. {}", route);
1895 String nextHop = String.valueOf(route.getNexthop().getValue());
1896 String destination = String.valueOf(route.getDestination().getValue());
1897 if (!nextHop.equals(fixedIp)) {
1898 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1901 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
1903 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1904 if (!hops.contains(nextHop)) {
1910 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
1911 final String destination = entry.getKey();
1912 final List<String> ipList = entry.getValue();
1913 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1914 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
1915 .setKey(new AdjacencyKey(destination)).build();
1921 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1922 checkAlarmExtraRoutes(vpnId, routeList);
1924 for (Routes route : routeList) {
1925 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1926 LOG.error("Incorrect input received for extra route. {}", route);
1928 String nextHop = String.valueOf(route.getNexthop().getValue());
1929 String destination = String.valueOf(route.getDestination().getValue());
1930 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
1932 if (infName != null) {
1933 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
1934 destination, vpnId.getValue(), nextHop, infName);
1935 boolean isLockAcquired = false;
1937 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
1938 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1939 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
1940 .child(Adjacency.class, new AdjacencyKey(destination));
1941 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1942 LogicalDatastoreType.CONFIGURATION, path);
1943 if (existingAdjacency.isPresent()
1944 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1945 LOG.error("The route with destination {} nextHop {} is already present as"
1946 + " a primary adjacency for interface {}. Skipping adjacency addition.",
1947 destination, nextHop, infName);
1950 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1951 .setNextHopIpList(Collections.singletonList(nextHop)).setKey(new AdjacencyKey(destination))
1952 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
1953 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1954 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1956 } catch (TransactionCommitFailedException e) {
1957 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
1958 destination, nextHop, e);
1959 } catch (ReadFailedException e) {
1960 LOG.error("Exception on reading data-store ", e);
1962 if (isLockAcquired) {
1963 interfaceLock.unlock(infName);
1967 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1968 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1975 * This method setup or down an alarm about extra route fault.
1976 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
1977 * available RDs, then an alarm and an error is generated.<br>
1978 * <b>Be careful</b> the routeList could be changed.
1980 * @param vpnId the vpnId of vpn to control.
1981 * @param routeList the list of router to check, it could be modified.
1983 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
1984 if (!neutronvpnAlarm.isAlarmEnabled()) {
1985 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
1988 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
1989 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
1990 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
1994 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
1995 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
1996 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2000 List<Routes> routesError = new ArrayList();
2001 for (Routes route : routeList) {
2002 // count the number of nexthops for each same route.getDestingation().getValue()
2003 String destination = String.valueOf(route.getDestination().getValue());
2004 String nextHop = String.valueOf(route.getNexthop().getValue());
2005 List<String> nextHopList = new ArrayList();
2006 nextHopList.add(nextHop);
2008 for (Routes routeTmp : routeList) {
2009 String routeDest = String.valueOf(routeTmp.getDestination().getValue());
2010 if (!destination.equals(routeDest)) {
2013 String routeNextH = String.valueOf(routeTmp.getNexthop().getValue());
2014 if (nextHop.equals(routeNextH)) {
2018 nextHopList.add(new String(routeTmp.getNexthop().getValue()));
2020 final List<String> rdList = new ArrayList<>();
2021 if (vpnInstance.getIpv4Family() != null
2022 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2023 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2029 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2030 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2031 if (rd != null && !rdList.contains(rd)) {
2036 // 1. VPN Instance Name
2037 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2040 Uuid routerUuid = neutronvpnUtils.getRouterforVpn(vpnId);
2041 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2042 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2044 // 3. List of RDs associated with the VPN
2045 detailsAlarm.append(" List of RDs associated with the VPN: ");
2046 for (String s : rdList) {
2047 detailsAlarm.append(s);
2048 detailsAlarm.append(", ");
2051 // 4. Prefix in question
2052 detailsAlarm.append(" for prefix: ");
2053 detailsAlarm.append(route.getDestination().getValue());
2055 // 5. List of NHs for the prefix
2056 detailsAlarm.append(" for nextHops: ");
2057 for (String s : nextHopList) {
2058 detailsAlarm.append(s);
2059 detailsAlarm.append(", ");
2062 if (rdList.size() < nbNextHops) {
2063 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2064 LOG.error("there are too many next hops for prefixe in vpn {}", vpnId);
2065 routesError.add(route);
2067 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2070 //in routesError there are a few route raised in alarm, so they have not to be used
2071 routeList.removeAll(routesError);
2074 // TODO Clean up the exception handling
2075 @SuppressWarnings("checkstyle:IllegalCatch")
2076 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2077 for (Routes route : routeList) {
2078 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2079 boolean isLockAcquired = false;
2080 String nextHop = String.valueOf(route.getNexthop().getValue());
2081 String destination = String.valueOf(route.getDestination().getValue());
2082 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2084 if (infName == null) {
2085 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2086 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2087 // Proceed to remove the next extra-route
2090 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2091 destination, vpnId.getValue(), nextHop, infName);
2093 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2094 InstanceIdentifier.builder(VpnInterfaces.class)
2095 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2096 .augmentation(Adjacencies.class)
2097 .child(Adjacency.class, new AdjacencyKey(destination))
2101 // Looking for existing prefix in MDSAL database
2102 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2103 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2104 boolean updateNextHops = false;
2105 List<String> nextHopList = new ArrayList<>();
2106 if (adjacency.isPresent()) {
2107 List<String> nhListRead = adjacency.get().getNextHopIpList();
2108 if (nhListRead.size() > 1) { // ECMP case
2109 for (String nextHopRead : nhListRead) {
2110 if (nextHopRead.equals(nextHop)) {
2111 updateNextHops = true;
2113 nextHopList.add(nextHopRead);
2119 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2120 if (updateNextHops) {
2121 // An update must be done, not including the current next hop
2122 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2123 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2124 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2125 .setNextHopIpList(nextHopList)
2126 .setKey(new AdjacencyKey(destination))
2128 Adjacencies erAdjs =
2129 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2130 VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2131 .addAugmentation(Adjacencies.class, erAdjs).build();
2132 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2133 vpnIfIdentifier, vpnIf);
2135 // Remove the whole route
2136 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2137 adjacencyIdentifier);
2138 LOG.trace("extra route {} deleted successfully", route);
2140 } catch (TransactionCommitFailedException | ReadFailedException e) {
2141 LOG.error("exception in deleting extra route with destination {} for interface {}",
2142 destination, infName, e);
2144 if (isLockAcquired) {
2145 interfaceLock.unlock(infName);
2149 LOG.error("Incorrect input received for extra route: {}", route);
2154 public void removeVpn(Uuid id) {
2156 VpnMap vpnMap = neutronvpnUtils.getVpnMap(id);
2157 Uuid router = vpnMap != null ? vpnMap.getRouterId() : null;
2158 // dissociate router
2159 if (router != null) {
2160 dissociateRouterFromVpn(id, router);
2162 // dissociate networks
2163 if (!id.equals(router) && vpnMap.getNetworkIds() != null) {
2164 dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
2166 // remove entire vpnMaps node
2167 deleteVpnMapsNode(id);
2169 // remove vpn-instance
2170 deleteVpnInstance(id);
2173 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2174 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2177 // TODO Clean up the exception handling
2178 @SuppressWarnings("checkstyle:IllegalCatch")
2179 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2180 updateVpnMaps(vpnId, null, routerId, null, null);
2181 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2182 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2183 for (Uuid subnetId : routerSubnets) {
2184 Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
2185 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) {
2186 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2187 NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
2192 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2193 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2195 } catch (Exception e) {
2196 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2197 .getValue(), vpnId.getValue(), e);
2201 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2202 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2203 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2204 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2205 for (Uuid subnet : routerSubnets) {
2206 IpVersionChoice version = NeutronvpnUtils
2207 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2208 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2209 addSubnetToVpn(vpnId, subnet, null);
2211 addSubnetToVpn(vpnId, subnet, internetVpnId);
2216 // TODO Clean up the exception handling
2217 @SuppressWarnings("checkstyle:IllegalCatch")
2218 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2220 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2221 boolean vpnInstanceIpVersionsRemoved = false;
2222 IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
2223 for (Uuid subnetId : routerSubnets) {
2224 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
2225 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
2226 vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
2227 .getIpVersionFromString(sn.getSubnetIp()));
2228 vpnInstanceIpVersionsRemoved = true;
2230 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2231 updateVpnForSubnet(vpnId, routerId, subnetId, false);
2234 if (vpnInstanceIpVersionsRemoved) {
2235 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false);
2237 clearFromVpnMaps(vpnId, routerId, null);
2239 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2240 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2242 } catch (Exception e) {
2243 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2244 .getValue(), vpnId.getValue(), e);
2249 * Parses and associates networks list with given VPN.
2251 * @param vpnId Uuid of given VPN.
2252 * @param networks List list of network Ids (Uuid), which will be associated.
2253 * @return list of formatted strings with detailed error messages.
2256 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networks) {
2257 List<String> failedNwList = new ArrayList<>();
2258 HashSet<Uuid> passedNwList = new HashSet<>();
2259 if (networks.isEmpty()) {
2260 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2261 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2263 return failedNwList;
2265 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2266 if (vpnInstance == null) {
2267 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2268 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2269 + "in ConfigDS", vpnId.getValue()));
2270 return failedNwList;
2273 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2274 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2276 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2277 + "associated with", vpnId.getValue()));
2278 return failedNwList;
2280 for (Uuid nw : networks) {
2281 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2282 if (network == null) {
2283 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2284 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2288 NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
2289 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2290 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2291 nw.getValue(), vpnId.getValue());
2292 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2293 nw.getValue(), vpnId.getValue()));
2296 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2297 if (networkVpnId != null) {
2298 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2299 nw.getValue(), networkVpnId.getValue());
2300 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2301 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2304 if (neutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2305 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2306 nw.getValue(), vpnId.getValue());
2307 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2308 nw.getValue(), vpnId.getValue()));
2311 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2312 if (networkSubnets == null) {
2313 passedNwList.add(nw);
2316 for (Uuid subnet : networkSubnets) {
2317 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnet);
2318 if (subnetVpnId != null) {
2319 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {} as it is already "
2320 + "associated", subnet.getValue(), subnetVpnId.getValue());
2321 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s as it is already "
2322 + "associated", subnet.getValue(), vpnId.getValue()));
2325 Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
2326 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sm, vpnId)) {
2327 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2328 NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()), true);
2330 if (!neutronvpnUtils.getIsExternal(network)) {
2331 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnet.getValue(),
2333 addSubnetToVpn(vpnId, subnet, null);
2336 passedNwList.add(nw);
2338 } catch (ReadFailedException e) {
2339 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2341 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2344 LOG.info("associateNetworksToVpn: update VPN {} with networks list: {}", vpnId.getValue(),
2345 passedNwList.toString());
2346 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2347 return failedNwList;
2350 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2351 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2352 if (vpnOpDataEntry == null) {
2353 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2356 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2359 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2360 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2361 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2363 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2364 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2366 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2369 updateVpnInternetForSubnet(sm, vpnId, true);
2370 if (!vpnOpDataEntry.isIpv6Configured()
2371 && NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6) {
2372 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2373 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true);
2380 * Parses and disassociates networks list from given VPN.
2382 * @param vpnId Uuid of given VPN.
2383 * @param networks List list of network Ids (Uuid), which will be disassociated.
2384 * @return list of formatted strings with detailed error messages.
2387 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networks) {
2388 List<String> failedNwList = new ArrayList<>();
2389 HashSet<Uuid> passedNwList = new HashSet<>();
2390 if (networks.isEmpty()) {
2391 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2392 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2394 return failedNwList;
2396 for (Uuid nw : networks) {
2397 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2398 if (network == null) {
2399 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2400 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2404 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2405 if (networkVpnId == null) {
2406 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2407 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2411 if (!vpnId.equals(networkVpnId)) {
2412 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2413 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2414 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2415 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2419 if (neutronvpnUtils.getIsExternal(network)) {
2420 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2421 passedNwList.add(nw);
2424 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2425 nw.getValue(), vpnId.getValue());
2426 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2431 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2432 if (networkSubnets == null) {
2433 passedNwList.add(nw);
2436 for (Uuid subnet : networkSubnets) {
2437 Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
2438 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sm, vpnId)) {
2439 IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
2440 IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2441 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2442 ipVersionsToRemove.addVersion(ipVersion), false);
2444 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2446 removeSubnetFromVpn(vpnId, subnet, null);
2447 passedNwList.add(nw);
2450 LOG.info("dissociateNetworksFromVpn: Withdraw networks list {} from VPN {}", networks.toString(),
2452 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2453 return failedNwList;
2456 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2457 if (!removeExternalNetworkFromVpn(extNet)) {
2460 // check, if there is another Provider Networks associated with given VPN
2461 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2462 if (vpnNets != null) {
2463 for (Uuid netId : vpnNets) {
2464 if (neutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2465 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2466 + "{}", vpnId.getValue(), netId.getValue());
2471 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2472 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2473 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2474 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2475 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2477 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2480 updateVpnInternetForSubnet(sm, vpnId, false);
2482 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2483 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue());
2484 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false);
2489 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2492 // TODO Clean up the exception handling
2493 @SuppressWarnings("checkstyle:IllegalCatch")
2494 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2496 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2497 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2498 LOG.debug("associateNetworks {}", input);
2499 StringBuilder returnMsg = new StringBuilder();
2500 Uuid vpnId = input.getVpnId();
2503 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2504 List<Uuid> netIds = input.getNetworkId();
2505 if (netIds != null && !netIds.isEmpty()) {
2506 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2507 if (!failed.isEmpty()) {
2508 returnMsg.append(failed);
2512 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2514 if (returnMsg.length() != 0) {
2515 opBuilder.setResponse(
2516 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2517 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2518 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2520 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2522 } catch (Exception ex) {
2523 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2524 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2525 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2527 LOG.debug("associateNetworks returns..");
2532 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2535 // TODO Clean up the exception handling
2536 @SuppressWarnings("checkstyle:IllegalCatch")
2537 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2539 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2540 LOG.debug("associateRouter {}", input);
2541 StringBuilder returnMsg = new StringBuilder();
2542 Uuid vpnId = input.getVpnId();
2543 Uuid routerId = input.getRouterId();
2545 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2546 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
2547 if (vpnMap != null) {
2549 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2550 if (vpnMap.getRouterId() != null) {
2551 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2552 .append(vpnMap.getRouterId().getValue());
2553 } else if (extVpnId != null) {
2554 returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
2555 + "another VPN ").append(extVpnId.getValue());
2557 associateRouterToVpn(vpnId, routerId);
2560 returnMsg.append("router not found : ").append(routerId.getValue());
2563 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2565 if (returnMsg.length() != 0) {
2566 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2567 "invalid-value", formatAndLog(LOG::error,
2568 "associate router to vpn {} failed due to {}", routerId.getValue(),returnMsg)).build());
2570 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2572 } catch (Exception ex) {
2573 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2574 formatAndLog(LOG::error, "associate router {} to vpn {} failed due to {}", routerId.getValue(),
2575 vpnId.getValue(), ex.getMessage(), ex)).build());
2577 LOG.debug("associateRouter returns..");
2581 /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2584 // TODO Clean up the exception handling
2585 @SuppressWarnings("checkstyle:IllegalCatch")
2586 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2587 GetFixedIPsForNeutronPortInput input) {
2588 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2589 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2590 Uuid portId = input.getPortId();
2591 StringBuilder returnMsg = new StringBuilder();
2593 List<String> fixedIPList = new ArrayList<>();
2594 Port port = neutronvpnUtils.getNeutronPort(portId);
2596 List<FixedIps> fixedIPs = port.getFixedIps();
2597 for (FixedIps ip : fixedIPs) {
2598 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
2601 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2603 if (returnMsg.length() != 0) {
2604 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2606 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2607 returnMsg)).build());
2609 opBuilder.setFixedIPs(fixedIPList);
2610 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2612 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2614 } catch (Exception ex) {
2615 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2616 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2617 portId.getValue(), ex.getMessage(), ex)).build());
2623 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2626 // TODO Clean up the exception handling
2627 @SuppressWarnings("checkstyle:IllegalCatch")
2628 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2630 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2631 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2633 LOG.debug("dissociateNetworks {}", input);
2634 StringBuilder returnMsg = new StringBuilder();
2635 Uuid vpnId = input.getVpnId();
2638 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2639 List<Uuid> netIds = input.getNetworkId();
2640 if (netIds != null && !netIds.isEmpty()) {
2641 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2642 if (!failed.isEmpty()) {
2643 returnMsg.append(failed);
2647 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2649 if (returnMsg.length() != 0) {
2650 opBuilder.setResponse(
2651 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2652 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2653 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2655 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2657 } catch (Exception ex) {
2658 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2659 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2660 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2662 LOG.debug("dissociateNetworks returns..");
2667 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2670 // TODO Clean up the exception handling
2671 @SuppressWarnings("checkstyle:IllegalCatch")
2672 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2674 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2676 LOG.debug("dissociateRouter {}", input);
2677 StringBuilder returnMsg = new StringBuilder();
2678 Uuid vpnId = input.getVpnId();
2679 Uuid routerId = input.getRouterId();
2681 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2682 if (routerId != null) {
2683 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
2685 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2686 if (vpnId.equals(routerVpnId)) {
2687 dissociateRouterFromVpn(vpnId, routerId);
2689 if (routerVpnId == null) {
2690 returnMsg.append("input router ").append(routerId.getValue())
2691 .append(" not associated to any vpn yet");
2693 returnMsg.append("input router ").append(routerId.getValue())
2694 .append(" associated to vpn ")
2695 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2699 returnMsg.append("router not found : ").append(routerId.getValue());
2703 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2705 if (returnMsg.length() != 0) {
2706 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2707 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to vpn {} failed due to {}",
2708 routerId.getValue(), vpnId.getValue(), returnMsg)).build());
2710 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2712 } catch (Exception ex) {
2713 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2714 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}", routerId.getValue(),
2715 vpnId.getValue(), ex.getMessage(), ex)).build());
2717 LOG.debug("dissociateRouter returns..");
2722 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2723 // check if the router is associated to some VPN
2724 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2725 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2726 if (vpnId != null) {
2727 // remove existing external vpn interfaces
2728 for (Uuid subnetId : routerSubnetIds) {
2729 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2731 clearFromVpnMaps(vpnId, routerId, null);
2733 // remove existing internal vpn interfaces
2734 for (Uuid subnetId : routerSubnetIds) {
2735 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2738 // delete entire vpnMaps node for internal VPN
2739 deleteVpnMapsNode(routerId);
2741 // delete vpn-instance for internal VPN
2742 deleteVpnInstance(routerId);
2745 protected Subnet getNeutronSubnet(Uuid subnetId) {
2746 return neutronvpnUtils.getNeutronSubnet(subnetId);
2749 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2750 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2752 return sn.getGatewayIp();
2758 protected Network getNeutronNetwork(Uuid networkId) {
2759 return neutronvpnUtils.getNeutronNetwork(networkId);
2762 protected Port getNeutronPort(String name) {
2763 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2766 protected Port getNeutronPort(Uuid portId) {
2767 return neutronvpnUtils.getNeutronPort(portId);
2770 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2771 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2774 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2775 return neutronvpnUtils.getNetworksForVpn(vpnId);
2779 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2781 * @return a List of String to be printed on screen
2782 * @throws ReadFailedException if there was a problem reading from the data store
2784 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2785 List<String> result = new ArrayList<>();
2786 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2788 result.add("-------------------------------------------------------------------------------------------");
2789 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2791 Optional<Ports> ports = syncReadOptional(dataBroker, CONFIGURATION, portidentifier);
2792 if (ports.isPresent() && ports.get().getPort() != null) {
2793 for (Port port : ports.get().getPort()) {
2794 List<FixedIps> fixedIPs = port.getFixedIps();
2795 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2796 List<String> ipList = new ArrayList<>();
2797 for (FixedIps fixedIp : fixedIPs) {
2798 IpAddress ipAddress = fixedIp.getIpAddress();
2799 if (ipAddress.getIpv4Address() != null) {
2800 ipList.add(ipAddress.getIpv4Address().getValue());
2802 ipList.add(ipAddress.getIpv6Address().getValue());
2805 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2806 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2807 ipList.toString()));
2809 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2810 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2819 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2821 * @param vpnuuid Uuid of the VPN whose config must be shown
2822 * @return formatted output list
2823 * @throws InterruptedException if there was a thread related problem getting the data to display
2824 * @throws ExecutionException if there was any other problem getting the data to display
2826 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2827 List<String> result = new ArrayList<>();
2828 if (vpnuuid == null) {
2830 result.add("Displaying VPN config for all VPNs");
2831 result.add("To display VPN config for a particular VPN, use the following syntax");
2832 result.add(getshowVpnConfigCLIHelp());
2834 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2835 if (rpcResult.isSuccessful()) {
2837 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2839 result.add(String.format(" %-80s ", "Import-RTs"));
2841 result.add(String.format(" %-80s ", "Export-RTs"));
2843 result.add(String.format(" %-76s ", "Subnet IDs"));
2845 result.add("------------------------------------------------------------------------------------");
2847 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2848 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2849 .rev150602.VpnInstance vpn : vpnList) {
2850 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2852 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2853 vpn.getRouteDistinguisher()));
2855 result.add(String.format(" %-80s ", vpn.getImportRT()));
2857 result.add(String.format(" %-80s ", vpn.getExportRT()));
2860 Uuid vpnid = vpn.getId();
2861 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
2862 if (!subnetList.isEmpty()) {
2863 for (Uuid subnetuuid : subnetList) {
2864 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2867 result.add(String.format(" %-76s ", "\" \""));
2870 result.add("----------------------------------------");
2874 String errortag = rpcResult.getErrors().iterator().next().getTag();
2875 if (Objects.equals(errortag, "")) {
2877 result.add("No VPN has been configured yet");
2878 } else if (Objects.equals(errortag, "invalid-value")) {
2880 result.add("VPN " + vpnuuid.getValue() + " is not present");
2882 result.add("error getting VPN info : " + rpcResult.getErrors());
2883 result.add(getshowVpnConfigCLIHelp());
2889 protected void createExternalVpnInterfaces(Uuid extNetId) {
2890 if (extNetId == null) {
2891 LOG.error("createExternalVpnInterfaces: external network is null");
2895 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2896 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2897 LOG.error("No external ports attached to external network {}", extNetId.getValue());
2901 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
2902 for (String elanInterface : extElanInterfaces) {
2903 createExternalVpnInterface(extNetId, elanInterface, tx);
2905 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
2908 // TODO Clean up the exception handling
2909 @SuppressWarnings("checkstyle:IllegalCatch")
2910 protected void removeExternalVpnInterfaces(Uuid extNetId) {
2911 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2912 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2913 LOG.error("No external ports attached for external network {}", extNetId.getValue());
2916 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
2917 for (String elanInterface : extElanInterfaces) {
2918 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2919 .buildVpnInterfaceIdentifier(elanInterface);
2920 LOG.info("Removing vpn interface {}", elanInterface);
2921 tx.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2923 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
2926 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2927 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null,
2928 false /* not a router iface */, wrtConfigTxn);
2931 // TODO Clean up the exception handling
2932 @SuppressWarnings("checkstyle:IllegalCatch")
2933 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
2934 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2935 if (vpnIdList.isEmpty() || infName == null) {
2936 LOG.error("vpn id or interface is null");
2939 if (wrtConfigTxn == null) {
2940 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
2941 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, isRouterInterface, tx)), LOG,
2942 "Error writing VPN interface");
2945 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
2946 for (Uuid vpnId: vpnIdList) {
2947 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
2948 AssociatedSubnetType.V4AndV6Subnets);
2949 vpnIdListStruct.add(vpnInstance);
2952 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2953 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2955 .setVpnInstanceNames(vpnIdListStruct)
2956 .setRouterInterface(isRouterInterface);
2957 if (adjacencies != null) {
2958 vpnb.addAugmentation(Adjacencies.class, adjacencies);
2960 VpnInterface vpnIf = vpnb.build();
2962 LOG.info("Creating vpn interface {}", vpnIf);
2963 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2964 } catch (Exception ex) {
2965 LOG.error("Creation of vpninterface {} failed", infName, ex);
2969 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
2970 WriteTransaction wrtConfigTxn) {
2971 if (vpnId == null || infName == null) {
2972 LOG.error("vpn id or interface is null");
2975 if (wrtConfigTxn == null) {
2976 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
2977 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
2978 }), LOG, "Error updating VPN interface with adjacencies");
2982 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2983 boolean isLockAcquired = false;
2985 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2986 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
2987 .syncReadOptional(dataBroker, LogicalDatastoreType
2988 .CONFIGURATION, vpnIfIdentifier);
2989 if (optionalVpnInterface.isPresent()) {
2990 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
2991 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
2993 if (adjacencies == null) {
2994 if (isLockAcquired) {
2995 interfaceLock.unlock(infName);
2999 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3000 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3001 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3002 optionalVpnInterface.get().getVpnInstanceNames());
3003 if (listVpnInstances.isEmpty() || !VpnHelper
3004 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),listVpnInstances)) {
3005 VpnInstanceNames vpnInstance = VpnHelper
3006 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3007 listVpnInstances.add(vpnInstance);
3008 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3011 VpnInstanceNames vpnInstance = VpnHelper
3012 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3013 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3014 listVpnInstances.add(vpnInstance);
3015 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3017 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3018 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder.build());
3020 } catch (IllegalStateException | ReadFailedException ex) {
3021 LOG.error("Update of vpninterface {} failed", infName, ex);
3023 if (isLockAcquired) {
3024 interfaceLock.unlock(infName);
3029 private String getshowVpnConfigCLIHelp() {
3030 StringBuilder help = new StringBuilder("Usage:");
3031 help.append("display vpn-config [-vid/--vpnid <id>]");
3032 return help.toString();
3035 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3036 InterruptedException {
3037 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3038 .setVpnId(vpnId).build();
3039 LOG.info("publishing notification upon association of router to VPN");
3040 notificationPublishService.putNotification(routerAssociatedToVpn);
3043 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3044 InterruptedException {
3045 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3046 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3047 LOG.info("publishing notification upon disassociation of router from VPN");
3048 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3051 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3052 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3056 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3057 return neutronEvpnManager.createEVPN(input);
3061 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3062 return neutronEvpnManager.getEVPN(input);
3066 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3067 return neutronEvpnManager.deleteEVPN(input);
3070 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3071 Uuid extNetId = extNet.getUuid();
3072 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3073 .child(Networks.class, new NetworksKey(extNetId)).build();
3076 Optional<Networks> optionalExtNets =
3077 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3079 if (!optionalExtNets.isPresent()) {
3080 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3081 extNetId.getValue());
3084 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3085 builder.setVpnid(vpnId);
3086 Networks networks = builder.build();
3087 // Add Networks object to the ExternalNetworks list
3088 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3089 extNetId.getValue());
3090 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3093 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3094 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3095 extNetId.getValue(), ex);
3100 private boolean removeExternalNetworkFromVpn(Network extNet) {
3101 Uuid extNetId = extNet.getUuid();
3102 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3103 .child(Networks.class, new NetworksKey(extNetId)).build();
3105 Optional<Networks> optionalNets =
3106 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3108 NetworksBuilder builder = null;
3109 if (optionalNets.isPresent()) {
3110 builder = new NetworksBuilder(optionalNets.get());
3112 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3113 extNetId.getValue());
3116 builder.setVpnid(null);
3117 Networks networks = builder.build();
3118 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3119 extNetId.getValue());
3120 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3122 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3123 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3124 extNetId.getValue(), ex);
3129 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3130 Optional<String> existingVpnName = Optional.of(primaryRd);
3131 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3133 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3134 .syncReadOptional(dataBroker, OPERATIONAL, neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3135 } catch (ReadFailedException e) {
3136 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3138 /*Read failed. We don't know if a VPN exists or not.
3139 * Return primaryRd to halt caller execution, to be safe.*/
3140 return existingVpnName;
3142 if (vpnInstanceOpDataOptional.isPresent()) {
3143 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3145 existingVpnName = Optional.absent();
3147 return existingVpnName;
3150 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3151 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3154 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3155 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3158 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3159 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3162 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3163 String message = tuple.getMessage();
3164 logger.accept(message);