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.JdkFutureAdapters;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.SettableFuture;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.EventListener;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
30 import java.util.Map.Entry;
31 import java.util.Objects;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ExecutionException;
35 import java.util.concurrent.Future;
36 import java.util.concurrent.TimeUnit;
37 import java.util.function.Consumer;
38 import javax.annotation.Nonnull;
39 import javax.annotation.Nullable;
40 import javax.annotation.PreDestroy;
41 import javax.inject.Inject;
42 import javax.inject.Singleton;
43 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
44 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
45 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
46 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
47 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
48 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
49 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
50 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
51 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
52 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
53 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
54 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
55 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
56 import org.opendaylight.netvirt.elanmanager.api.IElanService;
57 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
58 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
59 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
60 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
61 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
62 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
63 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
82 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
168 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
169 import org.opendaylight.yangtools.yang.common.RpcError;
170 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
171 import org.opendaylight.yangtools.yang.common.RpcResult;
172 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
173 import org.slf4j.Logger;
174 import org.slf4j.LoggerFactory;
175 import org.slf4j.helpers.FormattingTuple;
176 import org.slf4j.helpers.MessageFormatter;
179 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
181 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
182 private static long LOCK_WAIT_TIME = 10L;
184 private final DataBroker dataBroker;
185 private final ManagedNewTransactionRunner managedNewTransactionRunner;
186 private final NotificationPublishService notificationPublishService;
187 private final VpnRpcService vpnRpcService;
188 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
189 private final IElanService elanService;
190 private final NeutronvpnConfig neutronvpnConfig;
191 private final NeutronEvpnManager neutronEvpnManager;
192 private final NeutronEvpnUtils neutronEvpnUtils;
193 private final JobCoordinator jobCoordinator;
194 private final NeutronvpnUtils neutronvpnUtils;
195 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
196 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
197 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
198 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
201 public NeutronvpnManager(
202 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
203 final VpnRpcService vpnRpcSrv, final IElanService elanService,
204 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
205 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
206 final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
207 this.dataBroker = dataBroker;
208 this.managedNewTransactionRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
209 notificationPublishService = notiPublishService;
210 vpnRpcService = vpnRpcSrv;
211 this.elanService = elanService;
212 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
213 this.neutronvpnConfig = neutronvpnConfig;
214 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
215 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
216 this.jobCoordinator = jobCoordinator;
217 this.neutronvpnUtils = neutronvpnUtils;
224 public void close() {
225 LOG.info("{} close", getClass().getSimpleName());
228 private void configureFeatures() {
229 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
230 Neutron.class).child(Features.class).child(
231 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
232 Feature feature = new FeatureBuilder().setKey(new FeatureKey(OperationalPortStatus.class)).build();
234 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
235 } catch (TransactionCommitFailedException e) {
236 LOG.warn("Error configuring feature {}", feature, e);
240 public String getOpenDaylightVniRangesConfig() {
241 return neutronvpnConfig.getOpendaylightVniRanges();
244 // TODO Clean up the exception handling
245 @SuppressWarnings("checkstyle:IllegalCatch")
246 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
247 NetworkAttributes.NetworkType networkType, long segmentationId) {
249 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
250 synchronized (subnetId.getValue().intern()) {
251 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
252 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
253 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
254 if (sn.isPresent()) {
255 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
256 subnetId.getValue());
259 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId))
260 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
261 .setNetworkType(networkType).setSegmentationId(segmentationId);
262 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
263 subnetId.getValue());
264 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
265 subnetMapIdentifier, subnetmapBuilder.build());
267 } catch (TransactionCommitFailedException | ReadFailedException e) {
268 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
270 // check if there are ports to update for already created Subnetmap node
271 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
272 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
273 if (entry.getValue().getValue().equals(subnetId.getValue())) {
274 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
275 unprocessedPortsMap.remove(entry.getKey());
280 protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) {
281 Subnetmap subnetmap = null;
282 SubnetmapBuilder builder = null;
283 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
284 .child(Subnetmap.class, new SubnetmapKey(subnetId))
287 synchronized (subnetId.getValue().intern()) {
288 Optional<Subnetmap> sn =
289 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
291 if (sn.isPresent()) {
292 builder = new SubnetmapBuilder(sn.get());
293 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
295 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
298 if (routerId != null) {
299 builder.setRouterId(routerId);
302 builder.setVpnId(vpnId);
304 builder.setInternetVpnId(internetvpnId);
306 subnetmap = builder.build();
307 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
308 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
310 } catch (ReadFailedException | TransactionCommitFailedException e) {
311 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
316 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
317 Uuid routerInterfacePortId, String fixedIp,
318 String routerIntfMacAddress, Uuid vpnId) {
319 Subnetmap subnetmap = null;
320 SubnetmapBuilder builder = null;
321 InstanceIdentifier<Subnetmap> id =
322 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
324 synchronized (subnetId.getValue().intern()) {
325 Optional<Subnetmap> sn =
326 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
328 if (sn.isPresent()) {
329 builder = new SubnetmapBuilder(sn.get());
330 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
331 subnetId.getValue());
333 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
334 subnetId.getValue());
337 builder.setRouterId(routerId);
338 builder.setRouterInterfacePortId(routerInterfacePortId);
339 builder.setRouterIntfMacAddress(routerIntfMacAddress);
340 builder.setRouterInterfaceFixedIp(fixedIp);
342 builder.setVpnId(vpnId);
344 subnetmap = builder.build();
345 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
346 subnetId.getValue());
347 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
349 } catch (ReadFailedException | TransactionCommitFailedException e) {
350 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
351 subnetId.getValue(), e);
355 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
356 Subnetmap subnetmap = null;
357 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
358 new SubnetmapKey(subnetId)).build();
359 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
361 synchronized (subnetId.getValue().intern()) {
362 Optional<Subnetmap> sn =
363 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
365 if (sn.isPresent()) {
366 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
367 if (null != portId) {
368 List<Uuid> portList = builder.getPortList();
369 if (null == portList) {
370 portList = new ArrayList<>();
372 portList.add(portId);
373 builder.setPortList(portList);
374 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
375 subnetId.getValue(), portId.getValue());
377 if (null != directPortId) {
378 List<Uuid> directPortList = builder.getDirectPortList();
379 if (null == directPortList) {
380 directPortList = new ArrayList<>();
382 directPortList.add(directPortId);
383 builder.setDirectPortList(directPortList);
384 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
385 directPortId.getValue());
387 subnetmap = builder.build();
388 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
391 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
392 + "cache ", subnetId.getValue(), portId.getValue());
393 unprocessedPortsMap.put(portId, subnetId);
396 } catch (ReadFailedException | TransactionCommitFailedException e) {
397 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
402 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId,
403 Uuid vpnId, Uuid portId) {
404 Subnetmap subnetmap = null;
405 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
406 .child(Subnetmap.class, new SubnetmapKey(subnetId))
409 synchronized (subnetId.getValue().intern()) {
410 Optional<Subnetmap> sn =
411 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
413 if (sn.isPresent()) {
414 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
415 if (routerId != null) {
416 builder.setRouterId(null);
418 if (networkId != null) {
419 builder.setNetworkId(null);
422 builder.setVpnId(null);
424 builder.setInternetVpnId(null);
425 if (portId != null && builder.getPortList() != null) {
426 List<Uuid> portList = builder.getPortList();
427 portList.remove(portId);
428 builder.setPortList(portList);
431 subnetmap = builder.build();
432 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
433 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
436 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
439 } catch (ReadFailedException | TransactionCommitFailedException e) {
440 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
445 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
446 Subnetmap subnetmap = null;
447 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
448 new SubnetmapKey(subnetId)).build();
450 synchronized (subnetId.getValue().intern()) {
451 Optional<Subnetmap> sn =
452 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
454 if (sn.isPresent()) {
455 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
456 if (null != portId && null != builder.getPortList()) {
457 List<Uuid> portList = builder.getPortList();
458 portList.remove(portId);
459 builder.setPortList(portList);
460 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
461 subnetId.getValue());
463 if (null != directPortId && null != builder.getDirectPortList()) {
464 List<Uuid> directPortList = builder.getDirectPortList();
465 directPortList.remove(directPortId);
466 builder.setDirectPortList(directPortList);
467 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
468 .getValue(), subnetId.getValue());
470 subnetmap = builder.build();
471 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
474 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
477 } catch (ReadFailedException | TransactionCommitFailedException e) {
478 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
479 subnetId.getValue(), e);
484 // TODO Clean up the exception handling
485 @SuppressWarnings("checkstyle:IllegalCatch")
486 protected void deleteSubnetMapNode(Uuid subnetId) {
487 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
488 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
489 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
491 synchronized (subnetId.getValue().intern()) {
492 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
493 subnetMapIdentifier);
495 } catch (TransactionCommitFailedException e) {
496 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
500 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
501 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
502 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
504 Optional<VpnInstance> vpnInstanceConfig =
505 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
507 if (!vpnInstanceConfig.isPresent()) {
508 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
511 VpnInstance vpnInstance = vpnInstanceConfig.get();
512 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
513 if (vpnInstance.getIpv4Family() != null) {
514 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
515 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
517 if (vpnInstance.getIpv6Family() != null) {
518 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
519 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
521 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
522 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
523 updateVpnInstanceBuilder.build());
524 } catch (ReadFailedException | TransactionCommitFailedException ex) {
525 LOG.warn("Error configuring feature ", ex);
529 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
530 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
531 String vpnName = vpnId.getValue();
532 VpnInstanceBuilder builder = null;
533 List<VpnTarget> vpnTargetList = new ArrayList<>();
534 boolean isLockAcquired = false;
535 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
536 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
538 Optional<VpnInstance> optionalVpn =
539 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
541 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
542 if (optionalVpn.isPresent()) {
543 builder = new VpnInstanceBuilder(optionalVpn.get());
544 LOG.debug("updating existing vpninstance node");
546 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
547 .setType(type).setL3vni(l3vni);
549 if (irt != null && !irt.isEmpty()) {
550 if (ert != null && !ert.isEmpty()) {
551 List<String> commonRT = new ArrayList<>(irt);
552 commonRT.retainAll(ert);
554 for (String common : commonRT) {
557 VpnTarget vpnTarget =
558 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
559 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
560 vpnTargetList.add(vpnTarget);
563 for (String importRT : irt) {
564 VpnTarget vpnTarget =
565 new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
566 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
567 vpnTargetList.add(vpnTarget);
571 if (ert != null && !ert.isEmpty()) {
572 for (String exportRT : ert) {
573 VpnTarget vpnTarget =
574 new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
575 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
576 vpnTargetList.add(vpnTarget);
580 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
582 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
583 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
585 if (rd != null && !rd.isEmpty()) {
586 ipv4vpnBuilder.setRouteDistinguisher(rd);
587 ipv6vpnBuilder.setRouteDistinguisher(rd);
590 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
591 builder.setIpv4Family(ipv4vpnBuilder.build());
593 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
594 builder.setIpv6Family(ipv6vpnBuilder.build());
596 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
597 builder.setIpv4Family(ipv4vpnBuilder.build());
599 VpnInstance newVpn = builder.build();
600 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
601 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
602 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
604 } catch (ReadFailedException | TransactionCommitFailedException e) {
605 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
607 if (isLockAcquired) {
608 vpnLock.unlock(vpnId);
613 private void deleteVpnMapsNode(Uuid vpnId) {
614 boolean isLockAcquired = false;
615 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
616 .child(VpnMap.class, new VpnMapKey(vpnId))
618 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
620 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
621 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
622 } catch (TransactionCommitFailedException e) {
623 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
625 if (isLockAcquired) {
626 vpnLock.unlock(vpnId);
631 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
632 VpnMapBuilder builder;
633 boolean isLockAcquired = false;
634 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
635 .child(VpnMap.class, new VpnMapKey(vpnId))
638 Optional<VpnMap> optionalVpnMap =
639 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
641 if (optionalVpnMap.isPresent()) {
642 builder = new VpnMapBuilder(optionalVpnMap.get());
644 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
648 builder.setName(name);
650 if (tenantId != null) {
651 builder.setTenantId(tenantId);
653 if (router != null) {
654 builder.setRouterId(router);
656 if (networks != null) {
657 List<Uuid> nwList = builder.getNetworkIds();
658 if (nwList == null) {
659 nwList = new ArrayList<>();
661 nwList.addAll(networks);
662 builder.setNetworkIds(nwList);
665 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
666 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
667 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
669 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
670 } catch (ReadFailedException | TransactionCommitFailedException e) {
671 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
673 if (isLockAcquired) {
674 vpnLock.unlock(vpnId);
679 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
680 boolean isLockAcquired = false;
681 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
682 .child(VpnMap.class, new VpnMapKey(vpnId))
684 Optional<VpnMap> optionalVpnMap;
687 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
689 } catch (ReadFailedException e) {
690 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
693 if (optionalVpnMap.isPresent()) {
694 VpnMap vpnMap = optionalVpnMap.get();
695 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
696 if (routerId != null) {
697 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
699 // remove entire node in case of internal VPN
700 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
701 LOG.debug("removing vpnMaps node: {} ", vpnId);
702 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
704 } catch (TransactionCommitFailedException e) {
705 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
707 if (isLockAcquired) {
708 vpnLock.unlock(vpnId);
713 vpnMapBuilder.setRouterId(null);
715 if (networkIds != null) {
716 List<Uuid> vpnNw = vpnMap.getNetworkIds();
717 vpnNw.removeAll(networkIds);
718 if (vpnNw.isEmpty()) {
719 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
720 vpnMapBuilder.setNetworkIds(null);
722 vpnMapBuilder.setNetworkIds(vpnNw);
727 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
728 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
729 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
730 vpnMapBuilder.build());
731 } catch (TransactionCommitFailedException e) {
732 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
734 if (isLockAcquired) {
735 vpnLock.unlock(vpnId);
739 LOG.error("VPN : {} not found", vpnId.getValue());
741 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
744 private void deleteVpnInstance(Uuid vpnId) {
745 boolean isLockAcquired = false;
746 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
747 .child(VpnInstance.class,
748 new VpnInstanceKey(vpnId.getValue()))
751 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
752 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
753 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
754 } catch (TransactionCommitFailedException e) {
755 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
757 if (isLockAcquired) {
758 vpnLock.unlock(vpnId);
763 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
764 WriteTransaction wrtConfigTxn, Subnetmap sn, VpnInterface vpnIface) {
765 List<Adjacency> adjList = new ArrayList<>();
766 if (vpnIface != null) {
767 adjList = vpnIface.getAugmentation(Adjacencies.class).getAdjacency();
769 String infName = port.getUuid().getValue();
770 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
771 for (FixedIps ip : port.getFixedIps()) {
772 String ipValue = String.valueOf(ip.getIpAddress().getValue());
773 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
774 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
777 Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
778 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
779 .setSubnetId(ip.getSubnetId()).build();
780 if (!adjList.contains(vmAdj)) {
783 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
784 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
785 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
787 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
788 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
790 if (snTemp != null && snTemp.getInternetVpnId() != null) {
791 neutronvpnUtils.createVpnPortFixedIpToPort(sn.getInternetVpnId().getValue(),
792 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
794 if (routerId != null) {
795 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
796 if (rtr != null && rtr.getRoutes() != null) {
797 List<Routes> routeList = rtr.getRoutes();
798 // create extraroute Adjacence for each ipValue,
799 // because router can have IPv4 and IPv6 subnet ports, or can have
800 // more that one IPv4 subnet port or more than one IPv6 subnet port
801 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
802 if (!erAdjList.isEmpty()) {
803 adjList.addAll(erAdjList);
808 return new AdjacenciesBuilder().setAdjacency(adjList).build();
811 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port, WriteTransaction wrtConfigTxn) {
812 boolean isRouterInterface = false;
813 if (port.getDeviceOwner() != null) {
814 isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
816 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
817 String infName = port.getUuid().getValue();
818 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
819 writeVpnInterfaceToDs(vpnIds, infName, adjs, isRouterInterface, wrtConfigTxn);
822 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
823 Port port, Subnetmap sn, WriteTransaction wrtConfigTxn) {
824 String infName = port.getUuid().getValue();
825 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
826 Optional<VpnInterface> optionalVpnInterface = null;
827 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
828 vpnId, internetVpnId, infName);
830 optionalVpnInterface = SingleTransactionDataBroker
831 .syncReadOptional(dataBroker, LogicalDatastoreType
832 .CONFIGURATION, vpnIfIdentifier);
833 } catch (ReadFailedException e) {
834 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
837 if (!optionalVpnInterface.isPresent()) {
840 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
841 sn != null ? sn.getSubnetIp() : "null");
842 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().getAugmentation(Adjacencies.class).getAdjacency();
843 List<Adjacency> updatedAdjsList = new ArrayList<>();
844 boolean isIpFromAnotherSubnet = false;
845 for (Adjacency adj : vpnAdjsList) {
846 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
847 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
848 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
849 isIpFromAnotherSubnet = true;
851 updatedAdjsList.add(adj);
854 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
855 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
858 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
859 String.valueOf(adjString), wrtConfigTxn);
861 if (internetVpnId != null) {
862 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
863 String.valueOf(adjString), wrtConfigTxn);
866 if (port.getDeviceOwner()
867 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
868 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
869 if (rtr != null && rtr.getRoutes() != null) {
870 List<Routes> extraRoutesToRemove = new ArrayList<>();
871 for (Routes rt: rtr.getRoutes()) {
872 if (rt.getNexthop().toString().equals(adjString)) {
873 extraRoutesToRemove.add(rt);
877 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
878 extraRoutesToRemove, vpnId);
879 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
881 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
886 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
888 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
890 if (internetVpnId != null) {
891 updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn);
893 if (!isIpFromAnotherSubnet) {
894 // no more subnetworks for neutron port
895 if (sn != null && sn.getRouterId() != null) {
896 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
898 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
904 // TODO Clean up the exception handling
905 @SuppressWarnings("checkstyle:IllegalCatch")
906 protected boolean deleteVpnInterface(String infName, @Nullable String vpnId, WriteTransaction wrtConfigTxn) {
907 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
908 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
909 Optional<VpnInterface> optionalVpnInterface = null;
911 optionalVpnInterface =
912 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
914 } catch (ReadFailedException ex) {
915 LOG.error("Error during deletion of vpninterface {}", infName, ex);
918 if (!optionalVpnInterface.isPresent()) {
919 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
922 boolean wrtConfigTxnPresent = true;
923 if (wrtConfigTxn == null) {
924 wrtConfigTxnPresent = false;
925 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
928 VpnInterface vpnInterface = optionalVpnInterface.get();
929 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
931 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
932 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
933 if (!vpnList.isEmpty()) {
934 if (!wrtConfigTxnPresent) {
935 wrtConfigTxn.submit();
937 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
938 + "List not empty", infName);
941 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
942 .setVpnInstanceNames(vpnList);
943 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
947 LOG.debug("Deleting vpn interface {}", infName);
948 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
949 if (!wrtConfigTxnPresent) {
950 wrtConfigTxn.submit();
955 protected void removeVpnFromVpnInterface(Uuid vpnId, Port port,
956 WriteTransaction writeConfigTxn, Subnetmap sm) {
957 if (vpnId == null || port == null) {
960 String infName = port.getUuid().getValue();
961 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
963 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
964 .syncReadOptional(dataBroker, LogicalDatastoreType
965 .CONFIGURATION, vpnIfIdentifier);
966 if (optionalVpnInterface.isPresent()) {
967 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
969 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
970 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
972 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
973 .setVpnInstanceNames(listVpn);
974 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
975 LOG.debug("Updating vpn interface {}", infName);
976 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
977 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
978 while (adjacencyIter.hasNext()) {
979 Adjacency adjacency = adjacencyIter.next();
980 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
983 String mipToQuery = adjacency.getIpAddress().split("/")[0];
984 InstanceIdentifier<LearntVpnVipToPort> id =
985 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
986 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
987 SingleTransactionDataBroker.syncReadOptional(dataBroker,
988 LogicalDatastoreType.OPERATIONAL, id);
989 if (optionalVpnVipToPort.isPresent()) {
990 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
992 if (listVpn == null || listVpn.isEmpty()) {
993 adjacencyIter.remove();
995 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
996 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
997 mipToQuery, infName, vpnId.getValue());
1000 List<FixedIps> ips = port.getFixedIps();
1001 for (FixedIps ip : ips) {
1002 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1003 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1004 ipValue, writeConfigTxn);
1006 if (listVpn == null || listVpn.isEmpty()) {
1007 if (sm != null && sm.getRouterId() != null) {
1008 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1010 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1012 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1016 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1018 } catch (ReadFailedException ex) {
1019 LOG.error("Update of vpninterface {} failed", infName, ex);
1023 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
1024 boolean isSubnetIp, WriteTransaction writeConfigTxn) {
1025 if (vpnId == null || port == null) {
1028 boolean isLockAcquired = false;
1029 String infName = port.getUuid().getValue();
1030 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1033 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1034 Optional<VpnInterface> optionalVpnInterface =
1035 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1037 if (optionalVpnInterface.isPresent()) {
1038 VpnInstanceNames vpnInstance = VpnHelper
1039 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1040 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1041 .get().getVpnInstanceNames());
1042 if (oldVpnId != null
1043 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1044 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1046 if (vpnId.getValue() != null
1047 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1048 listVpn.add(vpnInstance);
1050 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1051 .setVpnInstanceNames(listVpn);
1052 LOG.debug("Updating vpn interface {}", infName);
1053 if (!isBeingAssociated) {
1054 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
1055 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1056 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1057 while (adjacencyIter.hasNext()) {
1058 Adjacency adjacency = adjacencyIter.next();
1059 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1060 InstanceIdentifier<LearntVpnVipToPort> id =
1061 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1062 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1063 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1064 LogicalDatastoreType.OPERATIONAL, id);
1065 if (optionalVpnVipToPort.isPresent()) {
1066 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1067 + "from VPN {}", infName, vpnId, oldVpnId);
1068 adjacencyIter.remove();
1069 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1071 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1072 mipToQuery, infName, vpnId.getValue());
1075 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1076 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1078 List<FixedIps> ips = port.getFixedIps();
1079 for (FixedIps ip : ips) {
1080 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1081 if (oldVpnId != null) {
1082 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1083 ipValue, writeConfigTxn);
1085 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1086 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1088 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1091 LOG.error("VPN Interface {} not found", infName);
1093 } catch (ReadFailedException ex) {
1094 LOG.error("Updation of vpninterface {} failed", infName, ex);
1096 if (isLockAcquired) {
1097 interfaceLock.unlock(infName);
1102 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
1103 List<String> ert, Uuid router, List<Uuid> networks) {
1105 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1107 // Update VPN Instance node
1108 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1110 // Update local vpn-subnet DS
1111 updateVpnMaps(vpn, name, router, tenant, networks);
1113 if (router != null) {
1114 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1115 if (existingVpn != null) {
1116 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1117 // if before reboot, router was already associated to VPN, should not proceed associating router to
1118 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1119 // preserved upon reboot.
1120 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1121 // RouterInterfacesMap via #createVPNInterface call.
1122 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1123 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1126 associateRouterToInternalVpn(vpn, router);
1131 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1132 * specified Neutron Networks and Routers.
1134 * @param vpn Uuid of the VPN tp be created
1135 * @param name Representative name of the new VPN
1136 * @param tenant Uuid of the Tenant under which the VPN is going to be created
1137 * @param rd Route-distinguisher for the VPN
1138 * @param irt A list of Import Route Targets
1139 * @param ert A list of Export Route Targets
1140 * @param router neutron router Id to associate with created VPN
1141 * @param networks UUID of the neutron network the VPN may be associated to
1142 * @param type Type of the VPN Instance
1143 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1144 * @throws Exception if association of L3VPN failed
1146 public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
1147 Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni)
1150 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1152 if (router != null) {
1153 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1154 ipVersChoices = ipVersChoices.addVersion(vers);
1156 updateVpnInstanceNode(vpn, rd, irt, ert, type, l3vni, ipVersChoices);
1158 // Please note that router and networks will be filled into VPNMaps
1159 // by subsequent calls here to associateRouterToVpn and
1160 // associateNetworksToVpn
1161 updateVpnMaps(vpn, name, null, tenant, null);
1163 if (router != null) {
1164 associateRouterToVpn(vpn, router);
1166 if (networks != null) {
1167 List<String> failStrings = associateNetworksToVpn(vpn, networks);
1168 if (!failStrings.isEmpty()) {
1169 LOG.error("VPN {} association to networks failed for networks: {}. ",
1170 vpn.getValue(), failStrings.toString());
1171 throw new Exception(failStrings.toString());
1177 * It handles the invocations to the createVPN RPC method.
1180 // TODO Clean up the exception handling
1181 @SuppressWarnings("checkstyle:IllegalCatch")
1182 public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1184 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1185 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1186 List<RpcError> errorList = new ArrayList<>();
1187 int failurecount = 0;
1188 int warningcount = 0;
1190 List<L3vpn> vpns = input.getL3vpn();
1191 for (L3vpn vpn : vpns) {
1192 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1193 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1194 formatAndLog(LOG::warn,
1195 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1196 vpn.getId().getValue())));
1200 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1201 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1202 formatAndLog(LOG::warn,
1203 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1204 vpn.getId().getValue())));
1208 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1210 if (vpn.getL3vni() != null) {
1211 l3vni = vpn.getL3vni();
1214 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1215 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1216 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1217 formatAndLog(LOG::warn,
1218 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1219 + "is already configured",
1220 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1224 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1225 if (operationalVpn.isPresent()) {
1226 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1227 formatAndLog(LOG::error,
1228 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1229 + "is still available. Please retry creation of a new vpn with the same RD"
1230 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1231 vpn.getRouteDistinguisher().get(0))));
1235 if (vpn.getRouterId() != null) {
1236 if (neutronvpnUtils.getNeutronRouter(vpn.getRouterId()) == null) {
1237 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1238 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router not found {}",
1239 vpn.getId().getValue(), vpn.getRouterId().getValue())));
1243 Uuid vpnId = neutronvpnUtils.getVpnForRouter(vpn.getRouterId(), true);
1244 if (vpnId != null) {
1245 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1246 formatAndLog(LOG::warn,
1247 "Creation of L3VPN failed for VPN {} due to router {} already associated to "
1248 + "another VPN {}", vpn.getId().getValue(), vpn.getRouterId().getValue(),
1249 vpnId.getValue())));
1254 if (vpn.getNetworkIds() != null) {
1255 int initialWarningCount = warningcount;
1256 for (Uuid nw : vpn.getNetworkIds()) {
1257 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1258 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1259 if (network == null) {
1260 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1261 formatAndLog(LOG::warn,
1262 "Creation of L3VPN failed for VPN {} due to network not found {}",
1263 vpn.getId().getValue(), nw.getValue())));
1265 } else if (vpnId != null) {
1266 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1267 formatAndLog(LOG::warn,
1268 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1269 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1270 vpnId.getValue())));
1274 if (warningcount != initialWarningCount) {
1279 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1280 vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
1281 vpnInstanceType, l3vni);
1282 } catch (Exception ex) {
1283 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1284 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1289 // if at least one succeeds; result is success
1290 // if none succeeds; result is failure
1291 if (failurecount + warningcount == vpns.size()) {
1292 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1294 List<String> errorResponseList = new ArrayList<>();
1295 if (!errorList.isEmpty()) {
1296 for (RpcError rpcError : errorList) {
1297 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1298 + ", ErrorMessage: " + rpcError.getMessage());
1301 errorResponseList.add("Operation successful with no errors");
1303 opBuilder.setResponse(errorResponseList);
1304 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1310 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1313 public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1315 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1316 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1317 Uuid inputVpnId = input.getId();
1318 List<VpnInstance> vpns = new ArrayList<>();
1319 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1322 if (inputVpnId == null) {
1324 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1326 Optional<VpnInstances> optionalVpns =
1327 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1329 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1330 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1331 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1332 // from getL3VPN output
1333 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1339 opBuilder.setL3vpnInstances(l3vpnList);
1340 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1344 String name = inputVpnId.getValue();
1345 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1346 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1347 // read VpnInstance Info
1348 Optional<VpnInstance> optionalVpn =
1349 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1351 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1353 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1354 vpns.add(optionalVpn.get());
1357 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1358 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1362 for (VpnInstance vpnInstance : vpns) {
1363 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1364 // create VpnMaps id
1365 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1366 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1367 List<String> ertList = new ArrayList<>();
1368 List<String> irtList = new ArrayList<>();
1370 if (vpnInstance.getIpv4Family().getVpnTargets() != null) {
1371 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1372 for (VpnTarget vpnTarget : vpnTargetList) {
1373 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1374 ertList.add(vpnTarget.getVrfRTValue());
1376 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1377 irtList.add(vpnTarget.getVrfRTValue());
1379 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1380 ertList.add(vpnTarget.getVrfRTValue());
1381 irtList.add(vpnTarget.getVrfRTValue());
1386 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1388 if (vpnInstance.getL3vni() != null) {
1389 l3vpn.setL3vni(vpnInstance.getL3vni());
1391 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1392 .class, new VpnMapKey(vpnId)).build();
1393 Optional<VpnMap> optionalVpnMap =
1394 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1396 if (optionalVpnMap.isPresent()) {
1397 VpnMap vpnMap = optionalVpnMap.get();
1398 l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1399 .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1401 l3vpnList.add(l3vpn.build());
1404 opBuilder.setL3vpnInstances(l3vpnList);
1405 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1407 } catch (ReadFailedException ex) {
1408 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1409 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1415 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1418 public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1420 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1421 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1422 List<RpcError> errorList = new ArrayList<>();
1424 int failurecount = 0;
1425 int warningcount = 0;
1426 List<Uuid> vpns = input.getId();
1427 for (Uuid vpn : vpns) {
1431 InstanceIdentifier<VpnInstance> vpnIdentifier =
1432 InstanceIdentifier.builder(VpnInstances.class)
1433 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1434 Optional<VpnInstance> optionalVpn =
1435 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1437 if (optionalVpn.isPresent()) {
1440 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1441 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1444 } catch (ReadFailedException ex) {
1445 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1446 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1451 // if at least one succeeds; result is success
1452 // if none succeeds; result is failure
1453 if (failurecount + warningcount == vpns.size()) {
1454 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1456 List<String> errorResponseList = new ArrayList<>();
1457 if (!errorList.isEmpty()) {
1458 for (RpcError rpcError : errorList) {
1459 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1460 + ", ErrorMessage: " + rpcError.getMessage());
1463 errorResponseList.add("Operation successful with no errors");
1465 opBuilder.setResponse(errorResponseList);
1466 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1471 public void createVpnInstanceForSubnet(Uuid subnetId) {
1472 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1473 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1476 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1477 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1478 removeVpn(subnetId);
1481 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1482 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1483 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1484 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1486 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1487 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1490 if (vpnId != null) {
1491 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1492 if (vpnMap == null) {
1493 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1494 + " cannot add subnet {} to VPN", vpnId.getValue(),
1498 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1499 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1500 if (isVpnOfTypeL2(vpnInstance)) {
1501 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1502 NeutronEvpnUtils.Operation.ADD);
1505 if (internetVpnId != null) {
1506 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1507 if (vpnMap == null) {
1508 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1509 + "subnet {} to VPN", internetVpnId.getValue(),
1514 final Uuid internetId = internetVpnId;
1515 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1516 List<Uuid> portList = sn.getPortList();
1517 if (portList != null) {
1518 for (final Uuid portId : portList) {
1519 String vpnInfName = portId.getValue();
1520 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1521 Port port = neutronvpnUtils.getNeutronPort(portId);
1523 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1524 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1527 final Boolean isRouterInterface = port.getDeviceOwner()
1528 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1529 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1530 managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1531 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1533 if (vpnIface == null) {
1534 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1535 Set<Uuid> listVpn = new HashSet<Uuid>();
1536 if (vpnId != null) {
1539 if (internetId != null) {
1540 listVpn.add(internetId);
1542 writeVpnInterfaceToDs(listVpn,
1543 vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
1544 if (sn.getRouterId() != null) {
1545 addToNeutronRouterInterfacesMap(sn.getRouterId(),portId.getValue());
1548 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1549 if (vpnId != null) {
1550 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1552 if (internetId != null) {
1553 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1562 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) {
1563 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1564 "removeSubnetFromVpn: at least one VPN must be not null");
1565 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1566 vpnId, internetVpnId);
1567 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1569 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1572 VpnMap vpnMap = null;
1573 VpnInstance vpnInstance = null;
1574 if (vpnId != null) {
1575 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1576 if (vpnMap == null) {
1577 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1578 vpnId.getValue(), subnet.getValue());
1581 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1583 if (internetVpnId == null) {
1584 internetVpnId = sn.getInternetVpnId();
1586 if (internetVpnId != null) {
1587 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1588 if (vpnMap == null) {
1589 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1590 + " from Internet VPN",
1591 internetVpnId.getValue(), subnet.getValue());
1595 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1596 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1597 NeutronEvpnUtils.Operation.DELETE);
1599 boolean subnetVpnAssociation = false;
1600 if (vpnId != null && sn.getVpnId() != null
1601 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1602 subnetVpnAssociation = true;
1603 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1604 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1605 subnetVpnAssociation = true;
1607 if (subnetVpnAssociation == false) {
1608 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1609 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1612 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1613 List<Uuid> portList = sn.getPortList();
1614 final Uuid internetId = internetVpnId;
1615 if (portList != null) {
1616 for (final Uuid portId : portList) {
1617 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1618 final Port port = neutronvpnUtils.getNeutronPort(portId);
1619 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1620 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1621 List<ListenableFuture<Void>> futures = new ArrayList<>();
1623 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, wrtConfigTxn);
1625 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1626 + "port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1628 futures.add(wrtConfigTxn.submit());
1633 //update subnet-vpn association
1634 removeFromSubnetNode(subnet, null, null, vpnId, null);
1637 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1638 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1639 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1641 Uuid internalVpnId = sm.getVpnId();
1642 if (internalVpnId == null) {
1643 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1644 sm.getId().getValue());
1647 if (isBeingAssociated) {
1648 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1650 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1653 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1654 managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1655 if (isBeingAssociated) {
1656 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1657 true, true, wrtConfigTxn);
1659 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1665 // Check for ports on this subnet and update association of
1666 // corresponding vpn-interfaces to internet vpn
1667 List<Uuid> portList = sm.getPortList();
1668 if (portList != null) {
1669 for (Uuid port : portList) {
1670 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1671 port.getValue(), isBeingAssociated);
1672 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> {
1673 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1674 List<ListenableFuture<Void>> futures = new ArrayList<>();
1675 if (isBeingAssociated) {
1676 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1677 isBeingAssociated, false, wrtConfigTxn);
1679 removeVpnFromVpnInterface(vpn,
1680 neutronvpnUtils.getNeutronPort(port), wrtConfigTxn, sm);
1682 futures.add(wrtConfigTxn.submit());
1689 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1690 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1691 oldVpnId.getValue(), newVpnId.getValue());
1692 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1693 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1694 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1695 Uuid vpnExtUuid = netIsExternal ? null
1696 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1697 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1699 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1703 //Update Router Interface first synchronously.
1704 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1706 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1707 updateVpnInterface(newVpnId, oldVpnId,
1708 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1709 isBeingAssociated, true, wrtConfigTxn);
1710 wrtConfigTxn.submit().checkedGet();
1711 } catch (TransactionCommitFailedException e) {
1712 LOG.error("Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, returning",
1713 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId);
1717 // Check for ports on this subnet and update association of
1718 // corresponding vpn-interfaces to external vpn
1719 List<Uuid> portList = sn.getPortList();
1720 if (portList != null) {
1721 for (Uuid port : portList) {
1722 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1723 port.getValue(), isBeingAssociated);
1724 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> {
1725 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1726 List<ListenableFuture<Void>> futures = new ArrayList<>();
1727 updateVpnInterface(newVpnId, oldVpnId, neutronvpnUtils.getNeutronPort(port),
1728 isBeingAssociated, false, wrtConfigTxn);
1729 futures.add(wrtConfigTxn.submit());
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 List<Routes> routesError = new ArrayList();
1995 for (Routes route : routeList) {
1996 // count the number of nexthops for each same route.getDestingation().getValue()
1997 String destination = String.valueOf(route.getDestination().getValue());
1998 String nextHop = String.valueOf(route.getNexthop().getValue());
1999 List<String> nextHopList = new ArrayList();
2000 nextHopList.add(nextHop);
2002 for (Routes routeTmp : routeList) {
2003 String routeDest = String.valueOf(routeTmp.getDestination().getValue());
2004 if (!destination.equals(routeDest)) {
2007 String routeNextH = String.valueOf(routeTmp.getNexthop().getValue());
2008 if (nextHop.equals(routeNextH)) {
2012 nextHopList.add(new String(routeTmp.getNexthop().getValue()));
2014 final List<String> rdList = new ArrayList();
2015 if (vpnInstance.getIpv4Family() != null
2016 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2017 vpnInstance.getIpv4Family().getRouteDistinguisher().stream().forEach(rd -> {
2023 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2024 vpnInstance.getIpv6Family().getRouteDistinguisher().stream().forEach(rd -> {
2025 if (rd != null && !rdList.contains(rd)) {
2030 // 1. VPN Instance Name
2031 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2034 Uuid routerUuid = neutronvpnUtils.getRouterforVpn(vpnId);
2035 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2036 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2038 // 3. List of RDs associated with the VPN
2039 detailsAlarm.append(" List of RDs associated with the VPN: ");
2040 for (String s : rdList) {
2041 detailsAlarm.append(s);
2042 detailsAlarm.append(", ");
2045 // 4. Prefix in question
2046 detailsAlarm.append(" for prefix: ");
2047 detailsAlarm.append(route.getDestination().getValue());
2049 // 5. List of NHs for the prefix
2050 detailsAlarm.append(" for nextHops: ");
2051 for (String s : nextHopList) {
2052 detailsAlarm.append(s);
2053 detailsAlarm.append(", ");
2056 if (rdList.size() < nbNextHops) {
2057 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2058 LOG.error("there are too many next hops for prefixe in vpn {}", vpnId);
2059 routesError.add(route);
2061 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2064 //in routesError there are a few route raised in alarm, so they have not to be used
2065 routeList.removeAll(routesError);
2068 // TODO Clean up the exception handling
2069 @SuppressWarnings("checkstyle:IllegalCatch")
2070 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2071 for (Routes route : routeList) {
2072 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2073 boolean isLockAcquired = false;
2074 String nextHop = String.valueOf(route.getNexthop().getValue());
2075 String destination = String.valueOf(route.getDestination().getValue());
2076 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2078 if (infName == null) {
2079 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2080 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2081 // Proceed to remove the next extra-route
2084 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2085 destination, vpnId.getValue(), nextHop, infName);
2087 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2088 InstanceIdentifier.builder(VpnInterfaces.class)
2089 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2090 .augmentation(Adjacencies.class)
2091 .child(Adjacency.class, new AdjacencyKey(destination))
2095 // Looking for existing prefix in MDSAL database
2096 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2097 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2098 boolean updateNextHops = false;
2099 List<String> nextHopList = new ArrayList<>();
2100 if (adjacency.isPresent()) {
2101 List<String> nhListRead = adjacency.get().getNextHopIpList();
2102 if (nhListRead.size() > 1) { // ECMP case
2103 for (String nextHopRead : nhListRead) {
2104 if (nextHopRead.equals(nextHop)) {
2105 updateNextHops = true;
2107 nextHopList.add(nextHopRead);
2113 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2114 if (updateNextHops) {
2115 // An update must be done, not including the current next hop
2116 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2117 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2118 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2119 .setNextHopIpList(nextHopList)
2120 .setKey(new AdjacencyKey(destination))
2122 Adjacencies erAdjs =
2123 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2124 VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2125 .addAugmentation(Adjacencies.class, erAdjs).build();
2126 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2127 vpnIfIdentifier, vpnIf);
2129 // Remove the whole route
2130 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2131 adjacencyIdentifier);
2132 LOG.trace("extra route {} deleted successfully", route);
2134 } catch (TransactionCommitFailedException | ReadFailedException e) {
2135 LOG.error("exception in deleting extra route with destination {} for interface {}",
2136 destination, infName, e);
2138 if (isLockAcquired) {
2139 interfaceLock.unlock(infName);
2143 LOG.error("Incorrect input received for extra route: {}", route);
2148 public void removeVpn(Uuid id) {
2150 VpnMap vpnMap = neutronvpnUtils.getVpnMap(id);
2151 Uuid router = vpnMap != null ? vpnMap.getRouterId() : null;
2152 // dissociate router
2153 if (router != null) {
2154 dissociateRouterFromVpn(id, router);
2156 // dissociate networks
2157 if (!id.equals(router) && vpnMap.getNetworkIds() != null) {
2158 dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
2160 // remove entire vpnMaps node
2161 deleteVpnMapsNode(id);
2163 // remove vpn-instance
2164 deleteVpnInstance(id);
2167 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2168 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2171 // TODO Clean up the exception handling
2172 @SuppressWarnings("checkstyle:IllegalCatch")
2173 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2174 updateVpnMaps(vpnId, null, routerId, null, null);
2175 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2176 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2177 for (Uuid subnetId : routerSubnets) {
2178 Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
2179 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) {
2180 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2181 NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
2186 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2187 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2189 } catch (Exception e) {
2190 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2191 .getValue(), vpnId.getValue(), e);
2195 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2196 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2197 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2198 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2199 for (Uuid subnet : routerSubnets) {
2200 IpVersionChoice version = NeutronvpnUtils
2201 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2202 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2203 addSubnetToVpn(vpnId, subnet, null);
2205 addSubnetToVpn(vpnId, subnet, internetVpnId);
2210 // TODO Clean up the exception handling
2211 @SuppressWarnings("checkstyle:IllegalCatch")
2212 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2214 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2215 boolean vpnInstanceIpVersionsRemoved = false;
2216 IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
2217 for (Uuid subnetId : routerSubnets) {
2218 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
2219 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
2220 vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
2221 .getIpVersionFromString(sn.getSubnetIp()));
2222 vpnInstanceIpVersionsRemoved = true;
2224 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2225 updateVpnForSubnet(vpnId, routerId, subnetId, false);
2228 if (vpnInstanceIpVersionsRemoved) {
2229 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false);
2231 clearFromVpnMaps(vpnId, routerId, null);
2233 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2234 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2236 } catch (Exception e) {
2237 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2238 .getValue(), vpnId.getValue(), e);
2243 * Parses and associates networks list with given VPN.
2245 * @param vpnId Uuid of given VPN.
2246 * @param networks List list of network Ids (Uuid), which will be associated.
2247 * @return list of formatted strings with detailed error messages.
2250 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networks) {
2251 List<String> failedNwList = new ArrayList<>();
2252 HashSet<Uuid> passedNwList = new HashSet<>();
2253 if (networks.isEmpty()) {
2254 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2255 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2257 return failedNwList;
2259 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2260 if (vpnInstance == null) {
2261 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2262 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2263 + "in ConfigDS", vpnId.getValue()));
2264 return failedNwList;
2267 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2268 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2270 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2271 + "associated with", vpnId.getValue()));
2272 return failedNwList;
2274 for (Uuid nw : networks) {
2275 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2276 if (network == null) {
2277 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2278 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2282 NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
2283 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2284 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2285 nw.getValue(), vpnId.getValue());
2286 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2287 nw.getValue(), vpnId.getValue()));
2290 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2291 if (networkVpnId != null) {
2292 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2293 nw.getValue(), networkVpnId.getValue());
2294 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2295 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2298 if (neutronvpnUtils.getIsExternal(network)) {
2299 if (associateExtNetworkToVpn(vpnId, network)) {
2300 passedNwList.add(nw);
2303 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2304 nw.getValue(), vpnId.getValue());
2305 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2306 nw.getValue(), vpnId.getValue()));
2310 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2311 if (networkSubnets == null) {
2312 passedNwList.add(nw);
2315 for (Uuid subnet : networkSubnets) {
2316 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnet);
2317 if (subnetVpnId != null) {
2318 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {} as it is already "
2319 + "associated", subnet.getValue(), subnetVpnId.getValue());
2320 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s as it is already "
2321 + "associated", subnet.getValue(), vpnId.getValue()));
2324 Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
2325 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sm, vpnId)) {
2326 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2327 NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()), true);
2329 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnet.getValue(), vpnId.getValue());
2330 addSubnetToVpn(vpnId, subnet, null);
2331 passedNwList.add(nw);
2334 } catch (ReadFailedException e) {
2335 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2337 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2340 LOG.info("associateNetworksToVpn: update VPN {} with networks list: {}", vpnId.getValue(),
2341 passedNwList.toString());
2342 updateVpnMaps(vpnId, null, null, null, new ArrayList<Uuid>(passedNwList));
2343 return failedNwList;
2346 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2347 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2348 if (vpnOpDataEntry == null) {
2349 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2352 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2355 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2356 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2357 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2359 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2360 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2362 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2365 updateVpnInternetForSubnet(sm, vpnId, true);
2366 if (!(vpnOpDataEntry.isIpv6Configured())
2367 && (NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6)) {
2368 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2369 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true);
2376 * Parses and disassociates networks list from given VPN.
2378 * @param vpnId Uuid of given VPN.
2379 * @param networks List list of network Ids (Uuid), which will be disassociated.
2380 * @return list of formatted strings with detailed error messages.
2383 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networks) {
2384 List<String> failedNwList = new ArrayList<>();
2385 HashSet<Uuid> passedNwList = new HashSet<>();
2386 if (networks.isEmpty()) {
2387 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2388 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2390 return failedNwList;
2392 for (Uuid nw : networks) {
2393 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2394 if (network == null) {
2395 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2396 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2400 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2401 if (networkVpnId == null) {
2402 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2403 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2407 if (!vpnId.equals(networkVpnId)) {
2408 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2409 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2410 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2411 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2415 if (neutronvpnUtils.getIsExternal(network)) {
2416 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2417 passedNwList.add(nw);
2420 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2421 nw.getValue(), vpnId.getValue());
2422 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2427 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2428 if (networkSubnets == null) {
2429 passedNwList.add(nw);
2432 for (Uuid subnet : networkSubnets) {
2433 Subnetmap sm = neutronvpnUtils.getSubnetmap(subnet);
2434 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sm, vpnId)) {
2435 IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
2436 IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2437 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2438 ipVersionsToRemove.addVersion(ipVersion), false);
2440 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2442 removeSubnetFromVpn(vpnId, subnet, null);
2443 passedNwList.add(nw);
2446 LOG.info("dissociateNetworksFromVpn: Withdraw networks list {} from VPN {}", networks.toString(),
2448 clearFromVpnMaps(vpnId, null, new ArrayList<Uuid>(passedNwList));
2449 return failedNwList;
2452 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2453 if (!removeExternalNetworkFromVpn(extNet)) {
2456 // check, if there is another Provider Networks associated with given VPN
2457 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2458 if (vpnNets != null) {
2459 for (Uuid netId : vpnNets) {
2460 if (neutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2461 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2462 + "{}", vpnId.getValue(), netId.getValue());
2467 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2468 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2469 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2470 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2471 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2473 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2476 updateVpnInternetForSubnet(sm, vpnId, false);
2478 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2479 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue());
2480 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false);
2485 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2488 // TODO Clean up the exception handling
2489 @SuppressWarnings("checkstyle:IllegalCatch")
2490 public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2492 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2493 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2494 LOG.debug("associateNetworks {}", input);
2495 StringBuilder returnMsg = new StringBuilder();
2496 Uuid vpnId = input.getVpnId();
2499 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2500 List<Uuid> netIds = input.getNetworkId();
2501 if (netIds != null && !netIds.isEmpty()) {
2502 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2503 if (!failed.isEmpty()) {
2504 returnMsg.append(failed);
2508 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2510 if (returnMsg.length() != 0) {
2511 opBuilder.setResponse(
2512 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2513 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2514 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2516 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2518 } catch (Exception ex) {
2519 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2520 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2521 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2523 LOG.debug("associateNetworks returns..");
2528 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2531 // TODO Clean up the exception handling
2532 @SuppressWarnings("checkstyle:IllegalCatch")
2533 public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
2535 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
2536 LOG.debug("associateRouter {}", input);
2537 StringBuilder returnMsg = new StringBuilder();
2538 Uuid vpnId = input.getVpnId();
2539 Uuid routerId = input.getRouterId();
2541 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2542 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
2543 if (vpnMap != null) {
2545 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2546 if (vpnMap.getRouterId() != null) {
2547 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2548 .append(vpnMap.getRouterId().getValue());
2549 } else if (extVpnId != null) {
2550 returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
2551 + "another VPN ").append(extVpnId.getValue());
2553 associateRouterToVpn(vpnId, routerId);
2556 returnMsg.append("router not found : ").append(routerId.getValue());
2559 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2561 if (returnMsg.length() != 0) {
2562 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
2563 formatAndLog(LOG::error, "associate router to vpn {} failed due to {}", routerId.getValue(),
2564 returnMsg)).build());
2566 result.set(RpcResultBuilder.<Void>success().build());
2568 } catch (Exception ex) {
2569 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION,
2570 formatAndLog(LOG::error, "associate router {} to vpn {} failed due to {}", routerId.getValue(),
2571 vpnId.getValue(), ex.getMessage(), ex)).build());
2573 LOG.debug("associateRouter returns..");
2577 /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2580 // TODO Clean up the exception handling
2581 @SuppressWarnings("checkstyle:IllegalCatch")
2582 public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2583 GetFixedIPsForNeutronPortInput input) {
2584 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2585 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2586 Uuid portId = input.getPortId();
2587 StringBuilder returnMsg = new StringBuilder();
2589 List<String> fixedIPList = new ArrayList<>();
2590 Port port = neutronvpnUtils.getNeutronPort(portId);
2592 List<FixedIps> fixedIPs = port.getFixedIps();
2593 for (FixedIps ip : fixedIPs) {
2594 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
2597 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2599 if (returnMsg.length() != 0) {
2600 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2602 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2603 returnMsg)).build());
2605 opBuilder.setFixedIPs(fixedIPList);
2606 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2608 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2610 } catch (Exception ex) {
2611 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2612 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2613 portId.getValue(), ex.getMessage(), ex)).build());
2619 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2622 // TODO Clean up the exception handling
2623 @SuppressWarnings("checkstyle:IllegalCatch")
2624 public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2626 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2627 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2629 LOG.debug("dissociateNetworks {}", input);
2630 StringBuilder returnMsg = new StringBuilder();
2631 Uuid vpnId = input.getVpnId();
2634 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2635 List<Uuid> netIds = input.getNetworkId();
2636 if (netIds != null && !netIds.isEmpty()) {
2637 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2638 if (!failed.isEmpty()) {
2639 returnMsg.append(failed);
2643 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2645 if (returnMsg.length() != 0) {
2646 opBuilder.setResponse(
2647 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2648 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2649 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2651 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2653 } catch (Exception ex) {
2654 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2655 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2656 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2658 LOG.debug("dissociateNetworks returns..");
2663 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2666 // TODO Clean up the exception handling
2667 @SuppressWarnings("checkstyle:IllegalCatch")
2668 public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
2670 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
2672 LOG.debug("dissociateRouter {}", input);
2673 StringBuilder returnMsg = new StringBuilder();
2674 Uuid vpnId = input.getVpnId();
2675 Uuid routerId = input.getRouterId();
2677 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2678 if (routerId != null) {
2679 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
2681 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2682 if (vpnId.equals(routerVpnId)) {
2683 dissociateRouterFromVpn(vpnId, routerId);
2685 if (routerVpnId == null) {
2686 returnMsg.append("input router ").append(routerId.getValue())
2687 .append(" not associated to any vpn yet");
2689 returnMsg.append("input router ").append(routerId.getValue())
2690 .append(" associated to vpn ")
2691 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2695 returnMsg.append("router not found : ").append(routerId.getValue());
2699 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2701 if (returnMsg.length() != 0) {
2702 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
2703 formatAndLog(LOG::error, "dissociate router {} to vpn {} failed due to {}", routerId.getValue(),
2704 vpnId.getValue(), returnMsg)).build());
2706 result.set(RpcResultBuilder.<Void>success().build());
2708 } catch (Exception ex) {
2709 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION,
2710 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}", routerId.getValue(),
2711 vpnId.getValue(), ex.getMessage(), ex)).build());
2713 LOG.debug("dissociateRouter returns..");
2718 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2719 // check if the router is associated to some VPN
2720 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2721 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2722 if (vpnId != null) {
2723 // remove existing external vpn interfaces
2724 for (Uuid subnetId : routerSubnetIds) {
2725 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2727 clearFromVpnMaps(vpnId, routerId, null);
2729 // remove existing internal vpn interfaces
2730 for (Uuid subnetId : routerSubnetIds) {
2731 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2734 // delete entire vpnMaps node for internal VPN
2735 deleteVpnMapsNode(routerId);
2737 // delete vpn-instance for internal VPN
2738 deleteVpnInstance(routerId);
2741 protected Subnet getNeutronSubnet(Uuid subnetId) {
2742 return neutronvpnUtils.getNeutronSubnet(subnetId);
2745 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2746 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2748 return sn.getGatewayIp();
2754 protected Network getNeutronNetwork(Uuid networkId) {
2755 return neutronvpnUtils.getNeutronNetwork(networkId);
2758 protected Port getNeutronPort(String name) {
2759 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2762 protected Port getNeutronPort(Uuid portId) {
2763 return neutronvpnUtils.getNeutronPort(portId);
2766 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2767 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2770 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2771 return neutronvpnUtils.getNetworksForVpn(vpnId);
2775 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2777 * @return a List of String to be printed on screen
2778 * @throws ReadFailedException if there was a problem reading from the data store
2780 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2781 List<String> result = new ArrayList<>();
2782 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2784 result.add("-------------------------------------------------------------------------------------------");
2785 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2787 Optional<Ports> ports = syncReadOptional(dataBroker, CONFIGURATION, portidentifier);
2788 if (ports.isPresent() && ports.get().getPort() != null) {
2789 for (Port port : ports.get().getPort()) {
2790 List<FixedIps> fixedIPs = port.getFixedIps();
2791 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2792 List<String> ipList = new ArrayList<>();
2793 for (FixedIps fixedIp : fixedIPs) {
2794 IpAddress ipAddress = fixedIp.getIpAddress();
2795 if (ipAddress.getIpv4Address() != null) {
2796 ipList.add(ipAddress.getIpv4Address().getValue());
2798 ipList.add(ipAddress.getIpv6Address().getValue());
2801 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2802 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2803 ipList.toString()));
2805 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2806 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2815 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2817 * @param vpnuuid Uuid of the VPN whose config must be shown
2818 * @return formatted output list
2819 * @throws InterruptedException if there was a thread related problem getting the data to display
2820 * @throws ExecutionException if there was any other problem getting the data to display
2822 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2823 List<String> result = new ArrayList<>();
2824 if (vpnuuid == null) {
2826 result.add("Displaying VPN config for all VPNs");
2827 result.add("To display VPN config for a particular VPN, use the following syntax");
2828 result.add(getshowVpnConfigCLIHelp());
2830 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2831 if (rpcResult.isSuccessful()) {
2833 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2835 result.add(String.format(" %-80s ", "Import-RTs"));
2837 result.add(String.format(" %-80s ", "Export-RTs"));
2839 result.add(String.format(" %-76s ", "Subnet IDs"));
2841 result.add("------------------------------------------------------------------------------------");
2843 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2844 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2845 .rev150602.VpnInstance vpn : vpnList) {
2846 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2848 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2849 vpn.getRouteDistinguisher()));
2851 result.add(String.format(" %-80s ", vpn.getImportRT()));
2853 result.add(String.format(" %-80s ", vpn.getExportRT()));
2856 Uuid vpnid = vpn.getId();
2857 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
2858 if (!subnetList.isEmpty()) {
2859 for (Uuid subnetuuid : subnetList) {
2860 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2863 result.add(String.format(" %-76s ", "\" \""));
2866 result.add("----------------------------------------");
2870 String errortag = rpcResult.getErrors().iterator().next().getTag();
2871 if (Objects.equals(errortag, "")) {
2873 result.add("No VPN has been configured yet");
2874 } else if (Objects.equals(errortag, "invalid-value")) {
2876 result.add("VPN " + vpnuuid.getValue() + " is not present");
2878 result.add("error getting VPN info : " + rpcResult.getErrors());
2879 result.add(getshowVpnConfigCLIHelp());
2885 protected void createExternalVpnInterfaces(Uuid extNetId) {
2886 if (extNetId == null) {
2887 LOG.error("createExternalVpnInterfaces: external network is null");
2891 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2892 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2893 LOG.error("No external ports attached to external network {}", extNetId.getValue());
2897 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2898 for (String elanInterface : extElanInterfaces) {
2899 createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
2901 wrtConfigTxn.submit();
2904 // TODO Clean up the exception handling
2905 @SuppressWarnings("checkstyle:IllegalCatch")
2906 protected void removeExternalVpnInterfaces(Uuid extNetId) {
2907 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2908 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2909 LOG.error("No external ports attached for external network {}", extNetId.getValue());
2914 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2915 for (String elanInterface : extElanInterfaces) {
2916 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2917 .buildVpnInterfaceIdentifier(elanInterface);
2918 LOG.info("Removing vpn interface {}", elanInterface);
2919 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2921 wrtConfigTxn.submit();
2923 } catch (Exception ex) {
2924 LOG.error("Removal of vpninterfaces {} failed", extElanInterfaces, ex);
2928 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2929 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null,
2930 false /* not a router iface */, wrtConfigTxn);
2933 // TODO Clean up the exception handling
2934 @SuppressWarnings("checkstyle:IllegalCatch")
2935 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
2936 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2937 if (vpnIdList.isEmpty() || infName == null) {
2938 LOG.error("vpn id or interface is null");
2941 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
2942 for (Uuid vpnId: vpnIdList) {
2943 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
2944 AssociatedSubnetType.V4AndV6Subnets);
2945 vpnIdListStruct.add(vpnInstance);
2947 Boolean wrtConfigTxnPresent = true;
2948 if (wrtConfigTxn == null) {
2949 wrtConfigTxnPresent = false;
2950 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2953 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2954 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2956 .setVpnInstanceNames(vpnIdListStruct)
2957 .setRouterInterface(isRouterInterface);
2958 if (adjacencies != null) {
2959 vpnb.addAugmentation(Adjacencies.class, adjacencies);
2961 VpnInterface vpnIf = vpnb.build();
2963 LOG.info("Creating vpn interface {}", vpnIf);
2964 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2965 } catch (Exception ex) {
2966 LOG.error("Creation of vpninterface {} failed", infName, ex);
2969 if (!wrtConfigTxnPresent) {
2970 wrtConfigTxn.submit();
2974 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
2975 WriteTransaction wrtConfigTxn) {
2976 if (vpnId == null || infName == null) {
2977 LOG.error("vpn id or interface is null");
2981 if (wrtConfigTxn == null) {
2982 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2984 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2985 boolean isLockAcquired = false;
2987 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2988 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
2989 .syncReadOptional(dataBroker, LogicalDatastoreType
2990 .CONFIGURATION, vpnIfIdentifier);
2991 if (optionalVpnInterface.isPresent()) {
2992 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
2993 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
2995 if (adjacencies == null) {
2996 if (isLockAcquired) {
2997 interfaceLock.unlock(infName);
3001 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3002 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3003 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3004 optionalVpnInterface.get().getVpnInstanceNames());
3005 if (listVpnInstances.isEmpty() || !VpnHelper
3006 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),listVpnInstances)) {
3007 VpnInstanceNames vpnInstance = VpnHelper
3008 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3009 listVpnInstances.add(vpnInstance);
3010 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3013 VpnInstanceNames vpnInstance = VpnHelper
3014 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3015 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3016 listVpnInstances.add(vpnInstance);
3017 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3019 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3020 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder.build());
3022 } catch (IllegalStateException | ReadFailedException ex) {
3023 LOG.error("Update of vpninterface {} failed", infName, ex);
3025 if (isLockAcquired) {
3026 interfaceLock.unlock(infName);
3031 private String getshowVpnConfigCLIHelp() {
3032 StringBuilder help = new StringBuilder("Usage:");
3033 help.append("display vpn-config [-vid/--vpnid <id>]");
3034 return help.toString();
3037 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3038 InterruptedException {
3039 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3040 .setVpnId(vpnId).build();
3041 LOG.info("publishing notification upon association of router to VPN");
3042 notificationPublishService.putNotification(routerAssociatedToVpn);
3045 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3046 InterruptedException {
3047 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3048 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3049 LOG.info("publishing notification upon disassociation of router from VPN");
3050 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3053 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3054 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3058 public Future<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3059 return neutronEvpnManager.createEVPN(input);
3063 public Future<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3064 return neutronEvpnManager.getEVPN(input);
3068 public Future<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3069 return neutronEvpnManager.deleteEVPN(input);
3072 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3073 Uuid extNetId = extNet.getUuid();
3074 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3075 .child(Networks.class, new NetworksKey(extNetId)).build();
3078 Optional<Networks> optionalExtNets =
3079 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3081 if (!optionalExtNets.isPresent()) {
3082 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3083 extNetId.getValue());
3086 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3087 builder.setVpnid(vpnId);
3088 Networks networks = builder.build();
3089 // Add Networks object to the ExternalNetworks list
3090 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3091 extNetId.getValue());
3092 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3095 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3096 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3097 extNetId.getValue(), ex);
3102 private boolean removeExternalNetworkFromVpn(Network extNet) {
3103 Uuid extNetId = extNet.getUuid();
3104 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3105 .child(Networks.class, new NetworksKey(extNetId)).build();
3107 Optional<Networks> optionalNets =
3108 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3110 NetworksBuilder builder = null;
3111 if (optionalNets.isPresent()) {
3112 builder = new NetworksBuilder(optionalNets.get());
3114 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3115 extNetId.getValue());
3118 builder.setVpnid(null);
3119 Networks networks = builder.build();
3120 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3121 extNetId.getValue());
3122 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3124 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3125 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3126 extNetId.getValue(), ex);
3131 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3132 Optional<String> existingVpnName = Optional.of(primaryRd);
3133 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3135 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3136 .syncReadOptional(dataBroker, OPERATIONAL, neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3137 } catch (ReadFailedException e) {
3138 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3140 /*Read failed. We don't know if a VPN exists or not.
3141 * Return primaryRd to halt caller execution, to be safe.*/
3142 return existingVpnName;
3144 if (vpnInstanceOpDataOptional.isPresent()) {
3145 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3147 existingVpnName = Optional.absent();
3149 return existingVpnName;
3152 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3153 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3156 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3157 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3160 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3161 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3164 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3165 String message = tuple.getMessage();
3166 logger.accept(message);