2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.JdkFutureAdapters;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.common.util.concurrent.SettableFuture;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.ExecutionException;
36 import java.util.concurrent.Future;
37 import java.util.concurrent.TimeUnit;
38 import java.util.function.Consumer;
39 import java.util.stream.Collectors;
40 import javax.annotation.Nonnull;
41 import javax.annotation.Nullable;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
45 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
46 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
50 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
51 import org.opendaylight.genius.infra.Datastore;
52 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
54 import org.opendaylight.genius.infra.TypedWriteTransaction;
55 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
56 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
57 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
58 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
59 import org.opendaylight.netvirt.elanmanager.api.IElanService;
60 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
61 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
62 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
63 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
64 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
65 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
66 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.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 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn,
792 Subnetmap sn, VpnInterface vpnIface) {
793 List<Adjacency> adjList = new ArrayList<>();
794 if (vpnIface != null) {
795 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
797 String infName = port.getUuid().getValue();
798 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
799 for (FixedIps ip : port.getFixedIps()) {
800 String ipValue = String.valueOf(ip.getIpAddress().getValue());
801 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
802 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
805 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
806 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
808 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
809 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
810 //Create Neutron port adjacency if VPN presence is existing for subnet
811 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
812 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
813 .setSubnetId(ip.getSubnetId()).build();
814 if (!adjList.contains(vmAdj)) {
818 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
819 if (snTemp != null && snTemp.getInternetVpnId() != null) {
820 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
821 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
823 if (routerId != null) {
824 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
825 if (rtr != null && rtr.getRoutes() != null) {
826 List<Routes> routeList = rtr.getRoutes();
827 // create extraroute Adjacence for each ipValue,
828 // because router can have IPv4 and IPv6 subnet ports, or can have
829 // more that one IPv4 subnet port or more than one IPv6 subnet port
830 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
831 if (!erAdjList.isEmpty()) {
832 adjList.addAll(erAdjList);
837 return new AdjacenciesBuilder().setAdjacency(adjList).build();
840 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
841 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
842 boolean isRouterInterface = false;
843 if (port.getDeviceOwner() != null) {
844 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
846 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, null);
847 String infName = port.getUuid().getValue();
848 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
849 writeVpnInterfaceToDs(vpnIds, infName, adjs, isRouterInterface, wrtConfigTxn);
852 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
853 Port port, Subnetmap sn, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
854 String infName = port.getUuid().getValue();
855 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
856 Optional<VpnInterface> optionalVpnInterface = null;
857 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
858 vpnId, internetVpnId, infName);
860 optionalVpnInterface = SingleTransactionDataBroker
861 .syncReadOptional(dataBroker, LogicalDatastoreType
862 .CONFIGURATION, vpnIfIdentifier);
863 } catch (ReadFailedException e) {
864 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
867 if (!optionalVpnInterface.isPresent()) {
870 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
871 sn != null ? sn.getSubnetIp() : "null");
872 List<Adjacency> vpnAdjsList = optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency();
873 List<Adjacency> updatedAdjsList = new ArrayList<>();
874 boolean isIpFromAnotherSubnet = false;
875 for (Adjacency adj : vpnAdjsList) {
876 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
877 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
878 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
879 isIpFromAnotherSubnet = true;
881 updatedAdjsList.add(adj);
884 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
885 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
888 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
889 String.valueOf(adjString), wrtConfigTxn);
891 if (internetVpnId != null) {
892 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
893 String.valueOf(adjString), wrtConfigTxn);
896 if (port.getDeviceOwner()
897 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) && sn.getRouterId() != null) {
898 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
899 if (rtr != null && rtr.getRoutes() != null) {
900 List<Routes> extraRoutesToRemove = new ArrayList<>();
901 for (Routes rt: rtr.getRoutes()) {
902 if (rt.getNexthop().toString().equals(adjString)) {
903 extraRoutesToRemove.add(rt);
907 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
908 extraRoutesToRemove, vpnId);
909 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
911 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
916 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
918 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
920 if (internetVpnId != null) {
921 updateVpnInterfaceWithAdjacencies(internetVpnId, infName, adjacencies, wrtConfigTxn);
923 if (!isIpFromAnotherSubnet) {
924 // no more subnetworks for neutron port
925 if (sn != null && sn.getRouterId() != null) {
926 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
928 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
934 // TODO Clean up the exception handling
935 @SuppressWarnings("checkstyle:IllegalCatch")
936 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
937 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
938 if (wrtConfigTxn == null) {
939 ListenableFutures.addErrorLogging(
940 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
941 tx -> deleteVpnInterface(infName, vpnId, tx)),
942 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
946 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
947 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
948 Optional<VpnInterface> optionalVpnInterface;
950 optionalVpnInterface =
951 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
953 } catch (ReadFailedException ex) {
954 LOG.error("Error during deletion of vpninterface {}", infName, ex);
957 if (!optionalVpnInterface.isPresent()) {
958 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
962 VpnInterface vpnInterface = optionalVpnInterface.get();
963 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
965 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
966 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
967 if (!vpnList.isEmpty()) {
968 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
969 + "List not empty", infName);
972 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
973 .setVpnInstanceNames(vpnList);
974 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
978 LOG.debug("Deleting vpn interface {}", infName);
979 wrtConfigTxn.delete(vpnIfIdentifier);
982 protected void removeVpnFromVpnInterface(Uuid vpnId, Port port,
983 TypedWriteTransaction<Datastore.Configuration> writeConfigTxn,
985 if (vpnId == null || port == null) {
988 String infName = port.getUuid().getValue();
989 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
991 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
992 .syncReadOptional(dataBroker, LogicalDatastoreType
993 .CONFIGURATION, vpnIfIdentifier);
994 if (optionalVpnInterface.isPresent()) {
995 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
997 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
998 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1000 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1001 .setVpnInstanceNames(listVpn);
1002 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1003 LOG.debug("Updating vpn interface {}", infName);
1004 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1005 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1006 while (adjacencyIter.hasNext()) {
1007 Adjacency adjacency = adjacencyIter.next();
1008 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1011 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1012 InstanceIdentifier<LearntVpnVipToPort> id =
1013 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1014 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1015 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1016 LogicalDatastoreType.OPERATIONAL, id);
1017 if (optionalVpnVipToPort.isPresent()) {
1018 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1020 if (listVpn == null || listVpn.isEmpty()) {
1021 adjacencyIter.remove();
1023 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1024 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1025 mipToQuery, infName, vpnId.getValue());
1028 List<FixedIps> ips = port.getFixedIps();
1029 for (FixedIps ip : ips) {
1030 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1031 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1032 ipValue, writeConfigTxn);
1034 if (listVpn == null || listVpn.isEmpty()) {
1035 if (sm != null && sm.getRouterId() != null) {
1036 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1038 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1040 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1043 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1045 } catch (ReadFailedException ex) {
1046 LOG.error("Update of vpninterface {} failed", infName, ex);
1050 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
1052 TypedWriteTransaction<Datastore.Configuration> writeConfigTxn) {
1053 if (vpnId == null || port == null) {
1056 boolean isLockAcquired = false;
1057 String infName = port.getUuid().getValue();
1058 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1061 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1062 Optional<VpnInterface> optionalVpnInterface =
1063 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1065 if (optionalVpnInterface.isPresent()) {
1066 VpnInstanceNames vpnInstance = VpnHelper
1067 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1068 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1069 .get().getVpnInstanceNames());
1070 if (oldVpnId != null
1071 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1072 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1074 if (vpnId.getValue() != null
1075 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1076 listVpn.add(vpnInstance);
1078 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1079 .setVpnInstanceNames(listVpn);
1080 LOG.debug("Updating vpn interface {}", infName);
1081 if (!isBeingAssociated) {
1082 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1083 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1084 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1085 while (adjacencyIter.hasNext()) {
1086 Adjacency adjacency = adjacencyIter.next();
1087 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1088 InstanceIdentifier<LearntVpnVipToPort> id =
1089 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1090 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1091 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1092 LogicalDatastoreType.OPERATIONAL, id);
1093 if (optionalVpnVipToPort.isPresent()) {
1094 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1095 + "from VPN {}", infName, vpnId, oldVpnId);
1096 adjacencyIter.remove();
1097 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1099 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1100 mipToQuery, infName, vpnId.getValue());
1103 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1104 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1106 List<FixedIps> ips = port.getFixedIps();
1107 for (FixedIps ip : ips) {
1108 String ipValue = String.valueOf(ip.getIpAddress().getValue());
1109 if (oldVpnId != null) {
1110 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1111 ipValue, writeConfigTxn);
1113 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1114 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1116 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1118 LOG.error("VPN Interface {} not found", infName);
1120 } catch (ReadFailedException ex) {
1121 LOG.error("Updation of vpninterface {} failed", infName, ex);
1123 if (isLockAcquired) {
1124 interfaceLock.unlock(infName);
1129 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
1130 List<String> ert, Uuid router, List<Uuid> networks) {
1132 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1134 // Update VPN Instance node
1135 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1137 // Update local vpn-subnet DS
1138 updateVpnMaps(vpn, name, router, tenant, networks);
1140 if (router != null) {
1141 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1142 if (existingVpn != null) {
1143 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1144 // if before reboot, router was already associated to VPN, should not proceed associating router to
1145 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1146 // preserved upon reboot.
1147 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1148 // RouterInterfacesMap via #createVPNInterface call.
1149 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1150 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1153 associateRouterToInternalVpn(vpn, router);
1158 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1159 * specified Neutron Networks and Routers.
1161 * @param vpnId Uuid of the VPN tp be created
1162 * @param name Representative name of the new VPN
1163 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1164 * @param rdList Route-distinguisher for the VPN
1165 * @param irtList A list of Import Route Targets
1166 * @param ertList A list of Export Route Targets
1167 * @param routerIdsList ist of neutron router Id to associate with created VPN
1168 * @param networkList UUID of the neutron network the VPN may be associated to
1169 * @param type Type of the VPN Instance
1170 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1171 * @throws Exception if association of L3VPN failed
1173 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1174 List<String> ertList, @Nullable List<Uuid> routerIdsList, List<Uuid> networkList,
1175 VpnInstance.Type type, long l3vni) throws Exception {
1177 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1179 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1180 for (Uuid routerId : routerIdsList) {
1181 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1182 ipVersChoices = ipVersChoices.addVersion(vers);
1185 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1187 // Please note that router and networks will be filled into VPNMaps
1188 // by subsequent calls here to associateRouterToVpn and
1189 // associateNetworksToVpn
1190 updateVpnMaps(vpnId, name, null, tenantId, null);
1191 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1192 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1195 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1196 for (Uuid routerId : routerIdsList) {
1197 associateRouterToVpn(vpnId, routerId);
1200 if (networkList != null) {
1201 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1202 if (!failStrings.isEmpty()) {
1203 LOG.error("VPN {} association to networks failed for networks: {}. ",
1204 vpnId.getValue(), failStrings.toString());
1205 throw new Exception(failStrings.toString());
1211 * It handles the invocations to the createVPN RPC method.
1214 // TODO Clean up the exception handling
1215 @SuppressWarnings("checkstyle:IllegalCatch")
1216 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1218 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1219 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1220 List<RpcError> errorList = new ArrayList<>();
1221 int failurecount = 0;
1222 int warningcount = 0;
1224 List<L3vpn> vpns = input.getL3vpn();
1226 vpns = Collections.emptyList();
1228 for (L3vpn vpn : vpns) {
1229 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1230 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1231 formatAndLog(LOG::warn,
1232 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1233 vpn.getId().getValue())));
1237 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1238 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1239 formatAndLog(LOG::warn,
1240 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1241 vpn.getId().getValue())));
1245 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1247 if (vpn.getL3vni() != null) {
1248 l3vni = vpn.getL3vni();
1251 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1252 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1253 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1254 formatAndLog(LOG::warn,
1255 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1256 + "is already configured",
1257 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1261 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1262 if (operationalVpn.isPresent()) {
1263 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1264 formatAndLog(LOG::error,
1265 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1266 + "is still available. Please retry creation of a new vpn with the same RD"
1267 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1268 vpn.getRouteDistinguisher().get(0))));
1272 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1273 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1274 routerIdsList = vpn.getRouterIds();
1275 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1276 routerId : routerIdsList) {
1277 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1278 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1279 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1280 + "{}", vpn.getId(), routerId.getRouterId())));
1284 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1285 if (vpnId != null) {
1286 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1287 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1288 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1289 vpnId.getValue())));
1295 if (vpn.getNetworkIds() != null) {
1296 int initialWarningCount = warningcount;
1297 for (Uuid nw : vpn.getNetworkIds()) {
1298 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1299 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1300 if (network == null) {
1301 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1302 formatAndLog(LOG::warn,
1303 "Creation of L3VPN failed for VPN {} due to network not found {}",
1304 vpn.getId().getValue(), nw.getValue())));
1306 } else if (vpnId != null) {
1307 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1308 formatAndLog(LOG::warn,
1309 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1310 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1311 vpnId.getValue())));
1315 if (warningcount != initialWarningCount) {
1319 List<Uuid> rtrIdsList = new ArrayList<>();
1320 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1321 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1322 rtrId : vpn.getRouterIds()) {
1323 rtrIdsList.add(rtrId.getRouterId());
1327 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1328 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1329 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1330 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1331 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1332 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1333 vpnInstanceType, l3vni);
1334 } catch (Exception ex) {
1335 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1336 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1341 // if at least one succeeds; result is success
1342 // if none succeeds; result is failure
1343 if (failurecount + warningcount == vpns.size()) {
1344 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1346 List<String> errorResponseList = new ArrayList<>();
1347 if (!errorList.isEmpty()) {
1348 for (RpcError rpcError : errorList) {
1349 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1350 + ", ErrorMessage: " + rpcError.getMessage());
1353 errorResponseList.add("Operation successful with no errors");
1355 opBuilder.setResponse(errorResponseList);
1356 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1362 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1365 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1367 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1368 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1369 Uuid inputVpnId = input.getId();
1370 List<VpnInstance> vpns = new ArrayList<>();
1371 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1374 if (inputVpnId == null) {
1376 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1378 Optional<VpnInstances> optionalVpns =
1379 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1381 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1382 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1383 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1384 // from getL3VPN output
1385 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1388 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1394 opBuilder.setL3vpnInstances(l3vpnList);
1395 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1399 String name = inputVpnId.getValue();
1400 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1401 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1402 // read VpnInstance Info
1403 Optional<VpnInstance> optionalVpn =
1404 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1406 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1408 if (optionalVpn.isPresent() && (optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null)
1409 || (optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null)) {
1410 vpns.add(optionalVpn.get());
1413 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1414 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1418 for (VpnInstance vpnInstance : vpns) {
1419 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1420 // create VpnMaps id
1421 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1422 List<String> rd = Collections.EMPTY_LIST;
1423 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1424 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1425 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1426 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1428 List<String> ertList = new ArrayList<>();
1429 List<String> irtList = new ArrayList<>();
1431 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1432 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1433 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1434 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1435 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1436 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1437 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1439 if (!vpnTargetList.isEmpty()) {
1440 for (VpnTarget vpnTarget : vpnTargetList) {
1441 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1442 ertList.add(vpnTarget.getVrfRTValue());
1444 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1445 irtList.add(vpnTarget.getVrfRTValue());
1447 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1448 ertList.add(vpnTarget.getVrfRTValue());
1449 irtList.add(vpnTarget.getVrfRTValue());
1455 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1457 if (vpnInstance.getL3vni() != null) {
1458 l3vpn.setL3vni(vpnInstance.getL3vni());
1460 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1461 .class, new VpnMapKey(vpnId)).build();
1462 Optional<VpnMap> optionalVpnMap =
1463 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1465 if (optionalVpnMap.isPresent()) {
1466 VpnMap vpnMap = optionalVpnMap.get();
1467 List<Uuid> rtrIds = new ArrayList<>();
1468 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1469 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1470 rtrIds.add(rtrId.getRouterId());
1473 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1474 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1475 .setName(vpnMap.getName());
1478 l3vpnList.add(l3vpn.build());
1481 opBuilder.setL3vpnInstances(l3vpnList);
1482 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1484 } catch (ReadFailedException ex) {
1485 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1486 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1492 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1495 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1497 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1498 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1499 List<RpcError> errorList = new ArrayList<>();
1501 int failurecount = 0;
1502 int warningcount = 0;
1503 List<Uuid> vpns = input.getId();
1504 for (Uuid vpn : vpns) {
1508 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1509 InstanceIdentifier<VpnInstance> vpnIdentifier =
1510 InstanceIdentifier.builder(VpnInstances.class)
1511 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1512 Optional<VpnInstance> optionalVpn =
1513 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1515 if (optionalVpn.isPresent()) {
1518 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1519 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1522 } catch (ReadFailedException ex) {
1523 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1524 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1529 // if at least one succeeds; result is success
1530 // if none succeeds; result is failure
1531 if (failurecount + warningcount == vpns.size()) {
1532 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1534 List<String> errorResponseList = new ArrayList<>();
1535 if (!errorList.isEmpty()) {
1536 for (RpcError rpcError : errorList) {
1537 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1538 + ", ErrorMessage: " + rpcError.getMessage());
1541 errorResponseList.add("Operation successful with no errors");
1543 opBuilder.setResponse(errorResponseList);
1544 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1549 public void createVpnInstanceForSubnet(Uuid subnetId) {
1550 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1551 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1554 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1555 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1556 removeVpn(subnetId);
1559 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1560 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1561 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1562 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1564 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1565 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1568 if (vpnId != null) {
1569 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1570 if (vpnMap == null) {
1571 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1572 + " cannot add subnet {} to VPN", vpnId.getValue(),
1576 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1577 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1578 if (isVpnOfTypeL2(vpnInstance)) {
1579 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1580 NeutronEvpnUtils.Operation.ADD);
1583 if (internetVpnId != null) {
1584 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1585 if (vpnMap == null) {
1586 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1587 + "subnet {} to VPN", internetVpnId.getValue(),
1592 final Uuid internetId = internetVpnId;
1593 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1594 List<Uuid> portList = sn.getPortList();
1595 if (portList != null) {
1596 for (final Uuid portId : portList) {
1597 String vpnInfName = portId.getValue();
1598 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1599 Port port = neutronvpnUtils.getNeutronPort(portId);
1601 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1602 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1605 final Boolean isRouterInterface = port.getDeviceOwner()
1606 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1607 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1608 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1609 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1611 if (vpnIface == null) {
1612 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1613 Set<Uuid> listVpn = new HashSet<>();
1614 if (vpnId != null) {
1617 if (internetId != null) {
1618 listVpn.add(internetId);
1620 writeVpnInterfaceToDs(listVpn,
1621 vpnInfName, portAdj, isRouterInterface, wrtConfigTxn);
1622 if (sn.getRouterId() != null) {
1623 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1626 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1627 if (vpnId != null) {
1628 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1630 if (internetId != null) {
1631 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1640 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, Uuid internetVpnId) {
1641 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1642 "removeSubnetFromVpn: at least one VPN must be not null");
1643 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1644 vpnId, internetVpnId);
1645 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1647 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1650 VpnMap vpnMap = null;
1651 VpnInstance vpnInstance = null;
1652 if (vpnId != null) {
1653 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1654 if (vpnMap == null) {
1655 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1656 vpnId.getValue(), subnet.getValue());
1659 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1661 if (internetVpnId == null) {
1662 internetVpnId = sn.getInternetVpnId();
1664 if (internetVpnId != null) {
1665 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1666 if (vpnMap == null) {
1667 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1668 + " from Internet VPN",
1669 internetVpnId.getValue(), subnet.getValue());
1673 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1674 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1675 NeutronEvpnUtils.Operation.DELETE);
1677 boolean subnetVpnAssociation = false;
1678 if (vpnId != null && sn.getVpnId() != null
1679 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1680 subnetVpnAssociation = true;
1681 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1682 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1683 subnetVpnAssociation = true;
1685 if (subnetVpnAssociation == false) {
1686 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1687 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1690 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1691 List<Uuid> portList = sn.getPortList();
1692 final Uuid internetId = internetVpnId;
1693 if (portList != null) {
1694 for (final Uuid portId : portList) {
1695 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1696 final Port port = neutronvpnUtils.getNeutronPort(portId);
1697 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1698 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1699 CONFIGURATION, tx -> {
1701 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1704 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1705 + "port is absent in Neutron config DS", portId.getValue(),
1711 //update subnet-vpn association
1712 removeFromSubnetNode(subnet, null, null, vpnId, null);
1715 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1716 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1717 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1719 Uuid internalVpnId = sm.getVpnId();
1720 if (internalVpnId == null) {
1721 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1722 sm.getId().getValue());
1725 if (isBeingAssociated) {
1726 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1728 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1731 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1732 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1733 if (isBeingAssociated) {
1734 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1735 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn);
1737 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()),
1743 // Check for ports on this subnet and update association of
1744 // corresponding vpn-interfaces to internet vpn
1745 List<Uuid> portList = sm.getPortList();
1746 if (portList != null) {
1747 for (Uuid port : portList) {
1748 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1749 port.getValue(), isBeingAssociated);
1750 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1751 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1753 if (isBeingAssociated) {
1754 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1757 removeVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1764 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1765 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1766 oldVpnId.getValue(), newVpnId.getValue());
1767 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1768 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1769 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1770 Uuid vpnExtUuid = netIsExternal ? null
1771 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1772 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1774 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1778 //Update Router Interface first synchronously.
1779 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1780 ListenableFuture<Void> future =
1781 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1782 tx -> updateVpnInterface(newVpnId, oldVpnId,
1783 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1784 isBeingAssociated, true, tx));
1785 Futures.addCallback(future, new FutureCallback<Void>() {
1787 public void onSuccess(Void result) {
1788 // Check for ports on this subnet and update association of
1789 // corresponding vpn-interfaces to external vpn
1790 List<Uuid> portList = sn.getPortList();
1791 if (portList != null) {
1792 for (Uuid port : portList) {
1793 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1794 port.getValue(), isBeingAssociated);
1795 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1796 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1797 tx -> updateVpnInterface(newVpnId, oldVpnId,
1798 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1805 public void onFailure(Throwable throwable) {
1807 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1809 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1811 }, MoreExecutors.directExecutor());
1816 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1817 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1818 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1821 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1822 synchronized (routerId.getValue().intern()) {
1823 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1825 Optional<RouterInterfaces> optRouterInterfaces =
1826 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1827 routerInterfacesId);
1828 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1829 .setInterfaceId(interfaceName).build();
1830 if (optRouterInterfaces.isPresent()) {
1831 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1832 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1835 // TODO Shouldn't we be doing something with builder and interfaces?
1836 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1837 // List<Interfaces> interfaces = new ArrayList<>();
1838 // interfaces.add(routerInterface);
1840 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1841 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1844 } catch (ReadFailedException | TransactionCommitFailedException e) {
1845 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1850 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1851 synchronized (routerId.getValue().intern()) {
1852 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1854 Optional<RouterInterfaces> optRouterInterfaces =
1855 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1856 routerInterfacesId);
1857 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1858 .setInterfaceId(interfaceName).build();
1859 if (optRouterInterfaces.isPresent()) {
1860 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1861 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1862 if (interfaces != null && interfaces.remove(routerInterface)) {
1863 if (interfaces.isEmpty()) {
1864 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1865 routerInterfacesId);
1867 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1868 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1872 } catch (ReadFailedException | TransactionCommitFailedException e) {
1873 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1879 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1880 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1881 * route will be ignored.
1883 * @param vpnName the VPN identifier
1884 * @param interVpnLinkRoutes The list of static routes
1885 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1887 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1888 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1889 for (Routes route : interVpnLinkRoutes) {
1890 String nexthop = String.valueOf(route.getNexthop().getValue());
1891 String destination = String.valueOf(route.getDestination().getValue());
1892 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1893 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1894 AddStaticRouteInput rpcInput =
1895 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1896 .setVpnInstanceName(vpnName.getValue())
1898 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1899 RpcResult<AddStaticRouteOutput> rpcResult;
1901 rpcResult = labelOuputFtr.get();
1902 if (rpcResult.isSuccessful()) {
1903 LOG.debug("Label generated for destination {} is: {}",
1904 destination, rpcResult.getResult().getLabel());
1906 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1907 destination, nexthop, rpcResult.getErrors());
1909 } catch (InterruptedException | ExecutionException e) {
1910 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1911 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1914 // Any other case is a fault.
1915 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1916 String.valueOf(route.getDestination().getValue()), nexthop);
1923 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1924 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1926 * @param vpnName the VPN identifier
1927 * @param interVpnLinkRoutes The list of static routes
1928 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1930 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1931 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1932 for (Routes route : interVpnLinkRoutes) {
1933 String nexthop = String.valueOf(route.getNexthop().getValue());
1934 String destination = String.valueOf(route.getDestination().getValue());
1935 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1936 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1937 RemoveStaticRouteInput rpcInput =
1938 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1939 .setVpnInstanceName(vpnName.getValue())
1942 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1943 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1945 // Any other case is a fault.
1946 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1947 String.valueOf(route.getDestination().getValue()), nexthop);
1954 * Returns true if the specified nexthop is the other endpoint in an
1955 * InterVpnLink, regarding one of the VPN's point of view.
1957 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1959 interVpnLink != null
1960 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1961 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1962 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1963 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1967 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
1968 List<Adjacency> adjList = new ArrayList<>();
1969 Map<String, List<String>> adjMap = new HashMap<>();
1970 for (Routes route : routeList) {
1971 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1972 LOG.error("Incorrect input received for extra route. {}", route);
1974 String nextHop = String.valueOf(route.getNexthop().getValue());
1975 String destination = String.valueOf(route.getDestination().getValue());
1976 if (!nextHop.equals(fixedIp)) {
1977 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1980 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
1982 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1983 if (!hops.contains(nextHop)) {
1989 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
1990 final String destination = entry.getKey();
1991 final List<String> ipList = entry.getValue();
1992 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1993 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
1994 .withKey(new AdjacencyKey(destination)).build();
2000 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2001 checkAlarmExtraRoutes(vpnId, routeList);
2003 for (Routes route : routeList) {
2004 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2005 LOG.error("Incorrect input received for extra route. {}", route);
2007 String nextHop = String.valueOf(route.getNexthop().getValue());
2008 String destination = String.valueOf(route.getDestination().getValue());
2009 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2011 if (infName != null) {
2012 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2013 destination, vpnId.getValue(), nextHop, infName);
2014 boolean isLockAcquired = false;
2016 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2017 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2018 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2019 .child(Adjacency.class, new AdjacencyKey(destination));
2020 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2021 LogicalDatastoreType.CONFIGURATION, path);
2022 if (existingAdjacency.isPresent()
2023 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2024 LOG.error("The route with destination {} nextHop {} is already present as"
2025 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2026 destination, nextHop, infName);
2029 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2030 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2031 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2032 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2033 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2035 } catch (TransactionCommitFailedException e) {
2036 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2037 destination, nextHop, e);
2038 } catch (ReadFailedException e) {
2039 LOG.error("Exception on reading data-store ", e);
2041 if (isLockAcquired) {
2042 interfaceLock.unlock(infName);
2046 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2047 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2054 * This method setup or down an alarm about extra route fault.
2055 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2056 * available RDs, then an alarm and an error is generated.<br>
2057 * <b>Be careful</b> the routeList could be changed.
2059 * @param vpnId the vpnId of vpn to control.
2060 * @param routeList the list of router to check, it could be modified.
2062 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2063 if (!neutronvpnAlarm.isAlarmEnabled()) {
2064 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2067 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2068 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2069 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2073 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2074 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2075 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2079 for (Routes route : routeList) {
2080 // count the number of nexthops for each same route.getDestingation().getValue()
2081 String destination = String.valueOf(route.getDestination().getValue());
2082 String nextHop = String.valueOf(route.getNexthop().getValue());
2083 List<String> nextHopList = new ArrayList();
2084 nextHopList.add(nextHop);
2086 for (Routes routeTmp : routeList) {
2087 String routeDest = String.valueOf(routeTmp.getDestination().getValue());
2088 if (!destination.equals(routeDest)) {
2091 String routeNextH = String.valueOf(routeTmp.getNexthop().getValue());
2092 if (nextHop.equals(routeNextH)) {
2096 nextHopList.add(new String(routeTmp.getNexthop().getValue()));
2098 final List<String> rdList = new ArrayList<>();
2099 if (vpnInstance.getIpv4Family() != null
2100 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2101 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2107 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2108 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2109 if (rd != null && !rdList.contains(rd)) {
2114 // 1. VPN Instance Name
2115 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2118 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2119 Uuid routerUuid = routerUuidList.get(0);
2120 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2121 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2123 // 3. List of RDs associated with the VPN
2124 detailsAlarm.append(" List of RDs associated with the VPN: ");
2125 for (String s : rdList) {
2126 detailsAlarm.append(s);
2127 detailsAlarm.append(", ");
2130 // 4. Prefix in question
2131 detailsAlarm.append(" for prefix: ");
2132 detailsAlarm.append(route.getDestination().getValue());
2134 // 5. List of NHs for the prefix
2135 detailsAlarm.append(" for nextHops: ");
2136 for (String s : nextHopList) {
2137 detailsAlarm.append(s);
2138 detailsAlarm.append(", ");
2141 if (rdList.size() < nbNextHops) {
2142 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2144 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2149 // TODO Clean up the exception handling
2150 @SuppressWarnings("checkstyle:IllegalCatch")
2151 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2152 for (Routes route : routeList) {
2153 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2154 boolean isLockAcquired = false;
2155 String nextHop = String.valueOf(route.getNexthop().getValue());
2156 String destination = String.valueOf(route.getDestination().getValue());
2157 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2159 if (infName == null) {
2160 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2161 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2162 // Proceed to remove the next extra-route
2165 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2166 destination, vpnId.getValue(), nextHop, infName);
2168 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2169 InstanceIdentifier.builder(VpnInterfaces.class)
2170 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2171 .augmentation(Adjacencies.class)
2172 .child(Adjacency.class, new AdjacencyKey(destination))
2176 // Looking for existing prefix in MDSAL database
2177 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2178 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2179 boolean updateNextHops = false;
2180 List<String> nextHopList = new ArrayList<>();
2181 if (adjacency.isPresent()) {
2182 List<String> nhListRead = adjacency.get().getNextHopIpList();
2183 if (nhListRead.size() > 1) { // ECMP case
2184 for (String nextHopRead : nhListRead) {
2185 if (nextHopRead.equals(nextHop)) {
2186 updateNextHops = true;
2188 nextHopList.add(nextHopRead);
2194 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2195 if (updateNextHops) {
2196 // An update must be done, not including the current next hop
2197 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2198 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2199 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2200 .setNextHopIpList(nextHopList)
2201 .withKey(new AdjacencyKey(destination))
2203 Adjacencies erAdjs =
2204 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2205 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2206 .addAugmentation(Adjacencies.class, erAdjs).build();
2207 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2208 vpnIfIdentifier, vpnIf);
2210 // Remove the whole route
2211 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2212 adjacencyIdentifier);
2213 LOG.trace("extra route {} deleted successfully", route);
2215 } catch (TransactionCommitFailedException | ReadFailedException e) {
2216 LOG.error("exception in deleting extra route with destination {} for interface {}",
2217 destination, infName, e);
2219 if (isLockAcquired) {
2220 interfaceLock.unlock(infName);
2224 LOG.error("Incorrect input received for extra route: {}", route);
2229 public void removeVpn(Uuid vpnId) {
2231 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2232 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2233 // dissociate router
2234 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2235 for (RouterIds routerId : routerIdsList) {
2236 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2238 List<Uuid> rtrIdsList = routerIdsList.stream().map(routerId -> routerId.getRouterId())
2239 .collect(Collectors.toList());
2240 if (rtrIdsList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2241 // dissociate networks
2242 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2245 // remove entire vpnMaps node
2246 deleteVpnMapsNode(vpnId);
2248 // remove vpn-instance
2249 deleteVpnInstance(vpnId);
2250 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2253 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2254 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2257 // TODO Clean up the exception handling
2258 @SuppressWarnings("checkstyle:IllegalCatch")
2259 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2260 updateVpnMaps(vpnId, null, routerId, null, null);
2261 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2262 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2263 for (Uuid subnetId : routerSubnets) {
2264 Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
2265 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(sn, vpnId)) {
2266 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2267 NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
2272 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2273 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2275 } catch (Exception e) {
2276 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2277 .getValue(), vpnId.getValue(), e);
2281 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2282 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2283 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2284 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2285 for (Uuid subnet : routerSubnets) {
2286 IpVersionChoice version = NeutronvpnUtils
2287 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2288 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2289 addSubnetToVpn(vpnId, subnet, null);
2291 addSubnetToVpn(vpnId, subnet, internetVpnId);
2296 // TODO Clean up the exception handling
2297 @SuppressWarnings("checkstyle:IllegalCatch")
2298 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2300 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2301 boolean vpnInstanceIpVersionsRemoved = false;
2302 IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
2303 for (Uuid subnetId : routerSubnets) {
2304 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
2305 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
2306 vpnInstanceIpVersionsToRemove = vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
2307 .getIpVersionFromString(sn.getSubnetIp()));
2308 vpnInstanceIpVersionsRemoved = true;
2310 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2311 updateVpnForSubnet(vpnId, routerId, subnetId, false);
2314 if (vpnInstanceIpVersionsRemoved) {
2315 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionsToRemove, false);
2317 clearFromVpnMaps(vpnId, routerId, null);
2319 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2320 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2322 } catch (Exception e) {
2323 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2324 .getValue(), vpnId.getValue(), e);
2329 * Parses and associates networks list with given VPN.
2331 * @param vpnId Uuid of given VPN.
2332 * @param networkList List list of network Ids (Uuid), which will be associated.
2333 * @return list of formatted strings with detailed error messages.
2336 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2337 List<String> failedNwList = new ArrayList<>();
2338 HashSet<Uuid> passedNwList = new HashSet<>();
2339 if (networkList.isEmpty()) {
2340 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2341 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2343 return failedNwList;
2345 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2346 if (vpnInstance == null) {
2347 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2348 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2349 + "in ConfigDS", vpnId.getValue()));
2350 return failedNwList;
2353 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2354 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2356 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2357 + "associated with", vpnId.getValue()));
2358 return failedNwList;
2360 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2361 for (Uuid nw : networkList) {
2362 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2363 if (network == null) {
2364 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2365 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2369 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2370 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2371 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2372 nw.getValue(), vpnId.getValue());
2373 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2374 nw.getValue(), vpnId.getValue()));
2377 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2378 if (networkVpnId != null) {
2379 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2380 nw.getValue(), networkVpnId.getValue());
2381 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2382 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2385 if (neutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2386 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2387 nw.getValue(), vpnId.getValue());
2388 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2389 nw.getValue(), vpnId.getValue()));
2392 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2393 if (subnetmapList == null || subnetmapList.isEmpty()) {
2394 passedNwList.add(nw);
2397 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2400 for (Subnetmap subnetmap : subnetmapList) {
2401 Uuid subnetId = subnetmap.getId();
2402 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2403 if (subnetVpnId != null) {
2404 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2405 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2406 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2407 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2410 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(subnetmap, vpnId)) {
2411 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2412 NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp()), true);
2414 if (!neutronvpnUtils.getIsExternal(network)) {
2415 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2417 addSubnetToVpn(vpnId, subnetId, null);
2418 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2420 passedNwList.add(nw);
2423 passedNwList.add(nw);
2425 } catch (ReadFailedException e) {
2426 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2428 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2431 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2432 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2433 return failedNwList;
2436 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2437 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2438 if (vpnOpDataEntry == null) {
2439 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2442 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2445 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2446 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2447 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2449 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2450 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2452 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2455 updateVpnInternetForSubnet(sm, vpnId, true);
2456 if (!vpnOpDataEntry.isIpv6Configured()
2457 && NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp()) == IpVersionChoice.IPV6) {
2458 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2459 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), true);
2466 * Parses and disassociates networks list from given VPN.
2468 * @param vpnId Uuid of given VPN.
2469 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2470 * @return list of formatted strings with detailed error messages.
2473 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2474 List<String> failedNwList = new ArrayList<>();
2475 HashSet<Uuid> passedNwList = new HashSet<>();
2476 if (networkList.isEmpty()) {
2477 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2478 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2480 return failedNwList;
2482 for (Uuid nw : networkList) {
2483 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2484 if (networkSubnets == null) {
2485 passedNwList.add(nw);
2488 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2489 if (network == null) {
2490 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2491 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2495 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2496 if (networkVpnId == null) {
2497 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2498 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2502 if (!vpnId.equals(networkVpnId)) {
2503 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2504 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2505 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2506 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2510 if (NeutronvpnUtils.getIsExternal(network)) {
2511 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2512 passedNwList.add(nw);
2515 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2516 nw.getValue(), vpnId.getValue());
2517 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2522 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2523 for (Uuid subnet : networkSubnets) {
2524 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2525 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(subnetmap, vpnId)) {
2526 IpVersionChoice ipVersionsToRemove = IpVersionChoice.UNDEFINED;
2527 IpVersionChoice ipVersion = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2528 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
2529 ipVersionsToRemove.addVersion(ipVersion), false);
2531 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2533 removeSubnetFromVpn(vpnId, subnet, null);
2534 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2536 passedNwList.add(nw);
2539 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2540 LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
2542 return failedNwList;
2545 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2546 if (!removeExternalNetworkFromVpn(extNet)) {
2549 // check, if there is another Provider Networks associated with given VPN
2550 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2551 if (vpnNets != null) {
2552 for (Uuid netId : vpnNets) {
2553 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2554 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2555 + "{}", vpnId.getValue(), netId.getValue());
2560 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2561 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2562 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2563 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet)) {
2564 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2566 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2569 updateVpnInternetForSubnet(sm, vpnId, false);
2571 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2572 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}", vpnId.getValue());
2573 neutronvpnUtils.updateVpnInstanceWithFallback(vpnId.getValue(), false);
2578 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2581 // TODO Clean up the exception handling
2582 @SuppressWarnings("checkstyle:IllegalCatch")
2583 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2585 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2586 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2587 StringBuilder returnMsg = new StringBuilder();
2588 Uuid vpnId = input.getVpnId();
2591 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2592 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2593 input.getNetworkId().toString());
2594 List<Uuid> netIds = input.getNetworkId();
2595 if (netIds != null && !netIds.isEmpty()) {
2596 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2597 if (!failed.isEmpty()) {
2598 returnMsg.append(failed);
2602 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2604 if (returnMsg.length() != 0) {
2605 opBuilder.setResponse(
2606 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2607 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2608 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2610 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2612 } catch (Exception ex) {
2613 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2614 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2615 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2617 LOG.debug("associateNetworks returns..");
2622 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2625 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2627 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2628 LOG.debug("associateRouter {}", input);
2629 StringBuilder returnMsg = new StringBuilder();
2630 Uuid vpnId = input.getVpnId();
2631 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2632 routerIds = input.getRouterIds();
2633 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2634 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2635 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2636 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2637 .RouterIds routerId : routerIds) {
2638 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2639 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2640 if (vpnMap != null) {
2642 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2643 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2644 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2645 .append(routerId.getRouterId());
2646 } else if (extVpnId != null) {
2647 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2648 + "another VPN ").append(extVpnId.getValue());
2650 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2651 routerId.getRouterId());
2652 associateRouterToVpn(vpnId, routerId.getRouterId());
2655 returnMsg.append("router not found : ").append(routerId.getRouterId());
2658 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2660 if (returnMsg.length() != 0) {
2661 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2662 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2663 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2665 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2668 LOG.debug("associateRouter returns..");
2673 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2676 // TODO Clean up the exception handling
2677 @SuppressWarnings("checkstyle:IllegalCatch")
2678 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2679 GetFixedIPsForNeutronPortInput input) {
2680 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2681 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2682 Uuid portId = input.getPortId();
2683 StringBuilder returnMsg = new StringBuilder();
2685 List<String> fixedIPList = new ArrayList<>();
2686 Port port = neutronvpnUtils.getNeutronPort(portId);
2688 List<FixedIps> fixedIPs = port.getFixedIps();
2689 for (FixedIps ip : fixedIPs) {
2690 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
2693 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2695 if (returnMsg.length() != 0) {
2696 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2698 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2699 returnMsg)).build());
2701 opBuilder.setFixedIPs(fixedIPList);
2702 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2704 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2706 } catch (Exception ex) {
2707 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2708 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2709 portId.getValue(), ex.getMessage(), ex)).build());
2715 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2718 // TODO Clean up the exception handling
2719 @SuppressWarnings("checkstyle:IllegalCatch")
2720 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2722 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2723 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2725 LOG.debug("dissociateNetworks {}", input);
2726 StringBuilder returnMsg = new StringBuilder();
2727 Uuid vpnId = input.getVpnId();
2730 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2731 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2732 input.getNetworkId().toString());
2733 List<Uuid> netIds = input.getNetworkId();
2734 if (netIds != null && !netIds.isEmpty()) {
2735 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2736 if (!failed.isEmpty()) {
2737 returnMsg.append(failed);
2741 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2743 if (returnMsg.length() != 0) {
2744 opBuilder.setResponse(
2745 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2746 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2748 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2750 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2752 } catch (Exception ex) {
2753 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2754 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2755 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2757 LOG.debug("dissociateNetworks returns..");
2762 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2765 // TODO Clean up the exception handling
2766 @SuppressWarnings("checkstyle:IllegalCatch")
2767 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2769 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2771 LOG.debug("dissociateRouter {}", input);
2772 StringBuilder returnMsg = new StringBuilder();
2773 Uuid vpnId = input.getVpnId();
2774 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2775 .RouterIds> routerIdList = input.getRouterIds();
2776 String routerIdsString = "";
2777 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2778 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2779 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2780 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2781 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2782 .RouterIds routerId : routerIdList) {
2784 if (routerId != null) {
2785 routerIdsString += routerId.getRouterId() + ", ";
2786 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2788 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2789 if (routerVpnId == null) {
2790 returnMsg.append("input router ").append(routerId.getRouterId())
2791 .append(" not associated to any vpn yet");
2792 } else if (vpnId.equals(routerVpnId)) {
2793 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2795 returnMsg.append("input router ").append(routerId.getRouterId())
2796 .append(" associated to vpn ")
2797 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2800 returnMsg.append("router not found : ").append(routerId.getRouterId());
2803 if (returnMsg.length() != 0) {
2804 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2805 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2806 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2807 returnMsg)).build());
2809 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2811 } catch (Exception ex) {
2812 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2813 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2814 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2818 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2821 LOG.debug("dissociateRouter returns..");
2825 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2826 // check if the router is associated to some VPN
2827 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2828 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2829 if (vpnId != null) {
2830 // remove existing external vpn interfaces
2831 for (Uuid subnetId : routerSubnetIds) {
2832 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2834 clearFromVpnMaps(vpnId, routerId, null);
2836 // remove existing internal vpn interfaces
2837 for (Uuid subnetId : routerSubnetIds) {
2838 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2841 // delete entire vpnMaps node for internal VPN
2842 deleteVpnMapsNode(routerId);
2844 // delete vpn-instance for internal VPN
2845 deleteVpnInstance(routerId);
2848 protected Subnet getNeutronSubnet(Uuid subnetId) {
2849 return neutronvpnUtils.getNeutronSubnet(subnetId);
2852 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2853 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2855 return sn.getGatewayIp();
2861 protected Network getNeutronNetwork(Uuid networkId) {
2862 return neutronvpnUtils.getNeutronNetwork(networkId);
2865 protected Port getNeutronPort(String name) {
2866 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2869 protected Port getNeutronPort(Uuid portId) {
2870 return neutronvpnUtils.getNeutronPort(portId);
2873 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2874 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2877 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2878 return neutronvpnUtils.getNetworksForVpn(vpnId);
2882 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2884 * @return a List of String to be printed on screen
2885 * @throws ReadFailedException if there was a problem reading from the data store
2887 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2888 List<String> result = new ArrayList<>();
2889 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2891 result.add("-------------------------------------------------------------------------------------------");
2892 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2894 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2895 if (ports.isPresent() && ports.get().getPort() != null) {
2896 for (Port port : ports.get().getPort()) {
2897 List<FixedIps> fixedIPs = port.getFixedIps();
2898 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2899 List<String> ipList = new ArrayList<>();
2900 for (FixedIps fixedIp : fixedIPs) {
2901 IpAddress ipAddress = fixedIp.getIpAddress();
2902 if (ipAddress.getIpv4Address() != null) {
2903 ipList.add(ipAddress.getIpv4Address().getValue());
2905 ipList.add(ipAddress.getIpv6Address().getValue());
2908 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2909 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
2910 ipList.toString()));
2912 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2913 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2922 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2924 * @param vpnuuid Uuid of the VPN whose config must be shown
2925 * @return formatted output list
2926 * @throws InterruptedException if there was a thread related problem getting the data to display
2927 * @throws ExecutionException if there was any other problem getting the data to display
2929 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2930 List<String> result = new ArrayList<>();
2931 if (vpnuuid == null) {
2933 result.add("Displaying VPN config for all VPNs");
2934 result.add("To display VPN config for a particular VPN, use the following syntax");
2935 result.add(getshowVpnConfigCLIHelp());
2937 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2938 if (rpcResult.isSuccessful()) {
2940 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2942 result.add(String.format(" %-80s ", "Import-RTs"));
2944 result.add(String.format(" %-80s ", "Export-RTs"));
2946 result.add(String.format(" %-76s ", "Subnet IDs"));
2948 result.add("------------------------------------------------------------------------------------");
2950 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2951 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2952 .rev150602.VpnInstance vpn : vpnList) {
2953 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2955 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2956 vpn.getRouteDistinguisher()));
2958 result.add(String.format(" %-80s ", vpn.getImportRT()));
2960 result.add(String.format(" %-80s ", vpn.getExportRT()));
2963 Uuid vpnid = vpn.getId();
2964 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
2965 if (!subnetList.isEmpty()) {
2966 for (Uuid subnetuuid : subnetList) {
2967 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2970 result.add(String.format(" %-76s ", "\" \""));
2973 result.add("----------------------------------------");
2977 String errortag = rpcResult.getErrors().iterator().next().getTag();
2978 if (Objects.equals(errortag, "")) {
2980 result.add("No VPN has been configured yet");
2981 } else if (Objects.equals(errortag, "invalid-value")) {
2983 result.add("VPN " + vpnuuid.getValue() + " is not present");
2985 result.add("error getting VPN info : " + rpcResult.getErrors());
2986 result.add(getshowVpnConfigCLIHelp());
2992 protected void createExternalVpnInterfaces(Uuid extNetId) {
2993 if (extNetId == null) {
2994 LOG.error("createExternalVpnInterfaces: external network is null");
2998 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2999 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3000 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3004 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3005 for (String elanInterface : extElanInterfaces) {
3006 createExternalVpnInterface(extNetId, elanInterface, tx);
3008 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3011 // TODO Clean up the exception handling
3012 @SuppressWarnings("checkstyle:IllegalCatch")
3013 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3014 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3015 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3016 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3019 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3020 for (String elanInterface : extElanInterfaces) {
3021 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3022 .buildVpnInterfaceIdentifier(elanInterface);
3023 LOG.info("Removing vpn interface {}", elanInterface);
3024 tx.delete(vpnIfIdentifier);
3026 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3029 private void createExternalVpnInterface(Uuid vpnId, String infName,
3030 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3031 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null,
3032 false /* not a router iface */, wrtConfigTxn);
3035 // TODO Clean up the exception handling
3036 @SuppressWarnings("checkstyle:IllegalCatch")
3037 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName, Adjacencies adjacencies,
3038 Boolean isRouterInterface, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3039 if (vpnIdList.isEmpty() || infName == null) {
3040 LOG.error("vpn id or interface is null");
3043 if (wrtConfigTxn == null) {
3044 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3045 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, isRouterInterface, tx)), LOG,
3046 "Error writing VPN interface");
3049 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3050 for (Uuid vpnId: vpnIdList) {
3051 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3052 AssociatedSubnetType.V4AndV6Subnets);
3053 vpnIdListStruct.add(vpnInstance);
3056 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3057 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3059 .setVpnInstanceNames(vpnIdListStruct)
3060 .setRouterInterface(isRouterInterface);
3061 if (adjacencies != null) {
3062 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3064 VpnInterface vpnIf = vpnb.build();
3066 LOG.info("Creating vpn interface {}", vpnIf);
3067 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3068 } catch (Exception ex) {
3069 LOG.error("Creation of vpninterface {} failed", infName, ex);
3073 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3074 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
3075 if (vpnId == null || infName == null) {
3076 LOG.error("vpn id or interface is null");
3079 if (wrtConfigTxn == null) {
3080 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3081 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3082 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3083 }), LOG, "Error updating VPN interface with adjacencies");
3087 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3088 boolean isLockAcquired = false;
3090 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3091 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3092 .syncReadOptional(dataBroker, LogicalDatastoreType
3093 .CONFIGURATION, vpnIfIdentifier);
3094 if (optionalVpnInterface.isPresent()) {
3095 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3096 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3098 if (adjacencies == null) {
3099 if (isLockAcquired) {
3100 interfaceLock.unlock(infName);
3104 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3105 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3106 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3107 optionalVpnInterface.get().getVpnInstanceNames());
3108 if (listVpnInstances.isEmpty() || !VpnHelper
3109 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3110 VpnInstanceNames vpnInstance = VpnHelper
3111 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3112 listVpnInstances.add(vpnInstance);
3113 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3116 VpnInstanceNames vpnInstance = VpnHelper
3117 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3118 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3119 listVpnInstances.add(vpnInstance);
3120 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3122 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3123 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3125 } catch (IllegalStateException | ReadFailedException ex) {
3126 LOG.error("Update of vpninterface {} failed", infName, ex);
3128 if (isLockAcquired) {
3129 interfaceLock.unlock(infName);
3134 private String getshowVpnConfigCLIHelp() {
3135 StringBuilder help = new StringBuilder("Usage:");
3136 help.append("display vpn-config [-vid/--vpnid <id>]");
3137 return help.toString();
3140 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3141 InterruptedException {
3142 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3143 .setVpnId(vpnId).build();
3144 LOG.info("publishing notification upon association of router to VPN");
3145 notificationPublishService.putNotification(routerAssociatedToVpn);
3148 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3149 InterruptedException {
3150 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3151 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3152 LOG.info("publishing notification upon disassociation of router from VPN");
3153 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3156 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3157 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3161 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3162 return neutronEvpnManager.createEVPN(input);
3166 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3167 return neutronEvpnManager.getEVPN(input);
3171 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3172 return neutronEvpnManager.deleteEVPN(input);
3175 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3176 Uuid extNetId = extNet.getUuid();
3177 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3178 .child(Networks.class, new NetworksKey(extNetId)).build();
3181 Optional<Networks> optionalExtNets =
3182 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3184 if (!optionalExtNets.isPresent()) {
3185 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3186 extNetId.getValue());
3189 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3190 builder.setVpnid(vpnId);
3191 Networks networks = builder.build();
3192 // Add Networks object to the ExternalNetworks list
3193 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3194 extNetId.getValue());
3195 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3198 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3199 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3200 extNetId.getValue(), ex);
3205 private boolean removeExternalNetworkFromVpn(Network extNet) {
3206 Uuid extNetId = extNet.getUuid();
3207 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3208 .child(Networks.class, new NetworksKey(extNetId)).build();
3210 Optional<Networks> optionalNets =
3211 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3213 NetworksBuilder builder = null;
3214 if (optionalNets.isPresent()) {
3215 builder = new NetworksBuilder(optionalNets.get());
3217 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3218 extNetId.getValue());
3221 builder.setVpnid(null);
3222 Networks networks = builder.build();
3223 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3224 extNetId.getValue());
3225 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3227 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3228 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3229 extNetId.getValue(), ex);
3234 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3235 Optional<String> existingVpnName = Optional.of(primaryRd);
3236 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3238 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3239 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3240 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3241 } catch (ReadFailedException e) {
3242 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3244 /*Read failed. We don't know if a VPN exists or not.
3245 * Return primaryRd to halt caller execution, to be safe.*/
3246 return existingVpnName;
3248 if (vpnInstanceOpDataOptional.isPresent()) {
3249 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3251 existingVpnName = Optional.absent();
3253 return existingVpnName;
3256 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3257 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3260 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3261 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3264 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3265 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3268 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3269 String message = tuple.getMessage();
3270 logger.accept(message);