2 * Copyright © 2015, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
12 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
13 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.JdkFutureAdapters;
20 import com.google.common.util.concurrent.ListenableFuture;
21 import com.google.common.util.concurrent.MoreExecutors;
22 import com.google.common.util.concurrent.SettableFuture;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.Map.Entry;
33 import java.util.Objects;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.function.Consumer;
40 import java.util.stream.Collectors;
41 import javax.annotation.Nonnull;
42 import javax.annotation.Nullable;
43 import javax.annotation.PreDestroy;
44 import javax.inject.Inject;
45 import javax.inject.Singleton;
46 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
47 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
48 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
49 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
50 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
51 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
52 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
55 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
56 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
57 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
58 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
59 import org.opendaylight.netvirt.elanmanager.api.IElanService;
60 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
61 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
62 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
63 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
64 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
65 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
66 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
177 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
178 import org.opendaylight.yangtools.yang.common.RpcError;
179 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
180 import org.opendaylight.yangtools.yang.common.RpcResult;
181 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
182 import org.slf4j.Logger;
183 import org.slf4j.LoggerFactory;
184 import org.slf4j.helpers.FormattingTuple;
185 import org.slf4j.helpers.MessageFormatter;
188 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
190 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
191 private static long LOCK_WAIT_TIME = 10L;
193 private final DataBroker dataBroker;
194 private final ManagedNewTransactionRunner txRunner;
195 private final NotificationPublishService notificationPublishService;
196 private final VpnRpcService vpnRpcService;
197 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
198 private final IElanService elanService;
199 private final NeutronvpnConfig neutronvpnConfig;
200 private final NeutronEvpnManager neutronEvpnManager;
201 private final NeutronEvpnUtils neutronEvpnUtils;
202 private final JobCoordinator jobCoordinator;
203 private final NeutronvpnUtils neutronvpnUtils;
204 private final IVpnManager vpnManager;
205 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
206 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
207 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
208 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
211 public NeutronvpnManager(
212 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
213 final VpnRpcService vpnRpcSrv, final IElanService elanService,
214 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
215 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
216 final JobCoordinator jobCoordinator, final NeutronvpnUtils neutronvpnUtils) {
217 this.dataBroker = dataBroker;
218 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
219 notificationPublishService = notiPublishService;
220 vpnRpcService = vpnRpcSrv;
221 this.elanService = elanService;
222 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
223 this.neutronvpnConfig = neutronvpnConfig;
224 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
225 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
226 this.jobCoordinator = jobCoordinator;
227 this.neutronvpnUtils = neutronvpnUtils;
228 this.vpnManager = vpnManager;
235 public void close() {
236 LOG.info("{} close", getClass().getSimpleName());
239 private void configureFeatures() {
240 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
241 Neutron.class).child(Features.class).child(
242 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
243 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
245 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
246 } catch (TransactionCommitFailedException e) {
247 LOG.warn("Error configuring feature {}", feature, e);
251 public String getOpenDaylightVniRangesConfig() {
252 return neutronvpnConfig.getOpendaylightVniRanges();
255 // TODO Clean up the exception handling
256 @SuppressWarnings("checkstyle:IllegalCatch")
257 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
258 NetworkAttributes.NetworkType networkType, long segmentationId) {
260 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
261 synchronized (subnetId.getValue().intern()) {
262 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
263 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
264 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
265 if (sn.isPresent()) {
266 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
267 subnetId.getValue());
270 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
271 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
272 .setNetworkType(networkType).setSegmentationId(segmentationId);
273 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
274 subnetId.getValue());
275 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
276 subnetMapIdentifier, subnetmapBuilder.build());
278 } catch (TransactionCommitFailedException | ReadFailedException e) {
279 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
281 // check if there are ports to update for already created Subnetmap node
282 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
283 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
284 if (entry.getValue().getValue().equals(subnetId.getValue())) {
285 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
286 unprocessedPortsMap.remove(entry.getKey());
291 protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId, Uuid internetvpnId) {
292 Subnetmap subnetmap = null;
293 SubnetmapBuilder builder = null;
294 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
295 .child(Subnetmap.class, new SubnetmapKey(subnetId))
298 synchronized (subnetId.getValue().intern()) {
299 Optional<Subnetmap> sn =
300 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
302 if (sn.isPresent()) {
303 builder = new SubnetmapBuilder(sn.get());
304 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
306 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
309 if (routerId != null) {
310 builder.setRouterId(routerId);
313 builder.setVpnId(vpnId);
315 builder.setInternetVpnId(internetvpnId);
317 subnetmap = builder.build();
318 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
319 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
321 } catch (ReadFailedException | TransactionCommitFailedException e) {
322 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
327 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
328 Uuid routerInterfacePortId, String fixedIp,
329 String routerIntfMacAddress, Uuid vpnId) {
330 Subnetmap subnetmap = null;
331 SubnetmapBuilder builder = null;
332 InstanceIdentifier<Subnetmap> id =
333 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
335 synchronized (subnetId.getValue().intern()) {
336 Optional<Subnetmap> sn =
337 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
339 if (sn.isPresent()) {
340 builder = new SubnetmapBuilder(sn.get());
341 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
342 subnetId.getValue());
344 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
345 subnetId.getValue());
348 builder.setRouterId(routerId);
349 builder.setRouterInterfacePortId(routerInterfacePortId);
350 builder.setRouterIntfMacAddress(routerIntfMacAddress);
351 builder.setRouterInterfaceFixedIp(fixedIp);
353 builder.setVpnId(vpnId);
355 subnetmap = builder.build();
356 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
357 subnetId.getValue());
358 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
360 } catch (ReadFailedException | TransactionCommitFailedException e) {
361 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
362 subnetId.getValue(), e);
366 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
367 Subnetmap subnetmap = null;
368 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
369 new SubnetmapKey(subnetId)).build();
370 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
372 synchronized (subnetId.getValue().intern()) {
373 Optional<Subnetmap> sn =
374 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
376 if (sn.isPresent()) {
377 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
378 if (null != portId) {
379 List<Uuid> portList = builder.getPortList();
380 if (null == portList) {
381 portList = new ArrayList<>();
383 portList.add(portId);
384 builder.setPortList(portList);
385 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
386 subnetId.getValue(), portId.getValue());
388 if (null != directPortId) {
389 List<Uuid> directPortList = builder.getDirectPortList();
390 if (null == directPortList) {
391 directPortList = new ArrayList<>();
393 directPortList.add(directPortId);
394 builder.setDirectPortList(directPortList);
395 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
396 directPortId.getValue());
398 subnetmap = builder.build();
399 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
402 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
403 + "cache ", subnetId.getValue(), portId.getValue());
404 unprocessedPortsMap.put(portId, subnetId);
407 } catch (ReadFailedException | TransactionCommitFailedException e) {
408 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
413 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId,
414 Uuid vpnId, Uuid portId) {
415 Subnetmap subnetmap = null;
416 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
417 .child(Subnetmap.class, new SubnetmapKey(subnetId))
420 synchronized (subnetId.getValue().intern()) {
421 Optional<Subnetmap> sn =
422 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
424 if (sn.isPresent()) {
425 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
426 if (routerId != null) {
427 builder.setRouterId(null);
429 if (networkId != null) {
430 builder.setNetworkId(null);
433 builder.setVpnId(null);
435 builder.setInternetVpnId(null);
436 if (portId != null && builder.getPortList() != null) {
437 List<Uuid> portList = builder.getPortList();
438 portList.remove(portId);
439 builder.setPortList(portList);
442 subnetmap = builder.build();
443 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
444 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
447 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
450 } catch (ReadFailedException | TransactionCommitFailedException e) {
451 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
456 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
457 Subnetmap subnetmap = null;
458 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
459 new SubnetmapKey(subnetId)).build();
461 synchronized (subnetId.getValue().intern()) {
462 Optional<Subnetmap> sn =
463 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
465 if (sn.isPresent()) {
466 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
467 if (null != portId && null != builder.getPortList()) {
468 List<Uuid> portList = builder.getPortList();
469 portList.remove(portId);
470 builder.setPortList(portList);
471 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
472 subnetId.getValue());
474 if (null != directPortId && null != builder.getDirectPortList()) {
475 List<Uuid> directPortList = builder.getDirectPortList();
476 directPortList.remove(directPortId);
477 builder.setDirectPortList(directPortList);
478 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
479 .getValue(), subnetId.getValue());
481 subnetmap = builder.build();
482 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
485 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
488 } catch (ReadFailedException | TransactionCommitFailedException e) {
489 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
490 subnetId.getValue(), e);
495 // TODO Clean up the exception handling
496 @SuppressWarnings("checkstyle:IllegalCatch")
497 protected void deleteSubnetMapNode(Uuid subnetId) {
498 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
499 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
500 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
502 synchronized (subnetId.getValue().intern()) {
503 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
504 subnetMapIdentifier);
506 } catch (TransactionCommitFailedException e) {
507 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
511 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
512 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
513 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
515 Optional<VpnInstance> vpnInstanceConfig =
516 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
518 if (!vpnInstanceConfig.isPresent()) {
519 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
522 VpnInstance vpnInstance = vpnInstanceConfig.get();
523 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
524 if (vpnInstance.getIpv4Family() != null) {
525 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
526 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
528 if (vpnInstance.getIpv6Family() != null) {
529 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
530 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
532 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
533 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
534 updateVpnInstanceBuilder.build());
535 } catch (ReadFailedException | TransactionCommitFailedException ex) {
536 LOG.warn("Error configuring feature ", ex);
540 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
541 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
542 String vpnName = vpnId.getValue();
543 VpnInstanceBuilder builder = null;
544 List<VpnTarget> vpnTargetList = new ArrayList<>();
545 boolean isLockAcquired = false;
546 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
547 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
549 Optional<VpnInstance> optionalVpn =
550 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
552 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
553 if (optionalVpn.isPresent()) {
554 builder = new VpnInstanceBuilder(optionalVpn.get());
555 LOG.debug("updating existing vpninstance node");
557 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
558 .setType(type).setL3vni(l3vni);
560 if (irt != null && !irt.isEmpty()) {
561 if (ert != null && !ert.isEmpty()) {
562 List<String> commonRT = new ArrayList<>(irt);
563 commonRT.retainAll(ert);
565 for (String common : commonRT) {
568 VpnTarget vpnTarget =
569 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
570 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
571 vpnTargetList.add(vpnTarget);
574 for (String importRT : irt) {
575 VpnTarget vpnTarget =
576 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
577 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
578 vpnTargetList.add(vpnTarget);
582 if (ert != null && !ert.isEmpty()) {
583 for (String exportRT : ert) {
584 VpnTarget vpnTarget =
585 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
586 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
587 vpnTargetList.add(vpnTarget);
591 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
593 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
594 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
596 if (rd != null && !rd.isEmpty()) {
597 ipv4vpnBuilder.setRouteDistinguisher(rd);
598 ipv6vpnBuilder.setRouteDistinguisher(rd);
601 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
602 builder.setIpv4Family(ipv4vpnBuilder.build());
604 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
605 builder.setIpv6Family(ipv6vpnBuilder.build());
607 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
608 builder.setIpv4Family(ipv4vpnBuilder.build());
610 VpnInstance newVpn = builder.build();
611 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
612 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
613 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
615 } catch (ReadFailedException | TransactionCommitFailedException e) {
616 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
618 if (isLockAcquired) {
619 vpnLock.unlock(vpnId);
624 private void deleteVpnMapsNode(Uuid vpnId) {
625 boolean isLockAcquired = false;
626 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
627 .child(VpnMap.class, new VpnMapKey(vpnId))
629 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
631 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
632 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
633 } catch (TransactionCommitFailedException e) {
634 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
636 if (isLockAcquired) {
637 vpnLock.unlock(vpnId);
642 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
643 VpnMapBuilder builder;
644 boolean isLockAcquired = false;
645 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
646 .child(VpnMap.class, new VpnMapKey(vpnId))
649 Optional<VpnMap> optionalVpnMap =
650 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
652 if (optionalVpnMap.isPresent()) {
653 builder = new VpnMapBuilder(optionalVpnMap.get());
655 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
659 builder.setName(name);
661 if (tenantId != null) {
662 builder.setTenantId(tenantId);
664 if (router != null) {
665 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
666 List<RouterIds> rtrIds = builder.getRouterIds();
667 if (rtrIds == null) {
668 rtrIds = Collections.singletonList(vpnRouterId);
670 rtrIds.add(vpnRouterId);
672 builder.setRouterIds(rtrIds);
674 if (networks != null) {
675 List<Uuid> nwList = builder.getNetworkIds();
676 if (nwList == null) {
677 nwList = new ArrayList<>();
679 nwList.addAll(networks);
680 builder.setNetworkIds(nwList);
683 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
684 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
685 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
687 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
688 } catch (ReadFailedException | TransactionCommitFailedException e) {
689 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
691 if (isLockAcquired) {
692 vpnLock.unlock(vpnId);
697 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
698 boolean isLockAcquired = false;
699 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
700 .child(VpnMap.class, new VpnMapKey(vpnId))
702 Optional<VpnMap> optionalVpnMap;
705 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
707 } catch (ReadFailedException e) {
708 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
711 if (optionalVpnMap.isPresent()) {
712 VpnMap vpnMap = optionalVpnMap.get();
713 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
714 List<RouterIds> rtrIds = vpnMap.getRouterIds();
715 if (rtrIds == null) {
716 rtrIds = new ArrayList<>();
718 if (routerId != null) {
719 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
720 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
721 vpnMapBuilder.setRouterIds(rtrIds);
723 // remove entire node in case of internal VPN
724 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
725 LOG.debug("removing vpnMaps node: {} ", vpnId);
726 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
728 } catch (TransactionCommitFailedException e) {
729 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
731 if (isLockAcquired) {
732 vpnLock.unlock(vpnId);
736 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
737 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
738 vpnMapBuilder.setRouterIds(rtrIds);
739 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
742 if (networkIds != null) {
743 List<Uuid> vpnNw = vpnMap.getNetworkIds();
744 vpnNw.removeAll(networkIds);
745 if (vpnNw.isEmpty()) {
746 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
747 vpnMapBuilder.setNetworkIds(null);
749 vpnMapBuilder.setNetworkIds(vpnNw);
754 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
755 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
756 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
757 vpnMapBuilder.build());
758 } catch (TransactionCommitFailedException e) {
759 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
761 if (isLockAcquired) {
762 vpnLock.unlock(vpnId);
766 LOG.error("VPN : {} not found", vpnId.getValue());
768 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
771 private void deleteVpnInstance(Uuid vpnId) {
772 boolean isLockAcquired = false;
773 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
774 .child(VpnInstance.class,
775 new VpnInstanceKey(vpnId.getValue()))
778 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
779 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
780 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
781 } catch (TransactionCommitFailedException e) {
782 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
784 if (isLockAcquired) {
785 vpnLock.unlock(vpnId);
790 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
791 WriteTransaction wrtConfigTxn, Subnetmap sn, VpnInterface vpnIface) {
792 List<Adjacency> adjList = new ArrayList<>();
793 if (vpnIface != null) {
794 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
796 String infName = port.getUuid().getValue();
797 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
798 for (FixedIps ip : port.getFixedIps()) {
799 String ipValue = String.valueOf(ip.getIpAddress().getValue());
800 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
801 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
804 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
805 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
807 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
808 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
809 //Create Neutron port adjacency if VPN presence is existing for subnet
810 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
811 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
812 .setSubnetId(ip.getSubnetId()).build();
813 if (!adjList.contains(vmAdj)) {
817 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
818 if (snTemp != null && snTemp.getInternetVpnId() != null) {
819 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
820 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
822 if (routerId != null) {
823 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
824 if (rtr != null && rtr.getRoutes() != null) {
825 List<Routes> routeList = rtr.getRoutes();
826 // create extraroute Adjacence for each ipValue,
827 // because router can have IPv4 and IPv6 subnet ports, or can have
828 // more that one IPv4 subnet port or more than one IPv6 subnet port
829 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
830 if (!erAdjList.isEmpty()) {
831 adjList.addAll(erAdjList);
836 return new AdjacenciesBuilder().setAdjacency(adjList).build();
839 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port, WriteTransaction wrtConfigTxn) {
840 boolean isRouterInterface = false;
841 if (port.getDeviceOwner() != null) {
842 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
844 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
845 String infName = port.getUuid().getValue();
846 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
847 writeVpnInterfaceToDs(vpnIds, infName, adjs, isRouterInterface, wrtConfigTxn);
850 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
851 Port port, Subnetmap sn, WriteTransaction wrtConfigTxn) {
852 String infName = port.getUuid().getValue();
853 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
854 Optional<VpnInterface> optionalVpnInterface = null;
855 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
856 vpnId, internetVpnId, infName);
858 optionalVpnInterface = SingleTransactionDataBroker
859 .syncReadOptional(dataBroker, LogicalDatastoreType
860 .CONFIGURATION, vpnIfIdentifier);
861 } catch (ReadFailedException e) {
862 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
865 if (!optionalVpnInterface.isPresent()) {
868 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
869 sn != null ? sn.getSubnetIp() : "null");
870 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency();
871 List<Adjacency> updatedAdjsList = new ArrayList<>();
872 boolean isIpFromAnotherSubnet = false;
873 for (Adjacency adj : vpnAdjsList) {
874 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
875 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
876 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
877 isIpFromAnotherSubnet = true;
879 updatedAdjsList.add(adj);
882 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
883 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
886 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
887 String.valueOf(adjString), wrtConfigTxn);
889 if (internetVpnId != null) {
890 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
891 String.valueOf(adjString), wrtConfigTxn);
894 if (port.getDeviceOwner()
895 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
896 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
897 if (rtr != null && rtr.getRoutes() != null) {
898 List<Routes> extraRoutesToRemove = new ArrayList<>();
899 for (Routes rt: rtr.getRoutes()) {
900 if (rt.getNexthop().toString().equals(adjString)) {
901 extraRoutesToRemove.add(rt);
905 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
906 extraRoutesToRemove, vpnId);
907 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
909 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
914 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
916 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
918 if (internetVpnId != null) {
919 updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn);
921 if (!isIpFromAnotherSubnet) {
922 // no more subnetworks for neutron port
923 if (sn != null && sn.getRouterId() != null) {
924 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
926 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
932 // TODO Clean up the exception handling
933 @SuppressWarnings("checkstyle:IllegalCatch")
934 protected void deleteVpnInterface(String infName, @Nullable String vpnId, WriteTransaction wrtConfigTxn) {
935 if (wrtConfigTxn == null) {
936 ListenableFutures.addErrorLogging(
937 txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> deleteVpnInterface(infName, vpnId, tx)),
938 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
942 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
943 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
944 Optional<VpnInterface> optionalVpnInterface;
946 optionalVpnInterface =
947 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
949 } catch (ReadFailedException ex) {
950 LOG.error("Error during deletion of vpninterface {}", infName, ex);
953 if (!optionalVpnInterface.isPresent()) {
954 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
958 VpnInterface vpnInterface = optionalVpnInterface.get();
959 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
961 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
962 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
963 if (!vpnList.isEmpty()) {
964 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
965 + "List not empty", infName);
968 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
969 .setVpnInstanceNames(vpnList);
970 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
974 LOG.debug("Deleting vpn interface {}", infName);
975 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
978 protected void removeVpnFromVpnInterface(Uuid vpnId, Port port,
979 WriteTransaction writeConfigTxn, Subnetmap sm) {
980 if (vpnId == null || port == null) {
983 String infName = port.getUuid().getValue();
984 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
986 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
987 .syncReadOptional(dataBroker, LogicalDatastoreType
988 .CONFIGURATION, vpnIfIdentifier);
989 if (optionalVpnInterface.isPresent()) {
990 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
992 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
993 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
995 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
996 .setVpnInstanceNames(listVpn);
997 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
998 LOG.debug("Updating vpn interface {}", infName);
999 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1000 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1001 while (adjacencyIter.hasNext()) {
1002 Adjacency adjacency = adjacencyIter.next();
1003 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1006 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1007 InstanceIdentifier<LearntVpnVipToPort> id =
1008 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1009 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1010 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1011 LogicalDatastoreType.OPERATIONAL, id);
1012 if (optionalVpnVipToPort.isPresent()) {
1013 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1015 if (listVpn == null || listVpn.isEmpty()) {
1016 adjacencyIter.remove();
1018 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1019 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1020 mipToQuery, infName, vpnId.getValue());
1023 List<FixedIps> ips = port.getFixedIps();
1024 for (FixedIps ip : ips) {
1025 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1026 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1027 ipValue, writeConfigTxn);
1029 if (listVpn == null || listVpn.isEmpty()) {
1030 if (sm != null && sm.getRouterId() != null) {
1031 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1033 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1035 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1039 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1041 } catch (ReadFailedException ex) {
1042 LOG.error("Update of vpninterface {} failed", infName, ex);
1046 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
1047 boolean isSubnetIp, WriteTransaction writeConfigTxn) {
1048 if (vpnId == null || port == null) {
1051 boolean isLockAcquired = false;
1052 String infName = port.getUuid().getValue();
1053 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1056 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1057 Optional<VpnInterface> optionalVpnInterface =
1058 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1060 if (optionalVpnInterface.isPresent()) {
1061 VpnInstanceNames vpnInstance = VpnHelper
1062 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1063 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1064 .get().getVpnInstanceNames());
1065 if (oldVpnId != null
1066 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1067 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1069 if (vpnId.getValue() != null
1070 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1071 listVpn.add(vpnInstance);
1073 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1074 .setVpnInstanceNames(listVpn);
1075 LOG.debug("Updating vpn interface {}", infName);
1076 if (!isBeingAssociated) {
1077 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1078 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1079 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1080 while (adjacencyIter.hasNext()) {
1081 Adjacency adjacency = adjacencyIter.next();
1082 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1083 InstanceIdentifier<LearntVpnVipToPort> id =
1084 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1085 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1086 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1087 LogicalDatastoreType.OPERATIONAL, id);
1088 if (optionalVpnVipToPort.isPresent()) {
1089 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1090 + "from VPN {}", infName, vpnId, oldVpnId);
1091 adjacencyIter.remove();
1092 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1094 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1095 mipToQuery, infName, vpnId.getValue());
1098 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1099 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1101 List<FixedIps> ips = port.getFixedIps();
1102 for (FixedIps ip : ips) {
1103 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1104 if (oldVpnId != null) {
1105 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1106 ipValue, writeConfigTxn);
1108 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1109 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1111 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
1114 LOG.error("VPN Interface {} not found", infName);
1116 } catch (ReadFailedException ex) {
1117 LOG.error("Updation of vpninterface {} failed", infName, ex);
1119 if (isLockAcquired) {
1120 interfaceLock.unlock(infName);
1125 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
1126 List<String> ert, Uuid router, List<Uuid> networks) {
1128 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1130 // Update VPN Instance node
1131 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1133 // Update local vpn-subnet DS
1134 updateVpnMaps(vpn, name, router, tenant, networks);
1136 if (router != null) {
1137 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1138 if (existingVpn != null) {
1139 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1140 // if before reboot, router was already associated to VPN, should not proceed associating router to
1141 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1142 // preserved upon reboot.
1143 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1144 // RouterInterfacesMap via #createVPNInterface call.
1145 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1146 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1149 associateRouterToInternalVpn(vpn, router);
1154 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1155 * specified Neutron Networks and Routers.
1157 * @param vpnId Uuid of the VPN tp be created
1158 * @param name Representative name of the new VPN
1159 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1160 * @param rdList Route-distinguisher for the VPN
1161 * @param irtList A list of Import Route Targets
1162 * @param ertList A list of Export Route Targets
1163 * @param routerIdsList ist of neutron router Id to associate with created VPN
1164 * @param networkList UUID of the neutron network the VPN may be associated to
1165 * @param type Type of the VPN Instance
1166 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1167 * @throws Exception if association of L3VPN failed
1169 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1170 List<String> ertList, @Nullable List<Uuid> routerIdsList, List<Uuid> networkList,
1171 VpnInstance.Type type, long l3vni) throws Exception {
1173 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1175 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1176 for (Uuid routerId : routerIdsList) {
1177 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1178 ipVersChoices = ipVersChoices.addVersion(vers);
1181 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1183 // Please note that router and networks will be filled into VPNMaps
1184 // by subsequent calls here to associateRouterToVpn and
1185 // associateNetworksToVpn
1186 updateVpnMaps(vpnId, name, null, tenantId, null);
1187 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1188 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1191 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1192 for (Uuid routerId : routerIdsList) {
1193 associateRouterToVpn(vpnId, routerId);
1196 if (networkList != null) {
1197 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1198 if (!failStrings.isEmpty()) {
1199 LOG.error("VPN {} association to networks failed for networks: {}. ",
1200 vpnId.getValue(), failStrings.toString());
1201 throw new Exception(failStrings.toString());
1207 * It handles the invocations to the createVPN RPC method.
1210 // TODO Clean up the exception handling
1211 @SuppressWarnings("checkstyle:IllegalCatch")
1212 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1214 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1215 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1216 List<RpcError> errorList = new ArrayList<>();
1217 int failurecount = 0;
1218 int warningcount = 0;
1220 List<L3vpn> vpns = input.getL3vpn();
1222 vpns = Collections.emptyList();
1224 for (L3vpn vpn : vpns) {
1225 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1226 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1227 formatAndLog(LOG::warn,
1228 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1229 vpn.getId().getValue())));
1233 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1234 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1235 formatAndLog(LOG::warn,
1236 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1237 vpn.getId().getValue())));
1241 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1243 if (vpn.getL3vni() != null) {
1244 l3vni = vpn.getL3vni();
1247 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1248 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1249 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1250 formatAndLog(LOG::warn,
1251 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1252 + "is already configured",
1253 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1257 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1258 if (operationalVpn.isPresent()) {
1259 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1260 formatAndLog(LOG::error,
1261 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1262 + "is still available. Please retry creation of a new vpn with the same RD"
1263 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1264 vpn.getRouteDistinguisher().get(0))));
1268 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1269 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1270 routerIdsList = vpn.getRouterIds();
1271 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1272 routerId : routerIdsList) {
1273 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1274 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1275 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1276 + "{}", vpn.getId(), routerId.getRouterId())));
1280 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1281 if (vpnId != null) {
1282 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1283 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1284 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1285 vpnId.getValue())));
1291 if (vpn.getNetworkIds() != null) {
1292 int initialWarningCount = warningcount;
1293 for (Uuid nw : vpn.getNetworkIds()) {
1294 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1295 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1296 if (network == null) {
1297 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1298 formatAndLog(LOG::warn,
1299 "Creation of L3VPN failed for VPN {} due to network not found {}",
1300 vpn.getId().getValue(), nw.getValue())));
1302 } else if (vpnId != null) {
1303 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1304 formatAndLog(LOG::warn,
1305 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1306 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1307 vpnId.getValue())));
1311 if (warningcount != initialWarningCount) {
1315 List<Uuid> rtrIdsList = new ArrayList<>();
1316 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1317 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1318 rtrId : vpn.getRouterIds()) {
1319 rtrIdsList.add(rtrId.getRouterId());
1323 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1324 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1325 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1326 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1327 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1328 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1329 vpnInstanceType, l3vni);
1330 } catch (Exception ex) {
1331 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1332 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1337 // if at least one succeeds; result is success
1338 // if none succeeds; result is failure
1339 if (failurecount + warningcount == vpns.size()) {
1340 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1342 List<String> errorResponseList = new ArrayList<>();
1343 if (!errorList.isEmpty()) {
1344 for (RpcError rpcError : errorList) {
1345 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1346 + ", ErrorMessage: " + rpcError.getMessage());
1349 errorResponseList.add("Operation successful with no errors");
1351 opBuilder.setResponse(errorResponseList);
1352 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1358 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1361 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1363 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1364 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1365 Uuid inputVpnId = input.getId();
1366 List<VpnInstance> vpns = new ArrayList<>();
1367 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1370 if (inputVpnId == null) {
1372 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1374 Optional<VpnInstances> optionalVpns =
1375 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1377 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1378 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1379 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1380 // from getL3VPN output
1381 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1384 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1390 opBuilder.setL3vpnInstances(l3vpnList);
1391 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1395 String name = inputVpnId.getValue();
1396 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1397 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1398 // read VpnInstance Info
1399 Optional<VpnInstance> optionalVpn =
1400 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1402 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1404 if (optionalVpn.isPresent() && (optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null)
1405 || (optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
1406 vpns.add(optionalVpn.get());
1409 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1410 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1414 for (VpnInstance vpnInstance : vpns) {
1415 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1416 // create VpnMaps id
1417 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1418 List<String> rd = Collections.EMPTY_LIST;
1419 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1420 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1421 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1422 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1424 List<String> ertList = new ArrayList<>();
1425 List<String> irtList = new ArrayList<>();
1427 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1428 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1429 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1430 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1431 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1432 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1433 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1435 if (!vpnTargetList.isEmpty()) {
1436 for (VpnTarget vpnTarget : vpnTargetList) {
1437 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1438 ertList.add(vpnTarget.getVrfRTValue());
1440 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1441 irtList.add(vpnTarget.getVrfRTValue());
1443 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1444 ertList.add(vpnTarget.getVrfRTValue());
1445 irtList.add(vpnTarget.getVrfRTValue());
1451 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1453 if (vpnInstance.getL3vni() != null) {
1454 l3vpn.setL3vni(vpnInstance.getL3vni());
1456 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1457 .class, new VpnMapKey(vpnId)).build();
1458 Optional<VpnMap> optionalVpnMap =
1459 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1461 if (optionalVpnMap.isPresent()) {
1462 VpnMap vpnMap = optionalVpnMap.get();
1463 List<Uuid> rtrIds = new ArrayList<>();
1464 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1465 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1466 rtrIds.add(rtrId.getRouterId());
1469 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1470 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1471 .setName(vpnMap.getName());
1474 l3vpnList.add(l3vpn.build());
1477 opBuilder.setL3vpnInstances(l3vpnList);
1478 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1480 } catch (ReadFailedException ex) {
1481 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1482 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1488 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1491 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1493 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1494 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1495 List<RpcError> errorList = new ArrayList<>();
1497 int failurecount = 0;
1498 int warningcount = 0;
1499 List<Uuid> vpns = input.getId();
1500 for (Uuid vpn : vpns) {
1504 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1505 InstanceIdentifier<VpnInstance> vpnIdentifier =
1506 InstanceIdentifier.builder(VpnInstances.class)
1507 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1508 Optional<VpnInstance> optionalVpn =
1509 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1511 if (optionalVpn.isPresent()) {
1514 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1515 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1518 } catch (ReadFailedException ex) {
1519 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1520 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1525 // if at least one succeeds; result is success
1526 // if none succeeds; result is failure
1527 if (failurecount + warningcount == vpns.size()) {
1528 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1530 List<String> errorResponseList = new ArrayList<>();
1531 if (!errorList.isEmpty()) {
1532 for (RpcError rpcError : errorList) {
1533 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1534 + ", ErrorMessage: " + rpcError.getMessage());
1537 errorResponseList.add("Operation successful with no errors");
1539 opBuilder.setResponse(errorResponseList);
1540 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1545 public void createVpnInstanceForSubnet(Uuid subnetId) {
1546 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1547 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1550 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1551 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1552 removeVpn(subnetId);
1555 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1556 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1557 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1558 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1560 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1561 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1564 if (vpnId != null) {
1565 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1566 if (vpnMap == null) {
1567 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1568 + " cannot add subnet {} to VPN", vpnId.getValue(),
1572 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1573 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1574 if (isVpnOfTypeL2(vpnInstance)) {
1575 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1576 NeutronEvpnUtils.Operation.ADD);
1579 if (internetVpnId != null) {
1580 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1581 if (vpnMap == null) {
1582 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1583 + "subnet {} to VPN", internetVpnId.getValue(),
1588 final Uuid internetId = internetVpnId;
1589 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1590 List<Uuid> portList = sn.getPortList();
1591 if (portList != null) {
1592 for (final Uuid portId : portList) {
1593 String vpnInfName = portId.getValue();
1594 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1595 Port port = neutronvpnUtils.getNeutronPort(portId);
1597 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1598 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1601 final Boolean isRouterInterface = port.getDeviceOwner()
1602 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1603 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1604 txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1605 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1607 if (vpnIface == null) {
1608 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1609 Set<Uuid> listVpn = new HashSet<>();
1610 if (vpnId != null) {
1613 if (internetId != null) {
1614 listVpn.add(internetId);
1616 writeVpnInterfaceToDs(listVpn,
1617 vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
1618 if (sn.getRouterId() != null) {
1619 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1622 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1623 if (vpnId != null) {
1624 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1626 if (internetId != null) {
1627 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1636 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) {
1637 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1638 "removeSubnetFromVpn: at least one VPN must be not null");
1639 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1640 vpnId, internetVpnId);
1641 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1643 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1646 VpnMap vpnMap = null;
1647 VpnInstance vpnInstance = null;
1648 if (vpnId != null) {
1649 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1650 if (vpnMap == null) {
1651 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1652 vpnId.getValue(), subnet.getValue());
1655 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1657 if (internetVpnId == null) {
1658 internetVpnId = sn.getInternetVpnId();
1660 if (internetVpnId != null) {
1661 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1662 if (vpnMap == null) {
1663 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1664 + " from Internet VPN",
1665 internetVpnId.getValue(), subnet.getValue());
1669 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1670 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1671 NeutronEvpnUtils.Operation.DELETE);
1673 boolean subnetVpnAssociation = false;
1674 if (vpnId != null && sn.getVpnId() != null
1675 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1676 subnetVpnAssociation = true;
1677 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1678 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1679 subnetVpnAssociation = true;
1681 if (subnetVpnAssociation == false) {
1682 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1683 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1686 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1687 List<Uuid> portList = sn.getPortList();
1688 final Uuid internetId = internetVpnId;
1689 if (portList != null) {
1690 for (final Uuid portId : portList) {
1691 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1692 final Port port = neutronvpnUtils.getNeutronPort(portId);
1693 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1694 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1696 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1699 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1700 + "port is absent in Neutron config DS", portId.getValue(),
1706 //update subnet-vpn association
1707 removeFromSubnetNode(subnet, null, null, vpnId, null);
1710 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1711 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1712 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1714 Uuid internalVpnId = sm.getVpnId();
1715 if (internalVpnId == null) {
1716 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1717 sm.getId().getValue());
1720 if (isBeingAssociated) {
1721 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1723 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1726 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1727 txRunner.callWithNewWriteOnlyTransactionAndSubmit(wrtConfigTxn -> {
1728 if (isBeingAssociated) {
1729 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1730 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn);
1732 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1738 // Check for ports on this subnet and update association of
1739 // corresponding vpn-interfaces to internet vpn
1740 List<Uuid> portList = sm.getPortList();
1741 if (portList != null) {
1742 for (Uuid port : portList) {
1743 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1744 port.getValue(), isBeingAssociated);
1745 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1746 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1747 if (isBeingAssociated) {
1748 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1751 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1758 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1759 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1760 oldVpnId.getValue(), newVpnId.getValue());
1761 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1762 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1763 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1764 Uuid vpnExtUuid = netIsExternal ? null
1765 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1766 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1768 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1772 //Update Router Interface first synchronously.
1773 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1774 ListenableFuture<Void> future =
1775 txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> updateVpnInterface(newVpnId, oldVpnId,
1776 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1777 isBeingAssociated, true, tx));
1778 Futures.addCallback(future, new FutureCallback<Void>() {
1780 public void onSuccess(Void result) {
1781 // Check for ports on this subnet and update association of
1782 // corresponding vpn-interfaces to external vpn
1783 List<Uuid> portList = sn.getPortList();
1784 if (portList != null) {
1785 for (Uuid port : portList) {
1786 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1787 port.getValue(), isBeingAssociated);
1788 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1789 txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1790 tx -> updateVpnInterface(newVpnId, oldVpnId,
1791 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1798 public void onFailure(Throwable throwable) {
1800 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1802 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1804 }, MoreExecutors.directExecutor());
1809 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1810 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1811 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1814 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1815 synchronized (routerId.getValue().intern()) {
1816 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1818 Optional<RouterInterfaces> optRouterInterfaces =
1819 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1820 routerInterfacesId);
1821 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1822 .setInterfaceId(interfaceName).build();
1823 if (optRouterInterfaces.isPresent()) {
1824 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1825 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1828 // TODO Shouldn't we be doing something with builder and interfaces?
1829 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1830 // List<Interfaces> interfaces = new ArrayList<>();
1831 // interfaces.add(routerInterface);
1833 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1834 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1837 } catch (ReadFailedException | TransactionCommitFailedException e) {
1838 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1843 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1844 synchronized (routerId.getValue().intern()) {
1845 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1847 Optional<RouterInterfaces> optRouterInterfaces =
1848 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1849 routerInterfacesId);
1850 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1851 .setInterfaceId(interfaceName).build();
1852 if (optRouterInterfaces.isPresent()) {
1853 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1854 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1855 if (interfaces != null && interfaces.remove(routerInterface)) {
1856 if (interfaces.isEmpty()) {
1857 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1858 routerInterfacesId);
1860 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1861 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1865 } catch (ReadFailedException | TransactionCommitFailedException e) {
1866 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1872 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1873 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1874 * route will be ignored.
1876 * @param vpnName the VPN identifier
1877 * @param interVpnLinkRoutes The list of static routes
1878 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1880 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1881 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1882 for (Routes route : interVpnLinkRoutes) {
1883 String nexthop = String.valueOf(route.getNexthop().getValue());
1884 String destination = String.valueOf(route.getDestination().getValue());
1885 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1886 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1887 AddStaticRouteInput rpcInput =
1888 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1889 .setVpnInstanceName(vpnName.getValue())
1891 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1892 RpcResult<AddStaticRouteOutput> rpcResult;
1894 rpcResult = labelOuputFtr.get();
1895 if (rpcResult.isSuccessful()) {
1896 LOG.debug("Label generated for destination {} is: {}",
1897 destination, rpcResult.getResult().getLabel());
1899 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1900 destination, nexthop, rpcResult.getErrors());
1902 } catch (InterruptedException | ExecutionException e) {
1903 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1904 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1907 // Any other case is a fault.
1908 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1909 String.valueOf(route.getDestination().getValue()), nexthop);
1916 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1917 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1919 * @param vpnName the VPN identifier
1920 * @param interVpnLinkRoutes The list of static routes
1921 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1923 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1924 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1925 for (Routes route : interVpnLinkRoutes) {
1926 String nexthop = String.valueOf(route.getNexthop().getValue());
1927 String destination = String.valueOf(route.getDestination().getValue());
1928 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1929 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1930 RemoveStaticRouteInput rpcInput =
1931 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1932 .setVpnInstanceName(vpnName.getValue())
1935 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1936 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1938 // Any other case is a fault.
1939 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1940 String.valueOf(route.getDestination().getValue()), nexthop);
1947 * Returns true if the specified nexthop is the other endpoint in an
1948 * InterVpnLink, regarding one of the VPN's point of view.
1950 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1952 interVpnLink != null
1953 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1954 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1955 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1956 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1960 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
1961 List<Adjacency> adjList = new ArrayList<>();
1962 Map<String, List<String>> adjMap = new HashMap<>();
1963 for (Routes route : routeList) {
1964 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1965 LOG.error("Incorrect input received for extra route. {}", route);
1967 String nextHop = String.valueOf(route.getNexthop().getValue());
1968 String destination = String.valueOf(route.getDestination().getValue());
1969 if (!nextHop.equals(fixedIp)) {
1970 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1973 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
1975 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1976 if (!hops.contains(nextHop)) {
1982 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
1983 final String destination = entry.getKey();
1984 final List<String> ipList = entry.getValue();
1985 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1986 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
1987 .withKey(new AdjacencyKey(destination)).build();
1993 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1994 checkAlarmExtraRoutes(vpnId, routeList);
1996 for (Routes route : routeList) {
1997 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1998 LOG.error("Incorrect input received for extra route. {}", route);
2000 String nextHop = String.valueOf(route.getNexthop().getValue());
2001 String destination = String.valueOf(route.getDestination().getValue());
2002 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2004 if (infName != null) {
2005 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2006 destination, vpnId.getValue(), nextHop, infName);
2007 boolean isLockAcquired = false;
2009 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2010 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2011 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2012 .child(Adjacency.class, new AdjacencyKey(destination));
2013 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2014 LogicalDatastoreType.CONFIGURATION, path);
2015 if (existingAdjacency.isPresent()
2016 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2017 LOG.error("The route with destination {} nextHop {} is already present as"
2018 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2019 destination, nextHop, infName);
2022 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2023 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2024 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2025 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2026 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2028 } catch (TransactionCommitFailedException e) {
2029 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2030 destination, nextHop, e);
2031 } catch (ReadFailedException e) {
2032 LOG.error("Exception on reading data-store ", e);
2034 if (isLockAcquired) {
2035 interfaceLock.unlock(infName);
2039 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2040 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2047 * This method setup or down an alarm about extra route fault.
2048 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2049 * available RDs, then an alarm and an error is generated.<br>
2050 * <b>Be careful</b> the routeList could be changed.
2052 * @param vpnId the vpnId of vpn to control.
2053 * @param routeList the list of router to check, it could be modified.
2055 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2056 if (!neutronvpnAlarm.isAlarmEnabled()) {
2057 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2060 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2061 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2062 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2066 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2067 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2068 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2072 for (Routes route : routeList) {
2073 // count the number of nexthops for each same route.getDestingation().getValue()
2074 String destination = String.valueOf(route.getDestination().getValue());
2075 String nextHop = String.valueOf(route.getNexthop().getValue());
2076 List<String> nextHopList = new ArrayList();
2077 nextHopList.add(nextHop);
2079 for (Routes routeTmp : routeList) {
2080 String routeDest = String.valueOf(routeTmp.getDestination().getValue());
2081 if (!destination.equals(routeDest)) {
2084 String routeNextH = String.valueOf(routeTmp.getNexthop().getValue());
2085 if (nextHop.equals(routeNextH)) {
2089 nextHopList.add(new String(routeTmp.getNexthop().getValue()));
2091 final List<String> rdList = new ArrayList<>();
2092 if (vpnInstance.getIpv4Family() != null
2093 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2094 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2100 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2101 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2102 if (rd != null && !rdList.contains(rd)) {
2107 // 1. VPN Instance Name
2108 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2111 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2112 Uuid routerUuid = routerUuidList.get(0);
2113 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2114 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2116 // 3. List of RDs associated with the VPN
2117 detailsAlarm.append(" List of RDs associated with the VPN: ");
2118 for (String s : rdList) {
2119 detailsAlarm.append(s);
2120 detailsAlarm.append(", ");
2123 // 4. Prefix in question
2124 detailsAlarm.append(" for prefix: ");
2125 detailsAlarm.append(route.getDestination().getValue());
2127 // 5. List of NHs for the prefix
2128 detailsAlarm.append(" for nextHops: ");
2129 for (String s : nextHopList) {
2130 detailsAlarm.append(s);
2131 detailsAlarm.append(", ");
2134 if (rdList.size() < nbNextHops) {
2135 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2137 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2142 // TODO Clean up the exception handling
2143 @SuppressWarnings("checkstyle:IllegalCatch")
2144 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2145 for (Routes route : routeList) {
2146 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2147 boolean isLockAcquired = false;
2148 String nextHop = String.valueOf(route.getNexthop().getValue());
2149 String destination = String.valueOf(route.getDestination().getValue());
2150 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2152 if (infName == null) {
2153 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2154 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2155 // Proceed to remove the next extra-route
2158 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2159 destination, vpnId.getValue(), nextHop, infName);
2161 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2162 InstanceIdentifier.builder(VpnInterfaces.class)
2163 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2164 .augmentation(Adjacencies.class)
2165 .child(Adjacency.class, new AdjacencyKey(destination))
2169 // Looking for existing prefix in MDSAL database
2170 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2171 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2172 boolean updateNextHops = false;
2173 List<String> nextHopList = new ArrayList<>();
2174 if (adjacency.isPresent()) {
2175 List<String> nhListRead = adjacency.get().getNextHopIpList();
2176 if (nhListRead.size() > 1) { // ECMP case
2177 for (String nextHopRead : nhListRead) {
2178 if (nextHopRead.equals(nextHop)) {
2179 updateNextHops = true;
2181 nextHopList.add(nextHopRead);
2187 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2188 if (updateNextHops) {
2189 // An update must be done, not including the current next hop
2190 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2191 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2192 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2193 .setNextHopIpList(nextHopList)
2194 .withKey(new AdjacencyKey(destination))
2196 Adjacencies erAdjs =
2197 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2198 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2199 .addAugmentation(Adjacencies.class, erAdjs).build();
2200 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2201 vpnIfIdentifier, vpnIf);
2203 // Remove the whole route
2204 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2205 adjacencyIdentifier);
2206 LOG.trace("extra route {} deleted successfully", route);
2208 } catch (TransactionCommitFailedException | ReadFailedException e) {
2209 LOG.error("exception in deleting extra route with destination {} for interface {}",
2210 destination, infName, e);
2212 if (isLockAcquired) {
2213 interfaceLock.unlock(infName);
2217 LOG.error("Incorrect input received for extra route: {}", route);
2222 public void removeVpn(Uuid vpnId) {
2224 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2225 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2226 // dissociate router
2227 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2228 for (RouterIds routerId : routerIdsList) {
2229 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2231 List<Uuid> rtrIdsList = routerIdsList.stream().map(routerId -> routerId.getRouterId())
2232 .collect(Collectors.toList());
2233 if (rtrIdsList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2234 // dissociate networks
2235 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2238 // remove entire vpnMaps node
2239 deleteVpnMapsNode(vpnId);
2241 // remove vpn-instance
2242 deleteVpnInstance(vpnId);
2243 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2246 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2247 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2250 // TODO Clean up the exception handling
2251 @SuppressWarnings("checkstyle:IllegalCatch")
2252 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2253 updateVpnMaps(vpnId, null, routerId, null, null);
2254 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2255 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2256 for (Uuid subnetId : routerSubnets) {
2257 Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
2258 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) {
2259 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2260 NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
2265 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2266 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2268 } catch (Exception e) {
2269 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2270 .getValue(), vpnId.getValue(), e);
2274 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2275 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2276 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2277 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2278 for (Uuid subnet : routerSubnets) {
2279 IpVersionChoice version = NeutronvpnUtils
2280 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2281 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2282 addSubnetToVpn(vpnId, subnet, null);
2284 addSubnetToVpn(vpnId, subnet, internetVpnId);
2289 // TODO Clean up the exception handling
2290 @SuppressWarnings("checkstyle:IllegalCatch")
2291 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2293 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2294 boolean vpnInstanceIpVersionsRemoved = false;
2295 IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
2296 for (Uuid subnetId : routerSubnets) {
2297 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
2298 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
2299 vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
2300 .getIpVersionFromString(sn.getSubnetIp()));
2301 vpnInstanceIpVersionsRemoved = true;
2303 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2304 updateVpnForSubnet(vpnId, routerId, subnetId, false);
2307 if (vpnInstanceIpVersionsRemoved) {
2308 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false);
2310 clearFromVpnMaps(vpnId, routerId, null);
2312 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2313 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2315 } catch (Exception e) {
2316 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2317 .getValue(), vpnId.getValue(), e);
2322 * Parses and associates networks list with given VPN.
2324 * @param vpnId Uuid of given VPN.
2325 * @param networkList List list of network Ids (Uuid), which will be associated.
2326 * @return list of formatted strings with detailed error messages.
2329 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2330 List<String> failedNwList = new ArrayList<>();
2331 HashSet<Uuid> passedNwList = new HashSet<>();
2332 if (networkList.isEmpty()) {
2333 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2334 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2336 return failedNwList;
2338 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2339 if (vpnInstance == null) {
2340 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2341 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2342 + "in ConfigDS", vpnId.getValue()));
2343 return failedNwList;
2346 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2347 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2349 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2350 + "associated with", vpnId.getValue()));
2351 return failedNwList;
2353 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2354 for (Uuid nw : networkList) {
2355 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2356 if (network == null) {
2357 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2358 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2362 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2363 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2364 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2365 nw.getValue(), vpnId.getValue());
2366 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2367 nw.getValue(), vpnId.getValue()));
2370 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2371 if (networkVpnId != null) {
2372 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2373 nw.getValue(), networkVpnId.getValue());
2374 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2375 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2378 if (neutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2379 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2380 nw.getValue(), vpnId.getValue());
2381 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2382 nw.getValue(), vpnId.getValue()));
2385 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2386 if (subnetmapList == null || subnetmapList.isEmpty()) {
2387 passedNwList.add(nw);
2390 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2393 for (Subnetmap subnetmap : subnetmapList) {
2394 Uuid subnetId = subnetmap.getId();
2395 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2396 if (subnetVpnId != null) {
2397 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2398 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2399 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2400 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2403 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(subnetmap, vpnId)) {
2404 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2405 NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()), true);
2407 if (!neutronvpnUtils.getIsExternal(network)) {
2408 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2410 addSubnetToVpn(vpnId, subnetId, null);
2411 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2413 passedNwList.add(nw);
2416 passedNwList.add(nw);
2418 } catch (ReadFailedException e) {
2419 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2421 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2424 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2425 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2426 return failedNwList;
2429 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2430 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2431 if (vpnOpDataEntry == null) {
2432 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2435 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2438 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2439 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2440 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2442 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2443 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2445 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2448 updateVpnInternetForSubnet(sm, vpnId, true);
2449 if (!vpnOpDataEntry.isIpv6Configured()
2450 && NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6) {
2451 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2452 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true);
2459 * Parses and disassociates networks list from given VPN.
2461 * @param vpnId Uuid of given VPN.
2462 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2463 * @return list of formatted strings with detailed error messages.
2466 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2467 List<String> failedNwList = new ArrayList<>();
2468 HashSet<Uuid> passedNwList = new HashSet<>();
2469 if (networkList.isEmpty()) {
2470 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2471 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2473 return failedNwList;
2475 for (Uuid nw : networkList) {
2476 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2477 if (networkSubnets == null) {
2478 passedNwList.add(nw);
2481 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2482 if (network == null) {
2483 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2484 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2488 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2489 if (networkVpnId == null) {
2490 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2491 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2495 if (!vpnId.equals(networkVpnId)) {
2496 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2497 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2498 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2499 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2503 if (NeutronvpnUtils.getIsExternal(network)) {
2504 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2505 passedNwList.add(nw);
2508 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2509 nw.getValue(), vpnId.getValue());
2510 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2515 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2516 for (Uuid subnet : networkSubnets) {
2517 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2518 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(subnetmap, vpnId)) {
2519 IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
2520 IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2521 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2522 ipVersionsToRemove.addVersion(ipVersion), false);
2524 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2526 removeSubnetFromVpn(vpnId, subnet, null);
2527 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2529 passedNwList.add(nw);
2532 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2533 LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
2535 return failedNwList;
2538 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2539 if (!removeExternalNetworkFromVpn(extNet)) {
2542 // check, if there is another Provider Networks associated with given VPN
2543 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2544 if (vpnNets != null) {
2545 for (Uuid netId : vpnNets) {
2546 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2547 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2548 + "{}", vpnId.getValue(), netId.getValue());
2553 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2554 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2555 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2556 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2557 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2559 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2562 updateVpnInternetForSubnet(sm, vpnId, false);
2564 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2565 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue());
2566 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false);
2571 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2574 // TODO Clean up the exception handling
2575 @SuppressWarnings("checkstyle:IllegalCatch")
2576 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2578 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2579 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2580 StringBuilder returnMsg = new StringBuilder();
2581 Uuid vpnId = input.getVpnId();
2584 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2585 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2586 input.getNetworkId().toString());
2587 List<Uuid> netIds = input.getNetworkId();
2588 if (netIds != null && !netIds.isEmpty()) {
2589 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2590 if (!failed.isEmpty()) {
2591 returnMsg.append(failed);
2595 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2597 if (returnMsg.length() != 0) {
2598 opBuilder.setResponse(
2599 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2600 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2601 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2603 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2605 } catch (Exception ex) {
2606 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2607 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2608 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2610 LOG.debug("associateNetworks returns..");
2615 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2618 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2620 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2621 LOG.debug("associateRouter {}", input);
2622 StringBuilder returnMsg = new StringBuilder();
2623 Uuid vpnId = input.getVpnId();
2624 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2625 routerIds = input.getRouterIds();
2626 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2627 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2628 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2629 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2630 .RouterIds routerId : routerIds) {
2631 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2632 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2633 if (vpnMap != null) {
2635 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2636 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2637 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2638 .append(routerId.getRouterId());
2639 } else if (extVpnId != null) {
2640 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2641 + "another VPN ").append(extVpnId.getValue());
2643 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2644 routerId.getRouterId());
2645 associateRouterToVpn(vpnId, routerId.getRouterId());
2648 returnMsg.append("router not found : ").append(routerId.getRouterId());
2651 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2653 if (returnMsg.length() != 0) {
2654 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2655 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2656 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2658 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2661 LOG.debug("associateRouter returns..");
2666 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2669 // TODO Clean up the exception handling
2670 @SuppressWarnings("checkstyle:IllegalCatch")
2671 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2672 GetFixedIPsForNeutronPortInput input) {
2673 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2674 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2675 Uuid portId = input.getPortId();
2676 StringBuilder returnMsg = new StringBuilder();
2678 List<String> fixedIPList = new ArrayList<>();
2679 Port port = neutronvpnUtils.getNeutronPort(portId);
2681 List<FixedIps> fixedIPs = port.getFixedIps();
2682 for (FixedIps ip : fixedIPs) {
2683 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
2686 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2688 if (returnMsg.length() != 0) {
2689 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2691 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2692 returnMsg)).build());
2694 opBuilder.setFixedIPs(fixedIPList);
2695 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2697 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2699 } catch (Exception ex) {
2700 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2701 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2702 portId.getValue(), ex.getMessage(), ex)).build());
2708 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2711 // TODO Clean up the exception handling
2712 @SuppressWarnings("checkstyle:IllegalCatch")
2713 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2715 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2716 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2718 LOG.debug("dissociateNetworks {}", input);
2719 StringBuilder returnMsg = new StringBuilder();
2720 Uuid vpnId = input.getVpnId();
2723 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2724 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2725 input.getNetworkId().toString());
2726 List<Uuid> netIds = input.getNetworkId();
2727 if (netIds != null && !netIds.isEmpty()) {
2728 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2729 if (!failed.isEmpty()) {
2730 returnMsg.append(failed);
2734 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2736 if (returnMsg.length() != 0) {
2737 opBuilder.setResponse(
2738 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2739 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2741 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2743 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2745 } catch (Exception ex) {
2746 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2747 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2748 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2750 LOG.debug("dissociateNetworks returns..");
2755 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2758 // TODO Clean up the exception handling
2759 @SuppressWarnings("checkstyle:IllegalCatch")
2760 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2762 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2764 LOG.debug("dissociateRouter {}", input);
2765 StringBuilder returnMsg = new StringBuilder();
2766 Uuid vpnId = input.getVpnId();
2767 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2768 .RouterIds> routerIdList = input.getRouterIds();
2769 String routerIdsString = "";
2770 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2771 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2772 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2773 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2774 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2775 .RouterIds routerId : routerIdList) {
2777 if (routerId != null) {
2778 routerIdsString += routerId.getRouterId() + ", ";
2779 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2781 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2782 if (routerVpnId == null) {
2783 returnMsg.append("input router ").append(routerId.getRouterId())
2784 .append(" not associated to any vpn yet");
2785 } else if (vpnId.equals(routerVpnId)) {
2786 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2788 returnMsg.append("input router ").append(routerId.getRouterId())
2789 .append(" associated to vpn ")
2790 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2793 returnMsg.append("router not found : ").append(routerId.getRouterId());
2796 if (returnMsg.length() != 0) {
2797 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2798 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2799 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2800 returnMsg)).build());
2802 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2804 } catch (Exception ex) {
2805 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2806 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2807 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2811 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2814 LOG.debug("dissociateRouter returns..");
2818 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2819 // check if the router is associated to some VPN
2820 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2821 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2822 if (vpnId != null) {
2823 // remove existing external vpn interfaces
2824 for (Uuid subnetId : routerSubnetIds) {
2825 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2827 clearFromVpnMaps(vpnId, routerId, null);
2829 // remove existing internal vpn interfaces
2830 for (Uuid subnetId : routerSubnetIds) {
2831 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2834 // delete entire vpnMaps node for internal VPN
2835 deleteVpnMapsNode(routerId);
2837 // delete vpn-instance for internal VPN
2838 deleteVpnInstance(routerId);
2841 protected Subnet getNeutronSubnet(Uuid subnetId) {
2842 return neutronvpnUtils.getNeutronSubnet(subnetId);
2845 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2846 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2848 return sn.getGatewayIp();
2854 protected Network getNeutronNetwork(Uuid networkId) {
2855 return neutronvpnUtils.getNeutronNetwork(networkId);
2858 protected Port getNeutronPort(String name) {
2859 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2862 protected Port getNeutronPort(Uuid portId) {
2863 return neutronvpnUtils.getNeutronPort(portId);
2866 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2867 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2870 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2871 return neutronvpnUtils.getNetworksForVpn(vpnId);
2875 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2877 * @return a List of String to be printed on screen
2878 * @throws ReadFailedException if there was a problem reading from the data store
2880 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2881 List<String> result = new ArrayList<>();
2882 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2884 result.add("-------------------------------------------------------------------------------------------");
2885 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2887 Optional<Ports> ports = syncReadOptional(dataBroker, CONFIGURATION, portidentifier);
2888 if (ports.isPresent() && ports.get().getPort() != null) {
2889 for (Port port : ports.get().getPort()) {
2890 List<FixedIps> fixedIPs = port.getFixedIps();
2891 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2892 List<String> ipList = new ArrayList<>();
2893 for (FixedIps fixedIp : fixedIPs) {
2894 IpAddress ipAddress = fixedIp.getIpAddress();
2895 if (ipAddress.getIpv4Address() != null) {
2896 ipList.add(ipAddress.getIpv4Address().getValue());
2898 ipList.add(ipAddress.getIpv6Address().getValue());
2901 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2902 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2903 ipList.toString()));
2905 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2906 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2915 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2917 * @param vpnuuid Uuid of the VPN whose config must be shown
2918 * @return formatted output list
2919 * @throws InterruptedException if there was a thread related problem getting the data to display
2920 * @throws ExecutionException if there was any other problem getting the data to display
2922 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2923 List<String> result = new ArrayList<>();
2924 if (vpnuuid == null) {
2926 result.add("Displaying VPN config for all VPNs");
2927 result.add("To display VPN config for a particular VPN, use the following syntax");
2928 result.add(getshowVpnConfigCLIHelp());
2930 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2931 if (rpcResult.isSuccessful()) {
2933 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2935 result.add(String.format(" %-80s ", "Import-RTs"));
2937 result.add(String.format(" %-80s ", "Export-RTs"));
2939 result.add(String.format(" %-76s ", "Subnet IDs"));
2941 result.add("------------------------------------------------------------------------------------");
2943 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2944 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2945 .rev150602.VpnInstance vpn : vpnList) {
2946 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2948 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2949 vpn.getRouteDistinguisher()));
2951 result.add(String.format(" %-80s ", vpn.getImportRT()));
2953 result.add(String.format(" %-80s ", vpn.getExportRT()));
2956 Uuid vpnid = vpn.getId();
2957 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
2958 if (!subnetList.isEmpty()) {
2959 for (Uuid subnetuuid : subnetList) {
2960 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2963 result.add(String.format(" %-76s ", "\" \""));
2966 result.add("----------------------------------------");
2970 String errortag = rpcResult.getErrors().iterator().next().getTag();
2971 if (Objects.equals(errortag, "")) {
2973 result.add("No VPN has been configured yet");
2974 } else if (Objects.equals(errortag, "invalid-value")) {
2976 result.add("VPN " + vpnuuid.getValue() + " is not present");
2978 result.add("error getting VPN info : " + rpcResult.getErrors());
2979 result.add(getshowVpnConfigCLIHelp());
2985 protected void createExternalVpnInterfaces(Uuid extNetId) {
2986 if (extNetId == null) {
2987 LOG.error("createExternalVpnInterfaces: external network is null");
2991 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2992 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2993 LOG.error("No external ports attached to external network {}", extNetId.getValue());
2997 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
2998 for (String elanInterface : extElanInterfaces) {
2999 createExternalVpnInterface(extNetId, elanInterface, tx);
3001 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3004 // TODO Clean up the exception handling
3005 @SuppressWarnings("checkstyle:IllegalCatch")
3006 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3007 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3008 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3009 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3012 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
3013 for (String elanInterface : extElanInterfaces) {
3014 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3015 .buildVpnInterfaceIdentifier(elanInterface);
3016 LOG.info("Removing vpn interface {}", elanInterface);
3017 tx.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
3019 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3022 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
3023 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null,
3024 false /* not a router iface */, wrtConfigTxn);
3027 // TODO Clean up the exception handling
3028 @SuppressWarnings("checkstyle:IllegalCatch")
3029 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
3030 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
3031 if (vpnIdList.isEmpty() || infName == null) {
3032 LOG.error("vpn id or interface is null");
3035 if (wrtConfigTxn == null) {
3036 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
3037 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, isRouterInterface, tx)), LOG,
3038 "Error writing VPN interface");
3041 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3042 for (Uuid vpnId: vpnIdList) {
3043 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3044 AssociatedSubnetType.V4AndV6Subnets);
3045 vpnIdListStruct.add(vpnInstance);
3048 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3049 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3051 .setVpnInstanceNames(vpnIdListStruct)
3052 .setRouterInterface(isRouterInterface);
3053 if (adjacencies != null) {
3054 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3056 VpnInterface vpnIf = vpnb.build();
3058 LOG.info("Creating vpn interface {}", vpnIf);
3059 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
3060 } catch (Exception ex) {
3061 LOG.error("Creation of vpninterface {} failed", infName, ex);
3065 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3066 WriteTransaction wrtConfigTxn) {
3067 if (vpnId == null || infName == null) {
3068 LOG.error("vpn id or interface is null");
3071 if (wrtConfigTxn == null) {
3072 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
3073 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3074 }), LOG, "Error updating VPN interface with adjacencies");
3078 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3079 boolean isLockAcquired = false;
3081 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3082 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3083 .syncReadOptional(dataBroker, LogicalDatastoreType
3084 .CONFIGURATION, vpnIfIdentifier);
3085 if (optionalVpnInterface.isPresent()) {
3086 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3087 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3089 if (adjacencies == null) {
3090 if (isLockAcquired) {
3091 interfaceLock.unlock(infName);
3095 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3096 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3097 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3098 optionalVpnInterface.get().getVpnInstanceNames());
3099 if (listVpnInstances.isEmpty() || !VpnHelper
3100 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3101 VpnInstanceNames vpnInstance = VpnHelper
3102 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3103 listVpnInstances.add(vpnInstance);
3104 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3107 VpnInstanceNames vpnInstance = VpnHelper
3108 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3109 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3110 listVpnInstances.add(vpnInstance);
3111 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3113 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3114 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder.build());
3116 } catch (IllegalStateException | ReadFailedException ex) {
3117 LOG.error("Update of vpninterface {} failed", infName, ex);
3119 if (isLockAcquired) {
3120 interfaceLock.unlock(infName);
3125 private String getshowVpnConfigCLIHelp() {
3126 StringBuilder help = new StringBuilder("Usage:");
3127 help.append("display vpn-config [-vid/--vpnid <id>]");
3128 return help.toString();
3131 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3132 InterruptedException {
3133 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3134 .setVpnId(vpnId).build();
3135 LOG.info("publishing notification upon association of router to VPN");
3136 notificationPublishService.putNotification(routerAssociatedToVpn);
3139 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3140 InterruptedException {
3141 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3142 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3143 LOG.info("publishing notification upon disassociation of router from VPN");
3144 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3147 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3148 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3152 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3153 return neutronEvpnManager.createEVPN(input);
3157 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3158 return neutronEvpnManager.getEVPN(input);
3162 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3163 return neutronEvpnManager.deleteEVPN(input);
3166 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3167 Uuid extNetId = extNet.getUuid();
3168 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3169 .child(Networks.class, new NetworksKey(extNetId)).build();
3172 Optional<Networks> optionalExtNets =
3173 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3175 if (!optionalExtNets.isPresent()) {
3176 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3177 extNetId.getValue());
3180 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3181 builder.setVpnid(vpnId);
3182 Networks networks = builder.build();
3183 // Add Networks object to the ExternalNetworks list
3184 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3185 extNetId.getValue());
3186 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3189 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3190 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3191 extNetId.getValue(), ex);
3196 private boolean removeExternalNetworkFromVpn(Network extNet) {
3197 Uuid extNetId = extNet.getUuid();
3198 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3199 .child(Networks.class, new NetworksKey(extNetId)).build();
3201 Optional<Networks> optionalNets =
3202 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3204 NetworksBuilder builder = null;
3205 if (optionalNets.isPresent()) {
3206 builder = new NetworksBuilder(optionalNets.get());
3208 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3209 extNetId.getValue());
3212 builder.setVpnid(null);
3213 Networks networks = builder.build();
3214 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3215 extNetId.getValue());
3216 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3218 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3219 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3220 extNetId.getValue(), ex);
3225 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3226 Optional<String> existingVpnName = Optional.of(primaryRd);
3227 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3229 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3230 .syncReadOptional(dataBroker, OPERATIONAL, neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3231 } catch (ReadFailedException e) {
3232 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3234 /*Read failed. We don't know if a VPN exists or not.
3235 * Return primaryRd to halt caller execution, to be safe.*/
3236 return existingVpnName;
3238 if (vpnInstanceOpDataOptional.isPresent()) {
3239 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3241 existingVpnName = Optional.absent();
3243 return existingVpnName;
3246 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3247 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3250 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3251 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3254 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3255 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3258 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3259 String message = tuple.getMessage();
3260 logger.accept(message);