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;
13 import static org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils.requireNonNullElse;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.JdkFutureAdapters;
20 import com.google.common.util.concurrent.ListenableFuture;
21 import com.google.common.util.concurrent.MoreExecutors;
22 import com.google.common.util.concurrent.SettableFuture;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
32 import java.util.Map.Entry;
33 import java.util.Objects;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.TimeUnit;
39 import java.util.function.Consumer;
40 import javax.annotation.Nonnull;
41 import javax.annotation.Nullable;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
45 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
46 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
50 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
51 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
52 import org.opendaylight.genius.infra.Datastore.Configuration;
53 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
54 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
55 import org.opendaylight.genius.infra.TypedWriteTransaction;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
58 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
59 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
60 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
61 import org.opendaylight.netvirt.elanmanager.api.IElanService;
62 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
63 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
64 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
65 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
66 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
67 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
68 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
72 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
73 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
74 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
75 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.BgpvpnType;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
181 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
182 import org.opendaylight.yangtools.yang.common.RpcError;
183 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
184 import org.opendaylight.yangtools.yang.common.RpcResult;
185 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
186 import org.slf4j.Logger;
187 import org.slf4j.LoggerFactory;
188 import org.slf4j.helpers.FormattingTuple;
189 import org.slf4j.helpers.MessageFormatter;
192 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
194 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
195 private static long LOCK_WAIT_TIME = 10L;
197 private final DataBroker dataBroker;
198 private final ManagedNewTransactionRunner txRunner;
199 private final NotificationPublishService notificationPublishService;
200 private final VpnRpcService vpnRpcService;
201 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
202 private final IElanService elanService;
203 private final NeutronvpnConfig neutronvpnConfig;
204 private final NeutronEvpnManager neutronEvpnManager;
205 private final NeutronEvpnUtils neutronEvpnUtils;
206 private final JobCoordinator jobCoordinator;
207 private final NeutronvpnUtils neutronvpnUtils;
208 private final IVpnManager vpnManager;
209 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
210 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
211 private final KeyedLocks<Uuid> vpnLock = new KeyedLocks<>();
212 private final KeyedLocks<String> interfaceLock = new KeyedLocks<>();
215 public NeutronvpnManager(
216 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
217 final VpnRpcService vpnRpcSrv, final IElanService elanService,
218 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
219 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
220 final JobCoordinator jobCoordinator,
221 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
222 this.dataBroker = dataBroker;
223 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
224 notificationPublishService = notiPublishService;
225 vpnRpcService = vpnRpcSrv;
226 this.elanService = elanService;
227 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
228 this.neutronvpnConfig = neutronvpnConfig;
229 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
230 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
231 this.jobCoordinator = jobCoordinator;
232 this.neutronvpnUtils = neutronvpnUtils;
233 this.vpnManager = vpnManager;
240 public void close() {
241 LOG.info("{} close", getClass().getSimpleName());
244 private void configureFeatures() throws TransactionCommitFailedException {
245 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
246 Neutron.class).child(Features.class).child(
247 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
248 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
250 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
251 } catch (OptimisticLockFailedException e) {
252 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
254 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
255 Neutron.class).child(Features.class).child(
256 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
257 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
259 SingleTransactionDataBroker.syncWrite(
260 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
261 } catch (OptimisticLockFailedException e) {
262 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
266 public String getOpenDaylightVniRangesConfig() {
267 return neutronvpnConfig.getOpendaylightVniRanges();
270 // TODO Clean up the exception handling
271 @SuppressWarnings("checkstyle:IllegalCatch")
272 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
273 @Nullable NetworkAttributes.NetworkType networkType, long segmentationId) {
275 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
276 synchronized (subnetId.getValue().intern()) {
277 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
278 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
279 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
280 if (sn.isPresent()) {
281 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
282 subnetId.getValue());
285 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
286 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
287 .setNetworkType(networkType).setSegmentationId(segmentationId);
288 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
289 subnetId.getValue());
290 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
291 subnetMapIdentifier, subnetmapBuilder.build());
293 } catch (TransactionCommitFailedException | ReadFailedException e) {
294 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
296 // check if there are ports to update for already created Subnetmap node
297 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
298 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
299 if (entry.getValue().getValue().equals(subnetId.getValue())) {
300 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
301 unprocessedPortsMap.remove(entry.getKey());
307 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
308 @Nullable Uuid internetvpnId) {
309 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
310 .child(Subnetmap.class, new SubnetmapKey(subnetId))
313 synchronized (subnetId.getValue().intern()) {
314 Optional<Subnetmap> sn =
315 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
317 if (!sn.isPresent()) {
318 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
321 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
322 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
323 if (routerId != null) {
324 builder.setRouterId(routerId);
327 builder.setVpnId(vpnId);
329 if (neutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
330 builder.setInternetVpnId(internetvpnId);
332 Subnetmap subnetmap = builder.build();
333 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
334 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
337 } catch (ReadFailedException | TransactionCommitFailedException e) {
338 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
343 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
344 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
345 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
346 InstanceIdentifier<Subnetmap> id =
347 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
349 synchronized (subnetId.getValue().intern()) {
350 Optional<Subnetmap> sn =
351 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
353 if (!sn.isPresent()) {
354 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
355 subnetId.getValue());
358 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
359 subnetId.getValue());
360 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
361 builder.setRouterId(routerId);
362 builder.setRouterInterfacePortId(routerInterfacePortId);
363 builder.setRouterIntfMacAddress(routerIntfMacAddress);
364 builder.setRouterInterfaceFixedIp(fixedIp);
366 builder.setVpnId(vpnId);
368 Subnetmap subnetmap = builder.build();
369 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
370 subnetId.getValue());
371 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
373 } catch (ReadFailedException | TransactionCommitFailedException e) {
374 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
375 subnetId.getValue(), e);
379 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
380 @Nullable Uuid directPortId) {
381 Subnetmap subnetmap = null;
382 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
383 new SubnetmapKey(subnetId)).build();
384 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
386 synchronized (subnetId.getValue().intern()) {
387 Optional<Subnetmap> sn =
388 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
390 if (sn.isPresent()) {
391 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
392 if (null != portId) {
393 List<Uuid> portList = builder.getPortList();
394 if (null == portList) {
395 portList = new ArrayList<>();
397 portList.add(portId);
398 builder.setPortList(portList);
399 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
400 subnetId.getValue(), portId.getValue());
402 if (null != directPortId) {
403 List<Uuid> directPortList = builder.getDirectPortList();
404 if (null == directPortList) {
405 directPortList = new ArrayList<>();
407 directPortList.add(directPortId);
408 builder.setDirectPortList(directPortList);
409 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
410 directPortId.getValue());
412 subnetmap = builder.build();
413 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
416 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
417 + "cache ", subnetId.getValue(), portId.getValue());
418 unprocessedPortsMap.put(portId, subnetId);
421 } catch (ReadFailedException | TransactionCommitFailedException e) {
422 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
427 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
428 Uuid vpnId, @Nullable Uuid portId) {
429 Subnetmap subnetmap = null;
430 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
431 .child(Subnetmap.class, new SubnetmapKey(subnetId))
434 synchronized (subnetId.getValue().intern()) {
435 Optional<Subnetmap> sn =
436 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
438 if (sn.isPresent()) {
439 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
440 if (routerId != null) {
441 builder.setRouterId(null);
443 if (networkId != null) {
444 builder.setNetworkId(null);
447 builder.setVpnId(null);
449 builder.setInternetVpnId(null);
450 if (portId != null && builder.getPortList() != null) {
451 List<Uuid> portList = builder.getPortList();
452 portList.remove(portId);
453 builder.setPortList(portList);
456 subnetmap = builder.build();
457 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
458 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
461 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
464 } catch (ReadFailedException | TransactionCommitFailedException e) {
465 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
471 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
472 @Nullable Uuid directPortId) {
473 Subnetmap subnetmap = null;
474 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
475 new SubnetmapKey(subnetId)).build();
477 synchronized (subnetId.getValue().intern()) {
478 Optional<Subnetmap> sn =
479 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
481 if (sn.isPresent()) {
482 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
483 if (null != portId && null != builder.getPortList()) {
484 List<Uuid> portList = builder.getPortList();
485 portList.remove(portId);
486 builder.setPortList(portList);
487 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
488 subnetId.getValue());
490 if (null != directPortId && null != builder.getDirectPortList()) {
491 List<Uuid> directPortList = builder.getDirectPortList();
492 directPortList.remove(directPortId);
493 builder.setDirectPortList(directPortList);
494 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
495 .getValue(), subnetId.getValue());
497 subnetmap = builder.build();
498 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
501 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
504 } catch (ReadFailedException | TransactionCommitFailedException e) {
505 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
506 subnetId.getValue(), e);
511 // TODO Clean up the exception handling
512 @SuppressWarnings("checkstyle:IllegalCatch")
513 protected void deleteSubnetMapNode(Uuid subnetId) {
514 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
515 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
516 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
518 synchronized (subnetId.getValue().intern()) {
519 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
520 subnetMapIdentifier);
522 } catch (TransactionCommitFailedException e) {
523 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
527 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
528 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
529 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
531 Optional<VpnInstance> vpnInstanceConfig =
532 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
534 if (!vpnInstanceConfig.isPresent()) {
535 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
538 VpnInstance vpnInstance = vpnInstanceConfig.get();
539 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
540 if (vpnInstance.getIpv4Family() != null) {
541 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
542 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
544 if (vpnInstance.getIpv6Family() != null) {
545 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
546 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
548 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
549 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
550 updateVpnInstanceBuilder.build());
551 } catch (ReadFailedException | TransactionCommitFailedException ex) {
552 LOG.warn("Error configuring feature ", ex);
556 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
557 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
558 String vpnName = vpnId.getValue();
559 VpnInstanceBuilder builder = null;
560 List<VpnTarget> vpnTargetList = new ArrayList<>();
561 boolean isLockAcquired = false;
562 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
563 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
565 Optional<VpnInstance> optionalVpn =
566 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
568 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
569 if (optionalVpn.isPresent()) {
570 builder = new VpnInstanceBuilder(optionalVpn.get());
571 LOG.debug("updating existing vpninstance node");
573 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
574 .setType(type).setL3vni(l3vni);
576 if (irt != null && !irt.isEmpty()) {
577 if (ert != null && !ert.isEmpty()) {
578 List<String> commonRT = new ArrayList<>(irt);
579 commonRT.retainAll(ert);
581 for (String common : commonRT) {
584 VpnTarget vpnTarget =
585 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
586 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
587 vpnTargetList.add(vpnTarget);
590 for (String importRT : irt) {
591 VpnTarget vpnTarget =
592 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
593 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
594 vpnTargetList.add(vpnTarget);
598 if (ert != null && !ert.isEmpty()) {
599 for (String exportRT : ert) {
600 VpnTarget vpnTarget =
601 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
602 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
603 vpnTargetList.add(vpnTarget);
607 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
609 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
610 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
612 if (rd != null && !rd.isEmpty()) {
613 ipv4vpnBuilder.setRouteDistinguisher(rd);
614 ipv6vpnBuilder.setRouteDistinguisher(rd);
617 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
618 builder.setIpv4Family(ipv4vpnBuilder.build());
620 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
621 builder.setIpv6Family(ipv6vpnBuilder.build());
623 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
624 builder.setIpv4Family(ipv4vpnBuilder.build());
626 VpnInstance newVpn = builder.build();
627 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
628 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
629 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
631 } catch (ReadFailedException | TransactionCommitFailedException e) {
632 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
634 if (isLockAcquired) {
635 vpnLock.unlock(vpnId);
640 private void deleteVpnMapsNode(Uuid vpnId) {
641 boolean isLockAcquired = false;
642 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
643 .child(VpnMap.class, new VpnMapKey(vpnId))
645 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
647 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
648 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
649 } catch (TransactionCommitFailedException e) {
650 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
652 if (isLockAcquired) {
653 vpnLock.unlock(vpnId);
658 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
659 @Nullable List<Uuid> networks) {
660 VpnMapBuilder builder;
661 boolean isLockAcquired = false;
662 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
663 .child(VpnMap.class, new VpnMapKey(vpnId))
666 Optional<VpnMap> optionalVpnMap =
667 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
669 if (optionalVpnMap.isPresent()) {
670 builder = new VpnMapBuilder(optionalVpnMap.get());
672 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
676 builder.setName(name);
678 if (tenantId != null) {
679 builder.setTenantId(tenantId);
681 if (router != null) {
682 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
683 List<RouterIds> rtrIds = builder.getRouterIds();
684 if (rtrIds == null) {
685 rtrIds = Collections.singletonList(vpnRouterId);
687 rtrIds.add(vpnRouterId);
689 builder.setRouterIds(rtrIds);
691 if (networks != null) {
692 List<Uuid> nwList = builder.getNetworkIds();
693 if (nwList == null) {
694 nwList = new ArrayList<>();
696 nwList.addAll(networks);
697 builder.setNetworkIds(nwList);
700 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
701 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
702 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
704 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
705 } catch (ReadFailedException | TransactionCommitFailedException e) {
706 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
708 if (isLockAcquired) {
709 vpnLock.unlock(vpnId);
714 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
715 boolean isLockAcquired = false;
716 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
717 .child(VpnMap.class, new VpnMapKey(vpnId))
719 Optional<VpnMap> optionalVpnMap;
722 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
724 } catch (ReadFailedException e) {
725 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
728 if (optionalVpnMap.isPresent()) {
729 VpnMap vpnMap = optionalVpnMap.get();
730 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
731 List<RouterIds> rtrIds = vpnMap.getRouterIds();
732 if (rtrIds == null) {
733 rtrIds = new ArrayList<>();
735 if (routerId != null) {
736 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
737 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
738 vpnMapBuilder.setRouterIds(rtrIds);
740 // remove entire node in case of internal VPN
741 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
742 LOG.debug("removing vpnMaps node: {} ", vpnId);
743 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
745 } catch (TransactionCommitFailedException e) {
746 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
748 if (isLockAcquired) {
749 vpnLock.unlock(vpnId);
753 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
754 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
755 vpnMapBuilder.setRouterIds(rtrIds);
756 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
759 if (networkIds != null) {
760 List<Uuid> vpnNw = vpnMap.getNetworkIds();
761 vpnNw.removeAll(networkIds);
762 if (vpnNw.isEmpty()) {
763 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
764 vpnMapBuilder.setNetworkIds(null);
766 vpnMapBuilder.setNetworkIds(vpnNw);
771 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
772 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
773 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
774 vpnMapBuilder.build());
775 } catch (TransactionCommitFailedException e) {
776 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
778 if (isLockAcquired) {
779 vpnLock.unlock(vpnId);
783 LOG.error("VPN : {} not found", vpnId.getValue());
785 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
788 private void deleteVpnInstance(Uuid vpnId) {
789 boolean isLockAcquired = false;
790 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
791 .child(VpnInstance.class,
792 new VpnInstanceKey(vpnId.getValue()))
795 isLockAcquired = vpnLock.tryLock(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
796 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
797 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
798 } catch (TransactionCommitFailedException e) {
799 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
801 if (isLockAcquired) {
802 vpnLock.unlock(vpnId);
807 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
808 TypedWriteTransaction<Configuration> wrtConfigTxn,
809 @Nullable Subnetmap sn, @Nullable VpnInterface vpnIface) {
810 List<Adjacency> adjList = new ArrayList<>();
811 if (vpnIface != null) {
812 adjList = vpnIface.augmentation(Adjacencies.class).getAdjacency();
814 String infName = port.getUuid().getValue();
815 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
816 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
817 String ipValue = ip.getIpAddress().stringValue();
818 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
819 if (sn != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix, sn.getSubnetIp(), false)) {
822 Subnetmap snTemp = sn != null ? sn : neutronvpnUtils.getSubnetmap(ip.getSubnetId());
823 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
825 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
826 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
827 //Create Neutron port adjacency if VPN presence is existing for subnet
828 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
829 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
830 .setSubnetId(ip.getSubnetId()).build();
831 if (!adjList.contains(vmAdj)) {
835 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
836 if (snTemp != null && snTemp.getInternetVpnId() != null) {
837 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
838 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
840 if (routerId != null) {
841 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
842 if (rtr != null && rtr.getRoutes() != null) {
843 List<Routes> routeList = rtr.getRoutes();
844 // create extraroute Adjacence for each ipValue,
845 // because router can have IPv4 and IPv6 subnet ports, or can have
846 // more that one IPv4 subnet port or more than one IPv6 subnet port
847 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
848 if (!erAdjList.isEmpty()) {
849 adjList.addAll(erAdjList);
854 return new AdjacenciesBuilder().setAdjacency(adjList).build();
857 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
858 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
859 boolean isRouterInterface = false;
860 if (port.getDeviceOwner() != null) {
861 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
863 String infName = port.getUuid().getValue();
864 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
865 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
866 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, null, vpnIface);
867 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
868 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
871 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
872 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
873 String infName = port.getUuid().getValue();
874 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
875 Optional<VpnInterface> optionalVpnInterface = null;
876 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
877 vpnId, internetVpnId, infName);
879 optionalVpnInterface = SingleTransactionDataBroker
880 .syncReadOptional(dataBroker, LogicalDatastoreType
881 .CONFIGURATION, vpnIfIdentifier);
882 } catch (ReadFailedException e) {
883 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
886 if (!optionalVpnInterface.isPresent()) {
889 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
890 sn != null ? sn.getSubnetIp() : "null");
891 List<Adjacency> vpnAdjsList =
892 requireNonNullElse(optionalVpnInterface.get().augmentation(Adjacencies.class).getAdjacency(),
893 Collections.emptyList());
894 List<Adjacency> updatedAdjsList = new ArrayList<>();
895 boolean isIpFromAnotherSubnet = false;
896 for (Adjacency adj : vpnAdjsList) {
897 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
898 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
899 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
900 isIpFromAnotherSubnet = true;
902 updatedAdjsList.add(adj);
905 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
906 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
909 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
910 String.valueOf(adjString), wrtConfigTxn);
912 if (internetVpnId != null) {
913 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
914 String.valueOf(adjString), wrtConfigTxn);
917 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
918 && sn.getRouterId() != null) {
919 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
920 if (rtr != null && rtr.getRoutes() != null) {
921 List<Routes> extraRoutesToRemove = new ArrayList<>();
922 for (Routes rt: rtr.getRoutes()) {
923 if (rt.getNexthop().toString().equals(adjString)) {
924 extraRoutesToRemove.add(rt);
928 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
929 extraRoutesToRemove, vpnId);
930 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
932 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
937 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(updatedAdjsList).build();
939 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
941 if (!isIpFromAnotherSubnet) {
942 // no more subnetworks for neutron port
943 if (sn != null && sn.getRouterId() != null) {
944 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
946 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
952 // TODO Clean up the exception handling
953 @SuppressWarnings("checkstyle:IllegalCatch")
954 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
955 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
956 if (wrtConfigTxn == null) {
957 ListenableFutures.addErrorLogging(
958 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
959 tx -> deleteVpnInterface(infName, vpnId, tx)),
960 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
964 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
965 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
966 Optional<VpnInterface> optionalVpnInterface;
968 optionalVpnInterface =
969 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
971 } catch (ReadFailedException ex) {
972 LOG.error("Error during deletion of vpninterface {}", infName, ex);
975 if (!optionalVpnInterface.isPresent()) {
976 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
980 VpnInterface vpnInterface = optionalVpnInterface.get();
981 List<VpnInstanceNames> vpnList = vpnInterface.getVpnInstanceNames();
983 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId, vpnList)) {
984 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId, vpnList);
985 if (!vpnList.isEmpty()) {
986 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
987 + "List not empty", infName);
990 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
991 .setVpnInstanceNames(vpnList);
992 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
996 LOG.debug("Deleting vpn interface {}", infName);
997 wrtConfigTxn.delete(vpnIfIdentifier);
1000 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1001 TypedWriteTransaction<Configuration> writeConfigTxn,
1003 if (vpnId == null || port == null) {
1006 String infName = port.getUuid().getValue();
1007 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1009 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1010 .syncReadOptional(dataBroker, LogicalDatastoreType
1011 .CONFIGURATION, vpnIfIdentifier);
1012 if (optionalVpnInterface.isPresent()) {
1013 List<VpnInstanceNames> listVpn = optionalVpnInterface.get().getVpnInstanceNames();
1015 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1016 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(), listVpn);
1018 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1019 .setVpnInstanceNames(listVpn);
1020 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1021 LOG.debug("Updating vpn interface {}", infName);
1022 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1023 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1024 while (adjacencyIter.hasNext()) {
1025 Adjacency adjacency = adjacencyIter.next();
1026 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1029 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1030 InstanceIdentifier<LearntVpnVipToPort> id =
1031 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1032 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1033 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1034 LogicalDatastoreType.OPERATIONAL, id);
1035 if (optionalVpnVipToPort.isPresent()) {
1036 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1038 if (listVpn == null || listVpn.isEmpty()) {
1039 adjacencyIter.remove();
1041 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1042 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1043 mipToQuery, infName, vpnId.getValue());
1046 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1047 String ipValue = ip.getIpAddress().stringValue();
1049 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1052 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1053 ipValue, writeConfigTxn);
1055 if (listVpn == null || listVpn.isEmpty()) {
1056 if (sm != null && sm.getRouterId() != null) {
1057 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1059 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1061 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1064 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1066 } catch (ReadFailedException ex) {
1067 LOG.error("Update of vpninterface {} failed", infName, ex);
1071 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1073 TypedWriteTransaction<Configuration> writeConfigTxn,
1074 boolean isInternetVpn) {
1075 if (vpnId == null || port == null) {
1078 boolean isLockAcquired = false;
1079 String infName = port.getUuid().getValue();
1080 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1083 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
1084 Optional<VpnInterface> optionalVpnInterface =
1085 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1087 if (optionalVpnInterface.isPresent()) {
1088 VpnInstanceNames vpnInstance = VpnHelper
1089 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1090 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface
1091 .get().getVpnInstanceNames());
1092 if (oldVpnId != null
1093 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1094 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1096 if (vpnId.getValue() != null
1097 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1098 listVpn.add(vpnInstance);
1100 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1101 .setVpnInstanceNames(listVpn);
1102 LOG.debug("Updating vpn interface {}", infName);
1103 if (!isBeingAssociated) {
1104 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1105 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
1106 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
1107 while (adjacencyIter.hasNext()) {
1108 Adjacency adjacency = adjacencyIter.next();
1109 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1110 InstanceIdentifier<LearntVpnVipToPort> id =
1111 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1112 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1113 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1114 LogicalDatastoreType.OPERATIONAL, id);
1115 if (optionalVpnVipToPort.isPresent()) {
1116 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1117 + "from VPN {}", infName, vpnId, oldVpnId);
1118 adjacencyIter.remove();
1119 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1121 "Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1122 mipToQuery, infName, vpnId.getValue());
1125 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
1126 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1128 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
1129 String ipValue = ip.getIpAddress().stringValue();
1130 if (oldVpnId != null) {
1131 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1132 ipValue, writeConfigTxn);
1134 if ((NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6)
1135 && (isInternetVpn == true)) {
1139 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1140 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1142 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1144 LOG.error("VPN Interface {} not found", infName);
1146 } catch (ReadFailedException ex) {
1147 LOG.error("Updation of vpninterface {} failed", infName, ex);
1149 if (isLockAcquired) {
1150 interfaceLock.unlock(infName);
1155 public void createL3InternalVpn(Uuid vpn, @Nullable String name, @Nullable Uuid tenant, @Nullable List<String> rd,
1156 @Nullable List<String> irt, @Nullable List<String> ert, @Nullable Uuid router,
1157 @Nullable List<Uuid> networks) {
1159 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(router);
1161 // Update VPN Instance node
1162 updateVpnInstanceNode(vpn, rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
1164 // Update local vpn-subnet DS
1165 updateVpnMaps(vpn, name, router, tenant, networks);
1167 if (router != null) {
1168 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(router, true);
1169 if (existingVpn != null) {
1170 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1171 // if before reboot, router was already associated to VPN, should not proceed associating router to
1172 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1173 // preserved upon reboot.
1174 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1175 // RouterInterfacesMap via #createVPNInterface call.
1176 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1177 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
1180 associateRouterToInternalVpn(vpn, router);
1185 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1186 * specified Neutron Networks and Routers.
1188 * @param vpnId Uuid of the VPN tp be created
1189 * @param name Representative name of the new VPN
1190 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1191 * @param rdList Route-distinguisher for the VPN
1192 * @param irtList A list of Import Route Targets
1193 * @param ertList A list of Export Route Targets
1194 * @param routerIdsList ist of neutron router Id to associate with created VPN
1195 * @param networkList UUID of the neutron network the VPN may be associated to
1196 * @param type Type of the VPN Instance
1197 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1198 * @throws Exception if association of L3VPN failed
1200 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1201 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1202 VpnInstance.Type type, long l3vni) throws Exception {
1204 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1206 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1207 for (Uuid routerId : routerIdsList) {
1208 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1209 ipVersChoices = ipVersChoices.addVersion(vers);
1212 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, type, l3vni, ipVersChoices);
1214 // Please note that router and networks will be filled into VPNMaps
1215 // by subsequent calls here to associateRouterToVpn and
1216 // associateNetworksToVpn
1217 updateVpnMaps(vpnId, name, null, tenantId, null);
1218 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1219 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1222 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1223 for (Uuid routerId : routerIdsList) {
1224 associateRouterToVpn(vpnId, routerId);
1227 if (networkList != null) {
1228 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1229 if (!failStrings.isEmpty()) {
1230 LOG.error("VPN {} association to networks failed for networks: {}. ",
1231 vpnId.getValue(), failStrings.toString());
1232 throw new Exception(failStrings.toString());
1238 * It handles the invocations to the createVPN RPC method.
1241 // TODO Clean up the exception handling
1242 @SuppressWarnings("checkstyle:IllegalCatch")
1243 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1245 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1246 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1247 List<RpcError> errorList = new ArrayList<>();
1248 int failurecount = 0;
1249 int warningcount = 0;
1251 List<L3vpn> vpns = input.getL3vpn();
1253 vpns = Collections.emptyList();
1255 for (L3vpn vpn : vpns) {
1256 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1257 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1258 formatAndLog(LOG::warn,
1259 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1260 vpn.getId().getValue())));
1264 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1265 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1266 formatAndLog(LOG::warn,
1267 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1268 vpn.getId().getValue())));
1272 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
1274 if (vpn.getL3vni() != null) {
1275 l3vni = vpn.getL3vni();
1278 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1279 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1280 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1281 formatAndLog(LOG::warn,
1282 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1283 + "is already configured",
1284 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1288 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1289 if (operationalVpn.isPresent()) {
1290 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1291 formatAndLog(LOG::error,
1292 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1293 + "is still available. Please retry creation of a new vpn with the same RD"
1294 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1295 vpn.getRouteDistinguisher().get(0))));
1299 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1300 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds>
1301 routerIdsList = vpn.getRouterIds();
1302 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1303 routerId : routerIdsList) {
1304 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1305 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1306 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1307 + "{}", vpn.getId(), routerId.getRouterId())));
1311 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1312 if (vpnId != null) {
1313 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1314 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1315 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1316 vpnId.getValue())));
1322 if (vpn.getNetworkIds() != null) {
1323 int initialWarningCount = warningcount;
1324 for (Uuid nw : vpn.getNetworkIds()) {
1325 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1326 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1327 if (network == null) {
1328 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1329 formatAndLog(LOG::warn,
1330 "Creation of L3VPN failed for VPN {} due to network not found {}",
1331 vpn.getId().getValue(), nw.getValue())));
1333 } else if (vpnId != null) {
1334 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1335 formatAndLog(LOG::warn,
1336 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1337 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1338 vpnId.getValue())));
1342 if (warningcount != initialWarningCount) {
1346 List<Uuid> rtrIdsList = new ArrayList<>();
1347 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1348 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1349 rtrId : vpn.getRouterIds()) {
1350 rtrIdsList.add(rtrId.getRouterId());
1354 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1355 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1356 vpn.getTenantId(), vpn.getRouteDistinguisher().toString(), vpn.getImportRT().toString(),
1357 vpn.getExportRT().toString(), rtrIdsList, vpn.getNetworkIds());
1358 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1359 vpn.getImportRT(), vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds(),
1360 vpnInstanceType, l3vni);
1361 } catch (Exception ex) {
1362 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1363 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1368 // if at least one succeeds; result is success
1369 // if none succeeds; result is failure
1370 if (failurecount + warningcount == vpns.size()) {
1371 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1373 List<String> errorResponseList = new ArrayList<>();
1374 if (!errorList.isEmpty()) {
1375 for (RpcError rpcError : errorList) {
1376 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1377 + ", ErrorMessage: " + rpcError.getMessage());
1380 errorResponseList.add("Operation successful with no errors");
1382 opBuilder.setResponse(errorResponseList);
1383 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1389 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1392 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1394 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1395 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1396 Uuid inputVpnId = input.getId();
1397 List<VpnInstance> vpns = new ArrayList<>();
1398 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1401 if (inputVpnId == null) {
1403 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1405 Optional<VpnInstances> optionalVpns =
1406 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1408 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1409 for (VpnInstance vpn : requireNonNullElse(optionalVpns.get().getVpnInstance(),
1410 Collections.<VpnInstance>emptyList())) {
1411 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1412 // from getL3VPN output
1413 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1416 if (vpn.getIpv6Family().getRouteDistinguisher() != null) {
1422 opBuilder.setL3vpnInstances(l3vpnList);
1423 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1427 String name = inputVpnId.getValue();
1428 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1429 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1430 // read VpnInstance Info
1431 Optional<VpnInstance> optionalVpn =
1432 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1434 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1436 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null
1437 || optionalVpn.get().getIpv6Family().getRouteDistinguisher() != null) {
1438 vpns.add(optionalVpn.get());
1441 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1442 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1446 for (VpnInstance vpnInstance : vpns) {
1447 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1448 // create VpnMaps id
1449 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1450 List<String> rd = Collections.EMPTY_LIST;
1451 if (vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
1452 rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1453 } else if (vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
1454 rd = vpnInstance.getIpv6Family().getRouteDistinguisher();
1456 List<String> ertList = new ArrayList<>();
1457 List<String> irtList = new ArrayList<>();
1459 if (vpnInstance.getIpv4Family().getVpnTargets() != null
1460 || vpnInstance.getIpv6Family().getVpnTargets() != null) {
1461 List<VpnTarget> vpnTargetList = Collections.EMPTY_LIST;
1462 if (!vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget().isEmpty()) {
1463 vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1464 } else if (!vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget().isEmpty()) {
1465 vpnTargetList = vpnInstance.getIpv6Family().getVpnTargets().getVpnTarget();
1467 if (!vpnTargetList.isEmpty()) {
1468 for (VpnTarget vpnTarget : vpnTargetList) {
1469 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1470 ertList.add(vpnTarget.getVrfRTValue());
1472 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1473 irtList.add(vpnTarget.getVrfRTValue());
1475 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1476 ertList.add(vpnTarget.getVrfRTValue());
1477 irtList.add(vpnTarget.getVrfRTValue());
1483 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1485 if (vpnInstance.getL3vni() != null) {
1486 l3vpn.setL3vni(vpnInstance.getL3vni());
1488 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1489 .class, new VpnMapKey(vpnId)).build();
1490 Optional<VpnMap> optionalVpnMap =
1491 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1493 if (optionalVpnMap.isPresent()) {
1494 VpnMap vpnMap = optionalVpnMap.get();
1495 List<Uuid> rtrIds = new ArrayList<>();
1496 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1497 for (RouterIds rtrId : vpnMap.getRouterIds()) {
1498 rtrIds.add(rtrId.getRouterId());
1501 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1502 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1503 .setName(vpnMap.getName());
1506 l3vpnList.add(l3vpn.build());
1509 opBuilder.setL3vpnInstances(l3vpnList);
1510 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1512 } catch (ReadFailedException ex) {
1513 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1514 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1520 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1523 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1525 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1526 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1527 List<RpcError> errorList = new ArrayList<>();
1529 int failurecount = 0;
1530 int warningcount = 0;
1531 List<Uuid> vpns = requireNonNullElse(input.getId(), Collections.emptyList());
1532 for (Uuid vpn : vpns) {
1534 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1535 InstanceIdentifier<VpnInstance> vpnIdentifier =
1536 InstanceIdentifier.builder(VpnInstances.class)
1537 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1538 Optional<VpnInstance> optionalVpn =
1539 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1541 if (optionalVpn.isPresent()) {
1544 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1545 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1548 } catch (ReadFailedException ex) {
1549 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1550 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1555 // if at least one succeeds; result is success
1556 // if none succeeds; result is failure
1557 if (failurecount + warningcount == vpns.size()) {
1558 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1560 List<String> errorResponseList = new ArrayList<>();
1561 if (!errorList.isEmpty()) {
1562 for (RpcError rpcError : errorList) {
1563 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1564 + ", ErrorMessage: " + rpcError.getMessage());
1567 errorResponseList.add("Operation successful with no errors");
1569 opBuilder.setResponse(errorResponseList);
1570 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1575 public void createVpnInstanceForSubnet(Uuid subnetId) {
1576 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1577 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1580 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1581 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1582 removeVpn(subnetId);
1585 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1586 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1587 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1588 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1590 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1591 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1594 if (vpnId != null) {
1595 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1596 if (vpnMap == null) {
1597 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1598 + " cannot add subnet {} to VPN", vpnId.getValue(),
1602 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1603 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance.toString());
1604 if (isVpnOfTypeL2(vpnInstance)) {
1605 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1606 NeutronEvpnUtils.Operation.ADD);
1609 if (internetVpnId != null) {
1610 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1611 if (vpnMap == null) {
1612 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1613 + "subnet {} to VPN", internetVpnId.getValue(),
1618 final Uuid internetId = internetVpnId;
1619 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1620 List<Uuid> portList = sn.getPortList();
1621 if (portList != null) {
1622 for (final Uuid portId : portList) {
1623 String vpnInfName = portId.getValue();
1624 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1625 Port port = neutronvpnUtils.getNeutronPort(portId);
1627 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1628 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1631 final Boolean isRouterInterface = port.getDeviceOwner()
1632 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1633 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> singletonList(
1634 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1635 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, sn,
1637 if (vpnIface == null) {
1638 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1639 Set<Uuid> listVpn = new HashSet<>();
1640 if (vpnId != null) {
1643 if (internetId != null) {
1644 listVpn.add(internetId);
1646 writeVpnInterfaceToDs(listVpn,
1647 vpnInfName, portAdj, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
1648 if (sn.getRouterId() != null) {
1649 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1652 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1653 if (vpnId != null) {
1654 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1656 if (internetId != null) {
1657 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1666 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet, @Nullable Uuid internetVpnId) {
1667 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1668 "removeSubnetFromVpn: at least one VPN must be not null");
1669 LOG.debug("Removing subnet {} from vpn {}/{}", subnet.getValue(),
1670 vpnId, internetVpnId);
1671 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnet);
1673 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnet.getValue());
1676 VpnMap vpnMap = null;
1677 VpnInstance vpnInstance = null;
1678 if (vpnId != null) {
1679 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1680 if (vpnMap == null) {
1681 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1682 vpnId.getValue(), subnet.getValue());
1685 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1687 if (internetVpnId == null) {
1688 internetVpnId = sn.getInternetVpnId();
1690 if (internetVpnId != null) {
1691 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1692 if (vpnMap == null) {
1693 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1694 + " from Internet VPN",
1695 internetVpnId.getValue(), subnet.getValue());
1699 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1700 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1701 NeutronEvpnUtils.Operation.DELETE);
1703 boolean subnetVpnAssociation = false;
1704 if (vpnId != null && sn.getVpnId() != null
1705 && sn.getVpnId().getValue().equals(vpnId.getValue())) {
1706 subnetVpnAssociation = true;
1707 } else if (internetVpnId != null && sn.getInternetVpnId() != null
1708 && sn.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1709 subnetVpnAssociation = true;
1711 if (subnetVpnAssociation == false) {
1712 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1713 vpnId, internetVpnId, sn.getVpnId(), sn.getInternetVpnId());
1716 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1717 List<Uuid> portList = sn.getPortList();
1718 final Uuid internetId = internetVpnId;
1719 if (portList != null) {
1720 for (final Uuid portId : portList) {
1721 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", sn.getSubnetIp(), portId.getValue());
1722 final Port port = neutronvpnUtils.getNeutronPort(portId);
1723 jobCoordinator.enqueueJob("PORT-" + portId.getValue(),
1724 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1725 CONFIGURATION, tx -> {
1727 withdrawPortIpFromVpnIface(vpnId, internetId, port, sn, tx);
1730 "Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since "
1731 + "port is absent in Neutron config DS", portId.getValue(),
1737 //update subnet-vpn association
1738 removeFromSubnetNode(subnet, null, null, vpnId, null);
1741 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1742 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1743 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1745 Uuid internalVpnId = sm.getVpnId();
1746 if (internalVpnId == null) {
1747 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1748 sm.getId().getValue());
1751 if (isBeingAssociated) {
1752 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1754 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1757 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1758 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1759 if (isBeingAssociated) {
1760 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1761 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1763 removeInternetVpnFromVpnInterface(vpn,
1764 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1769 // Check for ports on this subnet and update association of
1770 // corresponding vpn-interfaces to internet vpn
1771 List<Uuid> portList = sm.getPortList();
1772 if (portList != null) {
1773 for (Uuid port : portList) {
1774 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1775 port.getValue(), isBeingAssociated);
1776 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1777 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1779 if (isBeingAssociated) {
1780 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1781 true, false, tx, true);
1783 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1791 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1792 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1793 oldVpnId.getValue(), newVpnId.getValue());
1794 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1795 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1796 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1797 Uuid vpnExtUuid = netIsExternal ? null
1798 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1799 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1801 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1804 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1805 * associated with internet BGP-VPN.
1807 if (vpnExtUuid != null) {
1808 /* Update V6 Internet default route match with new VPN metadata.
1809 * isBeingAssociated = true means oldVpnId is same as routerId
1810 * isBeingAssociated = false means newVpnId is same as routerId
1812 if (isBeingAssociated) {
1813 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1815 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1818 //Update Router Interface first synchronously.
1819 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1820 ListenableFuture<Void> future =
1821 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1822 tx -> updateVpnInterface(newVpnId, oldVpnId,
1823 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1824 isBeingAssociated, true, tx, false));
1825 Futures.addCallback(future, new FutureCallback<Void>() {
1827 public void onSuccess(Void result) {
1828 // Check for ports on this subnet and update association of
1829 // corresponding vpn-interfaces to external vpn
1830 List<Uuid> portList = sn.getPortList();
1831 if (portList != null) {
1832 for (Uuid port : portList) {
1833 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1834 port.getValue(), isBeingAssociated);
1835 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1836 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1837 tx -> updateVpnInterface(newVpnId, oldVpnId,
1838 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1845 public void onFailure(Throwable throwable) {
1847 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1849 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1851 }, MoreExecutors.directExecutor());
1856 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1857 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1858 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1861 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1862 synchronized (routerId.getValue().intern()) {
1863 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1865 Optional<RouterInterfaces> optRouterInterfaces =
1866 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1867 routerInterfacesId);
1868 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1869 .setInterfaceId(interfaceName).build();
1870 if (optRouterInterfaces.isPresent()) {
1871 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1872 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1875 // TODO Shouldn't we be doing something with builder and interfaces?
1876 // RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1877 // List<Interfaces> interfaces = new ArrayList<>();
1878 // interfaces.add(routerInterface);
1880 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1881 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1884 } catch (ReadFailedException | TransactionCommitFailedException e) {
1885 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1890 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1891 synchronized (routerId.getValue().intern()) {
1892 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1894 Optional<RouterInterfaces> optRouterInterfaces =
1895 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1896 routerInterfacesId);
1897 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1898 .setInterfaceId(interfaceName).build();
1899 if (optRouterInterfaces.isPresent()) {
1900 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1901 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1902 if (interfaces != null && interfaces.remove(routerInterface)) {
1903 if (interfaces.isEmpty()) {
1904 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1905 routerInterfacesId);
1907 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1908 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1912 } catch (ReadFailedException | TransactionCommitFailedException e) {
1913 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1919 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1920 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1921 * route will be ignored.
1923 * @param vpnName the VPN identifier
1924 * @param interVpnLinkRoutes The list of static routes
1925 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1927 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1928 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1929 for (Routes route : interVpnLinkRoutes) {
1930 String nexthop = route.getNexthop().stringValue();
1931 String destination = route.getDestination().stringValue();
1932 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1933 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1934 AddStaticRouteInput rpcInput =
1935 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1936 .setVpnInstanceName(vpnName.getValue())
1938 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1939 RpcResult<AddStaticRouteOutput> rpcResult;
1941 rpcResult = labelOuputFtr.get();
1942 if (rpcResult.isSuccessful()) {
1943 LOG.debug("Label generated for destination {} is: {}",
1944 destination, rpcResult.getResult().getLabel());
1946 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1947 destination, nexthop, rpcResult.getErrors());
1949 } catch (InterruptedException | ExecutionException e) {
1950 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1951 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1954 // Any other case is a fault.
1955 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1956 route.getDestination().stringValue(), nexthop);
1963 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1964 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1966 * @param vpnName the VPN identifier
1967 * @param interVpnLinkRoutes The list of static routes
1968 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1970 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1971 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1972 for (Routes route : interVpnLinkRoutes) {
1973 String nexthop = route.getNexthop().stringValue();
1974 String destination = route.getDestination().stringValue();
1975 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1976 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1977 RemoveStaticRouteInput rpcInput =
1978 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1979 .setVpnInstanceName(vpnName.getValue())
1982 ListenableFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
1983 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
1985 // Any other case is a fault.
1986 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1987 route.getDestination().stringValue(), nexthop);
1994 * Returns true if the specified nexthop is the other endpoint in an
1995 * InterVpnLink, regarding one of the VPN's point of view.
1997 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1999 interVpnLink != null
2000 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2001 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2002 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2003 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2007 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2008 List<Adjacency> adjList = new ArrayList<>();
2009 Map<String, List<String>> adjMap = new HashMap<>();
2010 for (Routes route : routeList) {
2011 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2012 LOG.error("Incorrect input received for extra route. {}", route);
2014 String nextHop = route.getNexthop().stringValue();
2015 String destination = route.getDestination().stringValue();
2016 if (!nextHop.equals(fixedIp)) {
2017 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2020 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2022 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2023 if (!hops.contains(nextHop)) {
2029 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2030 final String destination = entry.getKey();
2031 final List<String> ipList = entry.getValue();
2032 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2033 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2034 .withKey(new AdjacencyKey(destination)).build();
2040 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2041 checkAlarmExtraRoutes(vpnId, routeList);
2043 for (Routes route : routeList) {
2044 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2045 LOG.error("Incorrect input received for extra route. {}", route);
2047 String nextHop = route.getNexthop().stringValue();
2048 String destination = route.getDestination().stringValue();
2049 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2051 if (infName != null) {
2052 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2053 destination, vpnId.getValue(), nextHop, infName);
2054 boolean isLockAcquired = false;
2056 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2057 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2058 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2059 .child(Adjacency.class, new AdjacencyKey(destination));
2060 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2061 LogicalDatastoreType.CONFIGURATION, path);
2062 if (existingAdjacency.isPresent()
2063 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2064 LOG.error("The route with destination {} nextHop {} is already present as"
2065 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2066 destination, nextHop, infName);
2069 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2070 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2071 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2072 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2073 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2075 } catch (TransactionCommitFailedException e) {
2076 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2077 destination, nextHop, e);
2078 } catch (ReadFailedException e) {
2079 LOG.error("Exception on reading data-store ", e);
2081 if (isLockAcquired) {
2082 interfaceLock.unlock(infName);
2086 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2087 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2094 * This method setup or down an alarm about extra route fault.
2095 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2096 * available RDs, then an alarm and an error is generated.<br>
2097 * <b>Be careful</b> the routeList could be changed.
2099 * @param vpnId the vpnId of vpn to control.
2100 * @param routeList the list of router to check, it could be modified.
2102 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2103 if (!neutronvpnAlarm.isAlarmEnabled()) {
2104 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2107 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2108 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2109 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2113 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2114 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2115 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2119 for (Routes route : routeList) {
2120 // count the number of nexthops for each same route.getDestingation().getValue()
2121 String destination = route.getDestination().stringValue();
2122 String nextHop = route.getNexthop().stringValue();
2123 List<String> nextHopList = new ArrayList<>();
2124 nextHopList.add(nextHop);
2126 for (Routes routeTmp : routeList) {
2127 String routeDest = routeTmp.getDestination().stringValue();
2128 if (!destination.equals(routeDest)) {
2131 String routeNextH = routeTmp.getNexthop().stringValue();
2132 if (nextHop.equals(routeNextH)) {
2136 nextHopList.add(routeTmp.getNexthop().stringValue());
2138 final List<String> rdList = new ArrayList<>();
2139 if (vpnInstance.getIpv4Family() != null
2140 && vpnInstance.getIpv4Family().getRouteDistinguisher() != null) {
2141 vpnInstance.getIpv4Family().getRouteDistinguisher().forEach(rd -> {
2147 if (vpnInstance.getIpv6Family() != null && vpnInstance.getIpv6Family().getRouteDistinguisher() != null) {
2148 vpnInstance.getIpv6Family().getRouteDistinguisher().forEach(rd -> {
2149 if (rd != null && !rdList.contains(rd)) {
2154 // 1. VPN Instance Name
2155 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2158 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2159 Uuid routerUuid = routerUuidList.get(0);
2160 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2161 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2163 // 3. List of RDs associated with the VPN
2164 detailsAlarm.append(" List of RDs associated with the VPN: ");
2165 for (String s : rdList) {
2166 detailsAlarm.append(s);
2167 detailsAlarm.append(", ");
2170 // 4. Prefix in question
2171 detailsAlarm.append(" for prefix: ");
2172 detailsAlarm.append(route.getDestination().stringValue());
2174 // 5. List of NHs for the prefix
2175 detailsAlarm.append(" for nextHops: ");
2176 for (String s : nextHopList) {
2177 detailsAlarm.append(s);
2178 detailsAlarm.append(", ");
2181 if (rdList.size() < nbNextHops) {
2182 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2184 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2189 // TODO Clean up the exception handling
2190 @SuppressWarnings("checkstyle:IllegalCatch")
2191 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2192 for (Routes route : routeList) {
2193 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2194 boolean isLockAcquired = false;
2195 String nextHop = route.getNexthop().stringValue();
2196 String destination = route.getDestination().stringValue();
2197 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2199 if (infName == null) {
2200 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2201 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2202 // Proceed to remove the next extra-route
2205 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2206 destination, vpnId.getValue(), nextHop, infName);
2208 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2209 InstanceIdentifier.builder(VpnInterfaces.class)
2210 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2211 .augmentation(Adjacencies.class)
2212 .child(Adjacency.class, new AdjacencyKey(destination))
2216 // Looking for existing prefix in MDSAL database
2217 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2218 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2219 boolean updateNextHops = false;
2220 List<String> nextHopList = new ArrayList<>();
2221 if (adjacency.isPresent()) {
2222 List<String> nhListRead = adjacency.get().getNextHopIpList();
2223 if (nhListRead.size() > 1) { // ECMP case
2224 for (String nextHopRead : nhListRead) {
2225 if (nextHopRead.equals(nextHop)) {
2226 updateNextHops = true;
2228 nextHopList.add(nextHopRead);
2234 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
2235 if (updateNextHops) {
2236 // An update must be done, not including the current next hop
2237 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2238 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2239 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2240 .setNextHopIpList(nextHopList)
2241 .withKey(new AdjacencyKey(destination))
2243 Adjacencies erAdjs =
2244 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
2245 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2246 .addAugmentation(Adjacencies.class, erAdjs).build();
2247 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2248 vpnIfIdentifier, vpnIf);
2250 // Remove the whole route
2251 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2252 adjacencyIdentifier);
2253 LOG.trace("extra route {} deleted successfully", route);
2255 } catch (TransactionCommitFailedException | ReadFailedException e) {
2256 LOG.error("exception in deleting extra route with destination {} for interface {}",
2257 destination, infName, e);
2259 if (isLockAcquired) {
2260 interfaceLock.unlock(infName);
2264 LOG.error("Incorrect input received for extra route: {}", route);
2269 public void removeVpn(Uuid vpnId) {
2271 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2272 List<RouterIds> routerIdsList = vpnMap != null ? vpnMap.getRouterIds() : null;
2273 List<Uuid> routerUuidList = new ArrayList<>();
2274 // dissociate router
2275 if (routerIdsList != null && !routerIdsList.isEmpty()) {
2276 for (RouterIds router : routerIdsList) {
2277 Uuid routerId = router.getRouterId();
2278 routerUuidList.add(routerId);
2279 dissociateRouterFromVpn(vpnId, routerId);
2282 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2283 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2285 // remove entire vpnMaps node
2286 deleteVpnMapsNode(vpnId);
2288 // remove vpn-instance
2289 deleteVpnInstance(vpnId);
2290 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2293 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2294 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
2297 // TODO Clean up the exception handling
2298 @SuppressWarnings("checkstyle:IllegalCatch")
2299 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2300 updateVpnMaps(vpnId, null, routerId, null, null);
2301 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
2302 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2303 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2304 for (Subnetmap sn : subMapList) {
2305 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2306 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2307 if (!ipVersion.isIpVersionChosen(ipVers)) {
2308 ipVersion = ipVersion.addVersion(ipVers);
2311 if (ipVersion != IpVersionChoice.UNDEFINED) {
2312 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ", ipVersion,
2314 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2318 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
2319 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
2321 } catch (Exception e) {
2322 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
2323 .getValue(), vpnId.getValue(), e);
2327 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2328 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2329 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2330 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2331 for (Uuid subnet : routerSubnets) {
2332 IpVersionChoice version = NeutronvpnUtils
2333 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2334 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2335 addSubnetToVpn(vpnId, subnet, null);
2337 addSubnetToVpn(vpnId, subnet, internetVpnId);
2342 // TODO Clean up the exception handling
2343 @SuppressWarnings("checkstyle:IllegalCatch")
2344 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2346 clearFromVpnMaps(vpnId, routerId, null);
2347 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2348 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2349 for (Subnetmap sn : subMapList) {
2350 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2351 if (ipVersion.isIpVersionChosen(ipVers)) {
2352 ipVersion = ipVersion.addVersion(ipVers);
2354 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
2355 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2357 if (ipVersion != IpVersionChoice.UNDEFINED) {
2358 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2360 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2364 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
2365 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
2367 } catch (Exception e) {
2368 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
2369 .getValue(), vpnId.getValue(), e);
2374 * Parses and associates networks list with given VPN.
2376 * @param vpnId Uuid of given VPN.
2377 * @param networkList List list of network Ids (Uuid), which will be associated.
2378 * @return list of formatted strings with detailed error messages.
2381 protected List<String> associateNetworksToVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2382 List<String> failedNwList = new ArrayList<>();
2383 HashSet<Uuid> passedNwList = new HashSet<>();
2384 boolean isExternalNetwork = false;
2385 if (networkList.isEmpty()) {
2386 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2387 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2389 return failedNwList;
2391 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2392 if (vpnInstance == null) {
2393 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2394 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2395 + "in ConfigDS", vpnId.getValue()));
2396 return failedNwList;
2399 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2400 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2402 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2403 + "associated with", vpnId.getValue()));
2404 return failedNwList;
2406 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2407 for (Uuid nw : networkList) {
2408 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2409 if (network == null) {
2410 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2411 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2415 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2416 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2417 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2418 nw.getValue(), vpnId.getValue());
2419 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2420 nw.getValue(), vpnId.getValue()));
2423 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2424 if (networkVpnId != null) {
2425 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2426 nw.getValue(), networkVpnId.getValue());
2427 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2428 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2431 if (NeutronvpnUtils.getIsExternal(network) && !associateExtNetworkToVpn(vpnId, network)) {
2432 LOG.error("associateNetworksToVpn: Failed to associate Provider Network {} with VPN {}",
2433 nw.getValue(), vpnId.getValue());
2434 failedNwList.add(String.format("Failed to associate Provider Network %s with VPN %s",
2435 nw.getValue(), vpnId.getValue()));
2438 if (NeutronvpnUtils.getIsExternal(network)) {
2439 isExternalNetwork = true;
2441 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2442 if (subnetmapList == null || subnetmapList.isEmpty()) {
2443 passedNwList.add(nw);
2446 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2449 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2450 for (Subnetmap subnetmap : subnetmapList) {
2451 Uuid subnetId = subnetmap.getId();
2452 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2453 if (subnetVpnId != null) {
2454 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2455 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2456 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2457 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2460 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2461 if (!ipVersion.isIpVersionChosen(ipVers)) {
2462 ipVersion = ipVersion.addVersion(ipVers);
2464 if (!NeutronvpnUtils.getIsExternal(network)) {
2465 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2467 addSubnetToVpn(vpnId, subnetId, null);
2468 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2470 passedNwList.add(nw);
2473 if (ipVersion != IpVersionChoice.UNDEFINED) {
2474 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {} ",
2476 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2478 passedNwList.add(nw);
2480 } catch (ReadFailedException e) {
2481 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2483 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2486 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2487 if (!isExternalNetwork) {
2488 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2490 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList.toString(), vpnId.getValue());
2491 return failedNwList;
2494 private boolean associateExtNetworkToVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2495 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2498 VpnInstanceOpDataEntry vpnOpDataEntry = neutronvpnUtils.getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
2499 if (vpnOpDataEntry == null) {
2500 LOG.error("associateExtNetworkToVpn: can not find VpnOpDataEntry for VPN {}", vpnId.getValue());
2503 if (!vpnOpDataEntry.getBgpvpnType().equals(BgpvpnType.BGPVPNInternet)) {
2504 LOG.info("associateExtNetworkToVpn: set type {} for VPN {}", BgpvpnType.BGPVPNInternet, vpnId.getValue());
2505 neutronvpnUtils.updateVpnInstanceOpWithType(BgpvpnType.BGPVPNInternet, vpnId);
2507 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2508 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2509 updateVpnMaps(vpnId, null, null, null, extNwList);
2510 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2511 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2512 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2514 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2517 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2518 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2521 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2522 updateVpnInternetForSubnet(sm, vpnId, true);
2524 if (!ipVersion.isIpVersionChosen(ipVers)) {
2525 ipVersion = ipVersion.addVersion(ipVers);
2528 if (ipVersion != IpVersionChoice.UNDEFINED) {
2529 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2530 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2531 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2537 * Parses and disassociates networks list from given VPN.
2539 * @param vpnId Uuid of given VPN.
2540 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2541 * @return list of formatted strings with detailed error messages.
2544 protected List<String> dissociateNetworksFromVpn(@Nonnull Uuid vpnId, @Nonnull List<Uuid> networkList) {
2545 List<String> failedNwList = new ArrayList<>();
2546 HashSet<Uuid> passedNwList = new HashSet<>();
2547 if (networkList.isEmpty()) {
2548 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2549 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2551 return failedNwList;
2553 for (Uuid nw : networkList) {
2554 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2555 if (networkSubnets == null) {
2556 passedNwList.add(nw);
2559 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2560 if (network == null) {
2561 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS");
2562 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2566 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2567 if (networkVpnId == null) {
2568 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2569 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2573 if (!vpnId.equals(networkVpnId)) {
2574 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2575 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2576 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2577 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2581 if (NeutronvpnUtils.getIsExternal(network)) {
2582 if (disassociateExtNetworkFromVpn(vpnId, network)) {
2583 passedNwList.add(nw);
2585 LOG.error("dissociateNetworksFromVpn: Failed to withdraw Provider Network {} from VPN {}",
2586 nw.getValue(), vpnId.getValue());
2587 failedNwList.add(String.format("Failed to withdraw Provider Network %s from VPN %s", nw.getValue(),
2592 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2593 for (Uuid subnet : networkSubnets) {
2594 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2595 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2596 if (!ipVersion.isIpVersionChosen(ipVers)) {
2597 ipVersion = ipVersion.addVersion(ipVers);
2599 if (!NeutronvpnUtils.getIsExternal(network)) {
2600 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2602 removeSubnetFromVpn(vpnId, subnet, null);
2603 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2604 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2606 passedNwList.add(nw);
2609 if (ipVersion != IpVersionChoice.UNDEFINED) {
2610 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
2612 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2615 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2616 LOG.info("Network(s) {} disassociated from L3VPN {} successfully", passedNwList.toString(),
2618 return failedNwList;
2621 private boolean disassociateExtNetworkFromVpn(@Nonnull Uuid vpnId, @Nonnull Network extNet) {
2622 if (!removeExternalNetworkFromVpn(extNet)) {
2625 // check, if there is another Provider Networks associated with given VPN
2626 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2627 if (vpnNets != null) {
2628 //Remove currently disassociated network from the list
2629 vpnNets.remove(extNet.getUuid());
2630 for (Uuid netId : vpnNets) {
2631 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2632 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2633 + "{}", vpnId.getValue(), netId.getValue());
2638 //Set VPN Type is BGPVPNExternal from BGPVPNInternet
2639 LOG.info("disassociateExtNetworkFromVpn: set type {} for VPN {}",
2640 VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId.getValue());
2641 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal, vpnId);
2642 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2643 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2644 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2646 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2649 IpVersionChoice ipVers = neutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2650 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2653 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2654 updateVpnInternetForSubnet(sm, vpnId, false);
2656 if (!ipVersion.isIpVersionChosen(ipVers)) {
2657 ipVersion = ipVersion.addVersion(ipVers);
2660 if (ipVersion != IpVersionChoice.UNDEFINED) {
2661 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2662 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2664 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2670 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2673 // TODO Clean up the exception handling
2674 @SuppressWarnings("checkstyle:IllegalCatch")
2675 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2677 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2678 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2679 StringBuilder returnMsg = new StringBuilder();
2680 Uuid vpnId = input.getVpnId();
2683 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2684 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2685 input.getNetworkId().toString());
2686 List<Uuid> netIds = input.getNetworkId();
2687 if (netIds != null && !netIds.isEmpty()) {
2688 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2689 if (!failed.isEmpty()) {
2690 returnMsg.append(failed);
2694 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2696 if (returnMsg.length() != 0) {
2697 opBuilder.setResponse(
2698 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2699 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2700 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2702 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2704 } catch (Exception ex) {
2705 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2706 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2707 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2709 LOG.debug("associateNetworks returns..");
2714 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2717 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2719 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2720 LOG.debug("associateRouter {}", input);
2721 StringBuilder returnMsg = new StringBuilder();
2722 Uuid vpnId = input.getVpnId();
2723 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input.RouterIds>
2724 routerIds = input.getRouterIds();
2725 Preconditions.checkArgument(!routerIds.isEmpty(), "associateRouter: RouterIds list is empty!");
2726 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2727 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2728 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2729 .RouterIds routerId : routerIds) {
2730 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2731 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2732 if (vpnMap != null) {
2734 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2735 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2736 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2737 .append(routerId.getRouterId());
2738 } else if (extVpnId != null) {
2739 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2740 + "another VPN ").append(extVpnId.getValue());
2742 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2743 routerId.getRouterId());
2744 associateRouterToVpn(vpnId, routerId.getRouterId());
2747 returnMsg.append("router not found : ").append(routerId.getRouterId());
2750 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2752 if (returnMsg.length() != 0) {
2753 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2754 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2755 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2757 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2760 LOG.debug("associateRouter returns..");
2765 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2768 // TODO Clean up the exception handling
2769 @SuppressWarnings("checkstyle:IllegalCatch")
2770 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2771 GetFixedIPsForNeutronPortInput input) {
2772 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2773 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2774 Uuid portId = input.getPortId();
2775 StringBuilder returnMsg = new StringBuilder();
2777 List<String> fixedIPList = new ArrayList<>();
2778 Port port = neutronvpnUtils.getNeutronPort(portId);
2780 for (FixedIps ip : requireNonNullElse(port.getFixedIps(), Collections.<FixedIps>emptyList())) {
2781 fixedIPList.add(ip.getIpAddress().stringValue());
2784 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2786 if (returnMsg.length() != 0) {
2787 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2789 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2790 returnMsg)).build());
2792 opBuilder.setFixedIPs(fixedIPList);
2793 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2795 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2797 } catch (Exception ex) {
2798 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2799 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2800 portId.getValue(), ex.getMessage(), ex)).build());
2806 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2809 // TODO Clean up the exception handling
2810 @SuppressWarnings("checkstyle:IllegalCatch")
2811 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2813 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2814 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2816 LOG.debug("dissociateNetworks {}", input);
2817 StringBuilder returnMsg = new StringBuilder();
2818 Uuid vpnId = input.getVpnId();
2821 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2822 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2823 input.getNetworkId().toString());
2824 List<Uuid> netIds = input.getNetworkId();
2825 if (netIds != null && !netIds.isEmpty()) {
2826 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2827 if (!failed.isEmpty()) {
2828 returnMsg.append(failed);
2832 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2834 if (returnMsg.length() != 0) {
2835 opBuilder.setResponse(
2836 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2837 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2839 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2841 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2843 } catch (Exception ex) {
2844 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2845 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2846 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2848 LOG.debug("dissociateNetworks returns..");
2853 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2856 // TODO Clean up the exception handling
2857 @SuppressWarnings("checkstyle:IllegalCatch")
2858 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2860 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2862 LOG.debug("dissociateRouter {}", input);
2863 StringBuilder returnMsg = new StringBuilder();
2864 Uuid vpnId = input.getVpnId();
2865 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2866 .RouterIds> routerIdList = input.getRouterIds();
2867 String routerIdsString = "";
2868 Preconditions.checkArgument(!routerIdList.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2869 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2870 Preconditions.checkNotNull(routerIdList, "dissociateRouter: routerIdList not found!");
2871 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2872 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2873 .RouterIds routerId : routerIdList) {
2875 if (routerId != null) {
2876 routerIdsString += routerId.getRouterId() + ", ";
2877 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2879 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2880 if (routerVpnId == null) {
2881 returnMsg.append("input router ").append(routerId.getRouterId())
2882 .append(" not associated to any vpn yet");
2883 } else if (vpnId.equals(routerVpnId)) {
2884 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2886 returnMsg.append("input router ").append(routerId.getRouterId())
2887 .append(" associated to vpn ")
2888 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2891 returnMsg.append("router not found : ").append(routerId.getRouterId());
2894 if (returnMsg.length() != 0) {
2895 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2896 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
2897 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
2898 returnMsg)).build());
2900 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
2902 } catch (Exception ex) {
2903 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
2904 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
2905 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
2909 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2912 LOG.debug("dissociateRouter returns..");
2916 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2917 // check if the router is associated to some VPN
2918 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
2919 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2920 if (vpnId != null) {
2921 // remove existing external vpn interfaces
2922 for (Uuid subnetId : routerSubnetIds) {
2923 removeSubnetFromVpn(vpnId, subnetId, internetVpnId);
2925 clearFromVpnMaps(vpnId, routerId, null);
2927 // remove existing internal vpn interfaces
2928 for (Uuid subnetId : routerSubnetIds) {
2929 removeSubnetFromVpn(routerId, subnetId, internetVpnId);
2932 // delete entire vpnMaps node for internal VPN
2933 deleteVpnMapsNode(routerId);
2935 // delete vpn-instance for internal VPN
2936 deleteVpnInstance(routerId);
2939 protected Subnet getNeutronSubnet(Uuid subnetId) {
2940 return neutronvpnUtils.getNeutronSubnet(subnetId);
2944 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2945 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
2947 return sn.getGatewayIp();
2953 protected Network getNeutronNetwork(Uuid networkId) {
2954 return neutronvpnUtils.getNeutronNetwork(networkId);
2957 protected Port getNeutronPort(String name) {
2958 return neutronvpnUtils.getNeutronPort(new Uuid(name));
2961 protected Port getNeutronPort(Uuid portId) {
2962 return neutronvpnUtils.getNeutronPort(portId);
2965 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2966 return neutronvpnUtils.getNetworkForSubnet(subnetId);
2969 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2970 return neutronvpnUtils.getNetworksForVpn(vpnId);
2974 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2976 * @return a List of String to be printed on screen
2977 * @throws ReadFailedException if there was a problem reading from the data store
2979 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2980 List<String> result = new ArrayList<>();
2981 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2983 result.add("-------------------------------------------------------------------------------------------");
2984 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2986 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2987 if (ports.isPresent() && ports.get().getPort() != null) {
2988 for (Port port : requireNonNullElse(ports.get().getPort(), Collections.<Port>emptyList())) {
2989 List<FixedIps> fixedIPs = port.getFixedIps();
2990 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2991 List<String> ipList = new ArrayList<>();
2992 for (FixedIps fixedIp : fixedIPs) {
2993 IpAddress ipAddress = fixedIp.getIpAddress();
2994 if (ipAddress.getIpv4Address() != null) {
2995 ipList.add(ipAddress.getIpv4Address().getValue());
2997 ipList.add(ipAddress.getIpv6Address().getValue());
3000 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3001 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3002 ipList.toString()));
3004 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3005 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3014 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3016 * @param vpnuuid Uuid of the VPN whose config must be shown
3017 * @return formatted output list
3018 * @throws InterruptedException if there was a thread related problem getting the data to display
3019 * @throws ExecutionException if there was any other problem getting the data to display
3021 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3022 List<String> result = new ArrayList<>();
3023 if (vpnuuid == null) {
3025 result.add("Displaying VPN config for all VPNs");
3026 result.add("To display VPN config for a particular VPN, use the following syntax");
3027 result.add(getshowVpnConfigCLIHelp());
3029 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3030 if (rpcResult.isSuccessful()) {
3032 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3034 result.add(String.format(" %-80s ", "Import-RTs"));
3036 result.add(String.format(" %-80s ", "Export-RTs"));
3038 result.add(String.format(" %-76s ", "Subnet IDs"));
3040 result.add("------------------------------------------------------------------------------------");
3042 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3043 requireNonNullElse(rpcResult.getResult().getL3vpnInstances(),
3044 Collections.<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
3045 .VpnInstance>emptyList())) {
3046 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3048 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3049 vpn.getRouteDistinguisher()));
3051 result.add(String.format(" %-80s ", vpn.getImportRT()));
3053 result.add(String.format(" %-80s ", vpn.getExportRT()));
3056 Uuid vpnid = vpn.getId();
3057 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3058 if (!subnetList.isEmpty()) {
3059 for (Uuid subnetuuid : subnetList) {
3060 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3063 result.add(String.format(" %-76s ", "\" \""));
3066 result.add("----------------------------------------");
3070 String errortag = rpcResult.getErrors().iterator().next().getTag();
3071 if (Objects.equals(errortag, "")) {
3073 result.add("No VPN has been configured yet");
3074 } else if (Objects.equals(errortag, "invalid-value")) {
3076 result.add("VPN " + vpnuuid.getValue() + " is not present");
3078 result.add("error getting VPN info : " + rpcResult.getErrors());
3079 result.add(getshowVpnConfigCLIHelp());
3085 protected void createExternalVpnInterfaces(Uuid extNetId) {
3086 if (extNetId == null) {
3087 LOG.error("createExternalVpnInterfaces: external network is null");
3091 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3092 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3093 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3097 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3098 for (String elanInterface : extElanInterfaces) {
3099 createExternalVpnInterface(extNetId, elanInterface, tx);
3101 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3104 // TODO Clean up the exception handling
3105 @SuppressWarnings("checkstyle:IllegalCatch")
3106 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3107 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3108 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3109 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3112 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3113 for (String elanInterface : extElanInterfaces) {
3114 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3115 .buildVpnInterfaceIdentifier(elanInterface);
3116 LOG.info("Removing vpn interface {}", elanInterface);
3117 tx.delete(vpnIfIdentifier);
3119 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3122 private void createExternalVpnInterface(Uuid vpnId, String infName,
3123 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3124 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3125 false /* not a router iface */, wrtConfigTxn);
3128 // TODO Clean up the exception handling
3129 @SuppressWarnings("checkstyle:IllegalCatch")
3130 private void writeVpnInterfaceToDs(@Nonnull Collection<Uuid> vpnIdList, String infName,
3131 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3132 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3133 if (vpnIdList.isEmpty() || infName == null) {
3134 LOG.error("vpnid is empty or interface({}) is null", infName);
3137 if (wrtConfigTxn == null) {
3138 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3139 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3140 "Error writing VPN interface");
3143 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3144 for (Uuid vpnId: vpnIdList) {
3145 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3146 AssociatedSubnetType.V4AndV6Subnets);
3147 vpnIdListStruct.add(vpnInstance);
3150 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3151 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3153 .setVpnInstanceNames(vpnIdListStruct)
3154 .setRouterInterface(isRouterInterface);
3155 LOG.info("Network Id is {}", networkUuid);
3156 if (networkUuid != null) {
3157 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3158 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3159 NetworkAttributes.NetworkType networkType = (providerType != null)
3160 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3161 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3162 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3163 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3166 if (adjacencies != null) {
3167 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3169 VpnInterface vpnIf = vpnb.build();
3171 LOG.info("Creating vpn interface {}", vpnIf);
3172 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3173 } catch (Exception ex) {
3174 LOG.error("Creation of vpninterface {} failed", infName, ex);
3178 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3179 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3180 if (vpnId == null || infName == null) {
3181 LOG.error("vpn id or interface is null");
3184 if (wrtConfigTxn == null) {
3185 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3186 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3187 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3188 }), LOG, "Error updating VPN interface with adjacencies");
3192 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3193 boolean isLockAcquired = false;
3195 isLockAcquired = interfaceLock.tryLock(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3196 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3197 .syncReadOptional(dataBroker, LogicalDatastoreType
3198 .CONFIGURATION, vpnIfIdentifier);
3199 if (optionalVpnInterface.isPresent()) {
3200 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3201 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3203 if (adjacencies == null) {
3204 if (isLockAcquired) {
3205 interfaceLock.unlock(infName);
3209 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3210 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3211 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3212 optionalVpnInterface.get().getVpnInstanceNames());
3213 if (listVpnInstances.isEmpty() || !VpnHelper
3214 .doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3215 VpnInstanceNames vpnInstance = VpnHelper
3216 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3217 listVpnInstances.add(vpnInstance);
3218 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3221 VpnInstanceNames vpnInstance = VpnHelper
3222 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3223 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3224 listVpnInstances.add(vpnInstance);
3225 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3227 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3228 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3230 } catch (IllegalStateException | ReadFailedException ex) {
3231 LOG.error("Update of vpninterface {} failed", infName, ex);
3233 if (isLockAcquired) {
3234 interfaceLock.unlock(infName);
3239 private String getshowVpnConfigCLIHelp() {
3240 StringBuilder help = new StringBuilder("Usage:");
3241 help.append("display vpn-config [-vid/--vpnid <id>]");
3242 return help.toString();
3245 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
3246 InterruptedException {
3247 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
3248 .setVpnId(vpnId).build();
3249 LOG.info("publishing notification upon association of router to VPN");
3250 notificationPublishService.putNotification(routerAssociatedToVpn);
3253 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
3254 InterruptedException {
3255 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
3256 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
3257 LOG.info("publishing notification upon disassociation of router from VPN");
3258 notificationPublishService.putNotification(routerDisassociatedFromVpn);
3261 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3262 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3266 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3267 return neutronEvpnManager.createEVPN(input);
3271 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3272 return neutronEvpnManager.getEVPN(input);
3276 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3277 return neutronEvpnManager.deleteEVPN(input);
3280 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3281 Uuid extNetId = extNet.getUuid();
3282 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3283 .child(Networks.class, new NetworksKey(extNetId)).build();
3286 Optional<Networks> optionalExtNets =
3287 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3289 if (!optionalExtNets.isPresent()) {
3290 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3291 extNetId.getValue());
3294 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3295 builder.setVpnid(vpnId);
3296 Networks networks = builder.build();
3297 // Add Networks object to the ExternalNetworks list
3298 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3299 extNetId.getValue());
3300 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3303 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3304 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3305 extNetId.getValue(), ex);
3310 private boolean removeExternalNetworkFromVpn(Network extNet) {
3311 Uuid extNetId = extNet.getUuid();
3312 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3313 .child(Networks.class, new NetworksKey(extNetId)).build();
3315 Optional<Networks> optionalNets =
3316 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3318 NetworksBuilder builder = null;
3319 if (optionalNets.isPresent()) {
3320 builder = new NetworksBuilder(optionalNets.get());
3322 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3323 extNetId.getValue());
3326 builder.setVpnid(null);
3327 Networks networks = builder.build();
3328 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3329 extNetId.getValue());
3330 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3332 } catch (TransactionCommitFailedException | ReadFailedException ex) {
3333 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3334 extNetId.getValue(), ex);
3339 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3340 Optional<String> existingVpnName = Optional.of(primaryRd);
3341 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3343 vpnInstanceOpDataOptional = SingleTransactionDataBroker
3344 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3345 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3346 } catch (ReadFailedException e) {
3347 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3349 /*Read failed. We don't know if a VPN exists or not.
3350 * Return primaryRd to halt caller execution, to be safe.*/
3351 return existingVpnName;
3353 if (vpnInstanceOpDataOptional.isPresent()) {
3354 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3356 existingVpnName = Optional.absent();
3358 return existingVpnName;
3361 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
3362 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3365 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3366 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3369 private String formatAndLog(Consumer<String> logger, String template, Object... args) {
3370 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3373 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3374 String message = tuple.getMessage();
3375 logger.accept(message);
3379 protected void addV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3380 @Nonnull Subnetmap subnetMap) {
3381 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3382 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3383 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3384 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3385 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3386 subnetMap.getId().getValue(), internetVpnId.getValue());
3390 protected void removeV6PrivateSubnetToExtNetwork(@Nonnull Uuid routerId, @Nonnull Uuid internetVpnId,
3391 @Nonnull Subnetmap subnetMap) {
3392 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3393 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3396 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3397 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3398 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3399 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3400 internetVpnId.getValue(), routerId.getValue());
3401 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW