2 * Copyright © 2015, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
13 import com.google.common.base.Optional;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.SettableFuture;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.EventListener;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
24 import java.util.Objects;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ExecutionException;
27 import java.util.concurrent.Future;
28 import javax.annotation.PreDestroy;
29 import javax.inject.Inject;
30 import javax.inject.Singleton;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
33 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
36 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
37 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
40 import org.opendaylight.netvirt.elanmanager.api.IElanService;
41 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
42 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
43 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
44 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
45 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
46 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
47 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
48 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
49 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
50 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
51 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
53 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
54 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
55 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
56 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
57 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
58 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
59 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv6FamilyBuilder;
60 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
145 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
146 import org.opendaylight.yangtools.yang.common.RpcError;
147 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
148 import org.opendaylight.yangtools.yang.common.RpcResult;
149 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
150 import org.slf4j.Logger;
151 import org.slf4j.LoggerFactory;
154 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
156 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
158 private final DataBroker dataBroker;
159 private final NeutronvpnNatManager nvpnNatManager;
160 private final NotificationPublishService notificationPublishService;
161 private final VpnRpcService vpnRpcService;
162 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
163 private final IElanService elanService;
164 private final NeutronvpnConfig neutronvpnConfig;
165 private final IVpnManager vpnManager;
166 private final NeutronEvpnManager neutronEvpnManager;
167 private final NeutronEvpnUtils neutronEvpnUtils;
168 private final JobCoordinator jobCoordinator;
169 private static ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
172 public NeutronvpnManager(
173 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
174 final NeutronvpnNatManager vpnNatMgr, final VpnRpcService vpnRpcSrv, final IElanService elanService,
175 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
176 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
177 final JobCoordinator jobCoordinator) {
178 this.dataBroker = dataBroker;
179 nvpnNatManager = vpnNatMgr;
180 notificationPublishService = notiPublishService;
181 vpnRpcService = vpnRpcSrv;
182 this.elanService = elanService;
183 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
184 this.neutronvpnConfig = neutronvpnConfig;
185 this.vpnManager = vpnManager;
186 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this);
187 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
188 this.jobCoordinator = jobCoordinator;
195 public void close() throws Exception {
196 LOG.info("{} close", getClass().getSimpleName());
199 private void configureFeatures() {
200 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
201 Neutron.class).child(Features.class).child(
202 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
203 Feature feature = new FeatureBuilder().setKey(new FeatureKey(OperationalPortStatus.class)).build();
205 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
206 } catch (TransactionCommitFailedException e) {
207 LOG.warn("Error configuring feature {}", feature, e);
211 public String getOpenDaylightVniRangesConfig() {
212 return neutronvpnConfig.getOpendaylightVniRanges();
215 // TODO Clean up the exception handling
216 @SuppressWarnings("checkstyle:IllegalCatch")
217 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
218 NetworkAttributes.NetworkType networkType, long segmentationId) {
220 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
221 synchronized (subnetId.getValue().intern()) {
222 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.toString());
223 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
224 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
225 if (sn.isPresent()) {
226 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
227 subnetId.getValue());
230 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId))
231 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
232 .setNetworkType(networkType).setSegmentationId(segmentationId);
233 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
234 subnetId.getValue());
235 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
236 subnetMapIdentifier, subnetmapBuilder.build());
238 } catch (Exception e) {
239 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
241 // check if there are ports to update for already created Subnetmap node
242 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
243 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
244 if (entry.getValue().getValue().equals(subnetId.getValue())) {
245 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
246 unprocessedPortsMap.remove(entry.getKey());
251 protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId) {
252 Subnetmap subnetmap = null;
253 SubnetmapBuilder builder = null;
254 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
255 .child(Subnetmap.class, new SubnetmapKey(subnetId))
258 synchronized (subnetId.getValue().intern()) {
259 Optional<Subnetmap> sn =
260 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
262 if (sn.isPresent()) {
263 builder = new SubnetmapBuilder(sn.get());
264 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
266 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
269 if (routerId != null) {
270 builder.setRouterId(routerId);
273 builder.setVpnId(vpnId);
275 subnetmap = builder.build();
276 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
277 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
279 } catch (ReadFailedException | TransactionCommitFailedException e) {
280 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
285 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
286 Uuid routerInterfacePortId, String fixedIp,
287 String routerIntfMacAddress) {
288 Subnetmap subnetmap = null;
289 SubnetmapBuilder builder = null;
290 InstanceIdentifier<Subnetmap> id =
291 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
293 synchronized (subnetId.getValue().intern()) {
294 Optional<Subnetmap> sn =
295 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
297 if (sn.isPresent()) {
298 builder = new SubnetmapBuilder(sn.get());
299 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
300 subnetId.getValue());
302 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
303 subnetId.getValue());
306 builder.setRouterId(routerId);
307 builder.setRouterInterfacePortId(routerInterfacePortId);
308 builder.setRouterIntfMacAddress(routerIntfMacAddress);
309 builder.setRouterInterfaceFixedIp(fixedIp);
310 subnetmap = builder.build();
311 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
312 subnetId.getValue());
313 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
315 } catch (ReadFailedException | TransactionCommitFailedException e) {
316 LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
317 subnetId.getValue(), e);
321 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
322 Subnetmap subnetmap = null;
323 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
324 new SubnetmapKey(subnetId)).build();
325 LOG.info("updateSubnetmapNodeWithPorts : subnetId {}, subnetMapId {}", subnetId.toString(), id.toString());
327 synchronized (subnetId.getValue().intern()) {
328 Optional<Subnetmap> sn =
329 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
331 if (sn.isPresent()) {
332 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
333 if (null != portId) {
334 List<Uuid> portList = builder.getPortList();
335 if (null == portList) {
336 portList = new ArrayList<>();
338 portList.add(portId);
339 builder.setPortList(portList);
340 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
341 subnetId.getValue(), portId.getValue());
343 if (null != directPortId) {
344 List<Uuid> directPortList = builder.getDirectPortList();
345 if (null == directPortList) {
346 directPortList = new ArrayList<>();
348 directPortList.add(directPortId);
349 builder.setDirectPortList(directPortList);
350 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
351 directPortId.getValue());
353 subnetmap = builder.build();
354 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
357 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
358 + "cache ", subnetId.getValue(), portId.getValue());
359 unprocessedPortsMap.put(portId, subnetId);
362 } catch (ReadFailedException | TransactionCommitFailedException e) {
363 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
368 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
369 Subnetmap subnetmap = null;
370 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
371 .child(Subnetmap.class, new SubnetmapKey(subnetId))
374 synchronized (subnetId.getValue().intern()) {
375 Optional<Subnetmap> sn =
376 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
378 if (sn.isPresent()) {
379 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
380 if (routerId != null) {
381 builder.setRouterId(null);
383 if (networkId != null) {
384 builder.setNetworkId(null);
387 builder.setVpnId(null);
389 if (portId != null && builder.getPortList() != null) {
390 List<Uuid> portList = builder.getPortList();
391 portList.remove(portId);
392 builder.setPortList(portList);
395 subnetmap = builder.build();
396 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
397 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
400 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
403 } catch (ReadFailedException | TransactionCommitFailedException e) {
404 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
409 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
410 Subnetmap subnetmap = null;
411 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
412 new SubnetmapKey(subnetId)).build();
414 synchronized (subnetId.getValue().intern()) {
415 Optional<Subnetmap> sn =
416 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
418 if (sn.isPresent()) {
419 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
420 if (null != portId && null != builder.getPortList()) {
421 List<Uuid> portList = builder.getPortList();
422 portList.remove(portId);
423 builder.setPortList(portList);
424 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
425 subnetId.getValue());
427 if (null != directPortId && null != builder.getDirectPortList()) {
428 List<Uuid> directPortList = builder.getDirectPortList();
429 directPortList.remove(directPortId);
430 builder.setDirectPortList(directPortList);
431 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
432 .getValue(), subnetId.getValue());
434 subnetmap = builder.build();
435 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
438 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
441 } catch (ReadFailedException | TransactionCommitFailedException e) {
442 LOG.error("Removing a port from port list of a subnetmap failed for node: {} with expection {}",
443 subnetId.getValue(), e);
448 // TODO Clean up the exception handling
449 @SuppressWarnings("checkstyle:IllegalCatch")
450 protected void deleteSubnetMapNode(Uuid subnetId) {
451 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
452 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
453 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
455 synchronized (subnetId.getValue().intern()) {
456 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
457 subnetMapIdentifier);
459 } catch (Exception e) {
460 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
464 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
465 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
466 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
468 Optional<VpnInstance> vpnInstanceConfig =
469 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
471 if (!vpnInstanceConfig.isPresent()) {
472 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
475 VpnInstance vpnInstance = vpnInstanceConfig.get();
476 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
477 if (vpnInstance.getIpv4Family() != null) {
478 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder(vpnInstance.getIpv4Family());
479 updateVpnInstanceBuilder.setIpv4Family(ipv4FamilyBuilder.setRouteDistinguisher(rds).build());
481 if (vpnInstance.getIpv6Family() != null) {
482 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
483 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
485 LOG.debug("Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
486 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
487 updateVpnInstanceBuilder.build());
488 } catch (ReadFailedException | TransactionCommitFailedException ex) {
489 LOG.warn("Error configuring feature ", ex);
493 // TODO Clean up the exception handling
494 @SuppressWarnings("checkstyle:IllegalCatch")
495 private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert,
496 VpnInstance.Type type, long l3vni, IpVersionChoice ipVersion) {
497 VpnInstanceBuilder builder = null;
498 List<VpnTarget> vpnTargetList = new ArrayList<>();
499 boolean isLockAcquired = false;
500 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
501 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
503 Optional<VpnInstance> optionalVpn =
504 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
506 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
507 if (optionalVpn.isPresent()) {
508 builder = new VpnInstanceBuilder(optionalVpn.get());
509 LOG.debug("updating existing vpninstance node");
511 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
512 .setType(type).setL3vni(l3vni);
514 if (irt != null && !irt.isEmpty()) {
515 if (ert != null && !ert.isEmpty()) {
516 List<String> commonRT = new ArrayList<>(irt);
517 commonRT.retainAll(ert);
519 for (String common : commonRT) {
522 VpnTarget vpnTarget =
523 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
524 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
525 vpnTargetList.add(vpnTarget);
528 for (String importRT : irt) {
529 VpnTarget vpnTarget =
530 new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
531 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
532 vpnTargetList.add(vpnTarget);
536 if (ert != null && !ert.isEmpty()) {
537 for (String exportRT : ert) {
538 VpnTarget vpnTarget =
539 new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
540 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
541 vpnTargetList.add(vpnTarget);
545 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
547 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
548 Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
550 if (rd != null && !rd.isEmpty()) {
551 ipv4vpnBuilder.setRouteDistinguisher(rd);
552 ipv6vpnBuilder.setRouteDistinguisher(rd);
555 VpnInstance newVpn = null;
556 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
557 newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
559 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
560 newVpn = builder.setIpv6Family(ipv6vpnBuilder.build()).build();
562 if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.UNDEFINED)) {
563 // no subnets presented in router set by default support of IPv4 family
564 newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
566 isLockAcquired = NeutronUtils.lock(vpnName);
567 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
568 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
569 } catch (Exception e) {
570 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
572 if (isLockAcquired) {
573 NeutronUtils.unlock(vpnName);
578 // TODO Clean up the exception handling
579 @SuppressWarnings("checkstyle:IllegalCatch")
580 private void deleteVpnMapsNode(Uuid vpnid) {
581 boolean isLockAcquired = false;
582 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
583 .child(VpnMap.class, new VpnMapKey(vpnid))
585 LOG.debug("removing vpnMaps node: {} ", vpnid.getValue());
587 isLockAcquired = NeutronUtils.lock(vpnid.getValue());
588 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
589 } catch (Exception e) {
590 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnid.getValue());
592 if (isLockAcquired) {
593 NeutronUtils.unlock(vpnid.getValue());
598 // TODO Clean up the exception handling
599 @SuppressWarnings("checkstyle:IllegalCatch")
600 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
601 VpnMapBuilder builder;
602 boolean isLockAcquired = false;
603 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
604 .child(VpnMap.class, new VpnMapKey(vpnId))
607 Optional<VpnMap> optionalVpnMap =
608 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
610 if (optionalVpnMap.isPresent()) {
611 builder = new VpnMapBuilder(optionalVpnMap.get());
613 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
617 builder.setName(name);
619 if (tenantId != null) {
620 builder.setTenantId(tenantId);
622 if (router != null) {
623 builder.setRouterId(router);
625 if (networks != null) {
626 List<Uuid> nwList = builder.getNetworkIds();
627 if (nwList == null) {
628 nwList = new ArrayList<>();
630 nwList.addAll(networks);
631 builder.setNetworkIds(nwList);
634 isLockAcquired = NeutronUtils.lock(vpnId.getValue());
635 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
636 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
637 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
638 } catch (Exception e) {
639 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
641 if (isLockAcquired) {
642 NeutronUtils.unlock(vpnId.getValue());
647 // TODO Clean up the exception handling
648 @SuppressWarnings("checkstyle:IllegalCatch")
649 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
650 boolean isLockAcquired = false;
651 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
652 .child(VpnMap.class, new VpnMapKey(vpnId))
654 Optional<VpnMap> optionalVpnMap;
657 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
659 } catch (ReadFailedException e) {
660 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
663 if (optionalVpnMap.isPresent()) {
664 VpnMap vpnMap = optionalVpnMap.get();
665 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
666 if (routerId != null) {
667 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
669 // remove entire node in case of internal VPN
670 isLockAcquired = NeutronUtils.lock(vpnId.getValue());
671 LOG.debug("removing vpnMaps node: {} ", vpnId);
672 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
673 } catch (Exception e) {
674 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
676 if (isLockAcquired) {
677 NeutronUtils.unlock(vpnId.getValue());
682 vpnMapBuilder.setRouterId(null);
684 if (networkIds != null) {
685 List<Uuid> vpnNw = vpnMap.getNetworkIds();
686 vpnNw.removeAll(networkIds);
687 if (vpnNw.isEmpty()) {
688 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
689 vpnMapBuilder.setNetworkIds(null);
691 vpnMapBuilder.setNetworkIds(vpnNw);
696 isLockAcquired = NeutronUtils.lock(vpnId.getValue());
697 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
698 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
699 vpnMapBuilder.build());
700 } catch (Exception e) {
701 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
703 if (isLockAcquired) {
704 NeutronUtils.unlock(vpnId.getValue());
708 LOG.error("VPN : {} not found", vpnId.getValue());
710 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
713 // TODO Clean up the exception handling
714 @SuppressWarnings("checkstyle:IllegalCatch")
715 private void deleteVpnInstance(Uuid vpnId) {
716 boolean isLockAcquired = false;
717 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
718 .child(VpnInstance.class,
719 new VpnInstanceKey(vpnId.getValue()))
722 isLockAcquired = NeutronUtils.lock(vpnId.getValue());
723 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
724 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
725 } catch (Exception e) {
726 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
728 if (isLockAcquired) {
729 NeutronUtils.unlock(vpnId.getValue());
734 protected void createVpnInterface(Uuid vpnId, Port port, WriteTransaction wrtConfigTxn) {
735 String infName = port.getUuid().getValue();
736 List<Adjacency> adjList = new ArrayList<>();
737 Boolean isRouterInterface = false;
738 if (port.getDeviceOwner() != null) {
739 isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
741 LOG.trace("createVpnInterface - isRouterInterface:{}", isRouterInterface);
742 // create adjacency list
744 for (FixedIps ip : port.getFixedIps()) {
745 String ipValue = String.valueOf(ip.getIpAddress().getValue());
746 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
747 Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
748 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
749 .setSubnetId(ip.getSubnetId()).build();
752 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName,
753 port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
755 Uuid routerId = NeutronvpnUtils.getSubnetmap(dataBroker, ip.getSubnetId()).getRouterId();
756 if (routerId != null && routerId != rtrId) {
757 addToNeutronRouterInterfacesMap(routerId, infName);
758 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
759 if (rtr != null && rtr.getRoutes() != null) {
760 List<Routes> routeList = rtr.getRoutes();
761 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(vpnId, routeList, ipValue);
762 if (erAdjList != null && !erAdjList.isEmpty()) {
763 adjList.addAll(erAdjList);
769 // create vpn-interface on this neutron port
770 Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
771 writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
774 // TODO Clean up the exception handling
775 @SuppressWarnings("checkstyle:IllegalCatch")
776 protected void deleteVpnInterface(Uuid vpnId, Port port, WriteTransaction wrtConfigTxn) {
777 Boolean wrtConfigTxnPresent = true;
778 if (wrtConfigTxn == null) {
779 wrtConfigTxnPresent = false;
780 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
782 String infName = port.getUuid().getValue();
783 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
785 LOG.debug("Deleting vpn interface {}", infName);
786 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
789 List<FixedIps> ips = port.getFixedIps();
790 for (FixedIps ip : ips) {
791 String ipValue = String.valueOf(ip.getIpAddress().getValue());
792 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(),
793 ipValue, wrtConfigTxn);
794 Uuid routerId = NeutronvpnUtils.getSubnetmap(dataBroker, ip.getSubnetId()).getRouterId();
795 if (routerId != null && routerId != rtrId) {
796 removeFromNeutronRouterInterfacesMap(routerId, infName);
800 } catch (Exception ex) {
801 LOG.error("Deletion of vpninterface {} failed", infName, ex);
803 if (!wrtConfigTxnPresent) {
804 wrtConfigTxn.submit();
808 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
809 boolean isSubnetIp, WriteTransaction writeConfigTxn) {
810 if (vpnId == null || port == null) {
813 boolean isLockAcquired = false;
814 String infName = port.getUuid().getValue();
815 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
818 isLockAcquired = NeutronUtils.lock(infName);
819 Optional<VpnInterface> optionalVpnInterface =
820 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
822 if (optionalVpnInterface.isPresent()) {
823 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
824 .setVpnInstanceName(vpnId.getValue());
825 LOG.debug("Updating vpn interface {}", infName);
826 if (!isBeingAssociated) {
827 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
828 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
829 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
830 while (adjacencyIter.hasNext()) {
831 Adjacency adjacency = adjacencyIter.next();
832 String mipToQuery = adjacency.getIpAddress().split("/")[0];
833 InstanceIdentifier<LearntVpnVipToPort> id =
834 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
835 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
836 SingleTransactionDataBroker.syncReadOptional(dataBroker,
837 LogicalDatastoreType.OPERATIONAL, id);
838 if (optionalVpnVipToPort.isPresent()) {
839 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
840 + "from VPN {}", infName, vpnId, oldVpnId);
841 adjacencyIter.remove();
842 NeutronvpnUtils.removeLearntVpnVipToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
843 LOG.trace("Entry for fixedIP {} for port {} on VPN removed from "
844 + "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
847 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
848 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
850 List<FixedIps> ips = port.getFixedIps();
851 for (FixedIps ip : ips) {
852 String ipValue = String.valueOf(ip.getIpAddress().getValue());
853 if (oldVpnId != null) {
854 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(),
855 ipValue, writeConfigTxn);
857 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
858 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
860 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
863 LOG.error("VPN Interface {} not found", infName);
865 } catch (ReadFailedException ex) {
866 LOG.error("Updation of vpninterface {} failed", infName, ex);
868 if (isLockAcquired) {
869 NeutronUtils.unlock(infName);
874 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
875 List<String> ert, Uuid router, List<Uuid> networks) {
877 IpVersionChoice ipVersChoices = NeutronvpnUtils.getIpVersionChoicesFromRouterUuid(dataBroker, router);
879 // Update VPN Instance node
880 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
882 // Update local vpn-subnet DS
883 updateVpnMaps(vpn, name, router, tenant, networks);
885 if (router != null) {
886 Uuid existingVpn = NeutronvpnUtils.getVpnForRouter(dataBroker, router, true);
887 if (existingVpn != null) {
888 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
890 // if before reboot, router was already associated to VPN, should not proceed associating router to
891 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
892 // preserved upon reboot.
893 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
894 // RouterInterfacesMap via #createVPNInterface call.
895 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
896 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
899 associateRouterToInternalVpn(vpn, router);
904 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
905 * specified Neutron Networks and Routers.
907 * @param vpn Uuid of the VPN tp be created
908 * @param name Representative name of the new VPN
909 * @param tenant Uuid of the Tenant under which the VPN is going to be created
910 * @param rd Route-distinguisher for the VPN
911 * @param irt A list of Import Route Targets
912 * @param ert A list of Export Route Targets
913 * @param router UUID of the neutron router the VPN may be associated to
914 * @param networks UUID of the neutron network the VPN may be associated to
915 * @param type Type of the VPN Instance
916 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
917 * @throws Exception if association of L3VPN failed
919 public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
920 Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni)
923 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
924 IpVersionChoice vers = NeutronvpnUtils.getIpVersionChoicesFromRouterUuid(dataBroker, router);
925 ipVersChoices = ipVersChoices.addVersion(vers);
927 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, type, l3vni, ipVersChoices);
929 // Please note that router and networks will be filled into VPNMaps
930 // by subsequent calls here to associateRouterToVpn and
931 // associateNetworksToVpn
932 updateVpnMaps(vpn, name, null, tenant, null);
934 if (router != null) {
935 associateRouterToVpn(vpn, router);
937 if (networks != null) {
938 List<String> failStrings = associateNetworksToVpn(vpn, networks);
939 if (failStrings != null && !failStrings.isEmpty()) {
940 LOG.error("VPN {} association to networks failed for networks: {}. ",
941 vpn.getValue(), failStrings.toString());
942 throw new Exception(failStrings.toString());
948 * It handles the invocations to the createVPN RPC method.
951 // TODO Clean up the exception handling
952 @SuppressWarnings("checkstyle:IllegalCatch")
953 public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
955 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
956 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
957 List<RpcError> errorList = new ArrayList<>();
958 int failurecount = 0;
959 int warningcount = 0;
961 List<L3vpn> vpns = input.getL3vpn();
962 for (L3vpn vpn : vpns) {
963 RpcError error = null;
965 if (NeutronvpnUtils.doesVpnExist(dataBroker, vpn.getId())) {
966 msg = String.format("Creation of L3VPN failed for VPN %s due to VPN with the same ID already present",
967 vpn.getId().getValue());
969 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
970 errorList.add(error);
974 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
975 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
976 vpn.getId().getValue());
978 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
979 errorList.add(error);
983 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
985 if (vpn.getL3vni() != null) {
986 l3vni = vpn.getL3vni();
989 List<String> existingRDs = NeutronvpnUtils.getExistingRDs(dataBroker);
990 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
991 msg = String.format("Creation of L3VPN failed for VPN %s as another VPN with the same RD %s "
992 + "is already configured",
993 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0));
995 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
996 errorList.add(error);
1000 if (vpn.getRouterId() != null) {
1001 if (NeutronvpnUtils.getNeutronRouter(dataBroker, vpn.getRouterId()) == null) {
1002 msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
1003 vpn.getId().getValue(), vpn.getRouterId().getValue());
1005 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1006 errorList.add(error);
1010 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, vpn.getRouterId(), true);
1011 if (vpnId != null) {
1012 msg = String.format("Creation of L3VPN failed for VPN %s due to router %s already associated to "
1013 + "another VPN %s", vpn.getId().getValue(), vpn.getRouterId().getValue(),
1016 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1017 errorList.add(error);
1022 if (vpn.getNetworkIds() != null) {
1023 for (Uuid nw : vpn.getNetworkIds()) {
1024 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1025 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1026 if (network == null) {
1027 msg = String.format("Creation of L3VPN failed for VPN %s due to network not found %s",
1028 vpn.getId().getValue(), nw.getValue());
1030 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1031 errorList.add(error);
1033 } else if (vpnId != null) {
1034 msg = String.format("Creation of L3VPN failed for VPN %s due to network %s already associated"
1035 + " to another VPN %s", vpn.getId().getValue(), nw.getValue(),
1038 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1039 errorList.add(error);
1043 if (error != null) {
1048 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
1049 vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
1050 vpnInstanceType, l3vni);
1051 } catch (Exception ex) {
1052 msg = String.format("Creation of VPN failed for VPN %s", vpn.getId().getValue());
1054 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1055 errorList.add(error);
1059 // if at least one succeeds; result is success
1060 // if none succeeds; result is failure
1061 if (failurecount + warningcount == vpns.size()) {
1062 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1064 List<String> errorResponseList = new ArrayList<>();
1065 if (!errorList.isEmpty()) {
1066 for (RpcError rpcError : errorList) {
1067 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
1068 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
1069 errorResponseList.add(errorResponse);
1072 errorResponseList.add("Operation successful with no errors");
1074 opBuilder.setResponse(errorResponseList);
1075 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1081 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1084 public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1086 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1087 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1088 Uuid inputVpnId = input.getId();
1089 List<VpnInstance> vpns = new ArrayList<>();
1090 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1093 if (inputVpnId == null) {
1095 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1097 Optional<VpnInstances> optionalVpns =
1098 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1100 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1101 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
1102 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1103 // from getL3VPN output
1104 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
1110 opBuilder.setL3vpnInstances(l3vpnList);
1111 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1115 String name = inputVpnId.getValue();
1116 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1117 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1118 // read VpnInstance Info
1119 Optional<VpnInstance> optionalVpn =
1120 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1122 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1124 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1125 vpns.add(optionalVpn.get());
1127 String message = String.format("GetL3VPN failed because VPN %s is not present", name);
1129 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL,
1130 "invalid-value", message).build());
1133 for (VpnInstance vpnInstance : vpns) {
1134 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1135 // create VpnMaps id
1136 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1137 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1138 List<String> ertList = new ArrayList<>();
1139 List<String> irtList = new ArrayList<>();
1141 if (vpnInstance.getIpv4Family().getVpnTargets() != null) {
1142 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1143 for (VpnTarget vpnTarget : vpnTargetList) {
1144 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1145 ertList.add(vpnTarget.getVrfRTValue());
1147 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1148 irtList.add(vpnTarget.getVrfRTValue());
1150 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1151 ertList.add(vpnTarget.getVrfRTValue());
1152 irtList.add(vpnTarget.getVrfRTValue());
1157 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1159 if (vpnInstance.getL3vni() != null) {
1160 l3vpn.setL3vni(vpnInstance.getL3vni());
1162 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1163 .class, new VpnMapKey(vpnId)).build();
1164 Optional<VpnMap> optionalVpnMap =
1165 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1167 if (optionalVpnMap.isPresent()) {
1168 VpnMap vpnMap = optionalVpnMap.get();
1169 l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1170 .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1172 l3vpnList.add(l3vpn.build());
1175 opBuilder.setL3vpnInstances(l3vpnList);
1176 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1178 } catch (ReadFailedException ex) {
1179 String message = String.format("GetVPN failed due to %s", ex.getMessage());
1180 LOG.error(message, ex);
1181 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
1187 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1190 public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1192 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1193 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1194 List<RpcError> errorList = new ArrayList<>();
1196 int failurecount = 0;
1197 int warningcount = 0;
1198 List<Uuid> vpns = input.getId();
1199 for (Uuid vpn : vpns) {
1203 InstanceIdentifier<VpnInstance> vpnIdentifier =
1204 InstanceIdentifier.builder(VpnInstances.class)
1205 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1206 Optional<VpnInstance> optionalVpn =
1207 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1209 if (optionalVpn.isPresent()) {
1212 msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
1214 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
1215 errorList.add(error);
1218 } catch (ReadFailedException ex) {
1219 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
1221 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1222 errorList.add(error);
1226 // if at least one succeeds; result is success
1227 // if none succeeds; result is failure
1228 if (failurecount + warningcount == vpns.size()) {
1229 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1231 List<String> errorResponseList = new ArrayList<>();
1232 if (!errorList.isEmpty()) {
1233 for (RpcError rpcError : errorList) {
1234 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
1235 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
1236 errorResponseList.add(errorResponse);
1239 errorResponseList.add("Operation successful with no errors");
1241 opBuilder.setResponse(errorResponseList);
1242 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1247 public void createVpnInstanceForSubnet(Uuid subnetId) {
1248 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1249 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1252 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1253 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1254 removeVpn(subnetId);
1257 protected void addSubnetToVpn(final Uuid vpnId, Uuid subnet) {
1258 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
1259 Subnetmap sn = updateSubnetNode(subnet, null, vpnId);
1261 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1265 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1266 if (vpnMap == null) {
1267 LOG.error("addSubnetToVpn: No vpnMap for vpnId {}, cannot add subnet {} to VPN", vpnId.getValue(),
1272 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1273 if (isVpnOfTypeL2(vpnInstance)) {
1274 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1275 NeutronEvpnUtils.Operation.ADD);
1277 // Check if there are ports on this subnet and add corresponding
1279 List<Uuid> portList = sn.getPortList();
1280 if (portList != null) {
1281 for (final Uuid portId : portList) {
1282 LOG.debug("addSubnetToVpn: adding vpn-interface for vpnId {}", vpnId.getValue());
1283 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1284 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1285 List<ListenableFuture<Void>> futures = new ArrayList<>();
1286 createVpnInterface(vpnId, NeutronvpnUtils.getNeutronPort(dataBroker, portId), wrtConfigTxn);
1287 futures.add(wrtConfigTxn.submit());
1294 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1295 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1296 oldVpnId.getValue(), newVpnId.getValue());
1297 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId);
1299 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1303 //Update Router Interface first synchronously.
1304 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1306 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1307 updateVpnInterface(newVpnId, oldVpnId,
1308 NeutronvpnUtils.getNeutronPort(dataBroker, sn.getRouterInterfacePortId()),
1309 isBeingAssociated, true, wrtConfigTxn);
1310 wrtConfigTxn.submit().checkedGet();
1311 } catch (TransactionCommitFailedException e) {
1312 LOG.error("Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, returning",
1313 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId);
1317 // Check for ports on this subnet and update association of
1318 // corresponding vpn-interfaces to external vpn
1319 List<Uuid> portList = sn.getPortList();
1320 if (portList != null) {
1321 for (Uuid port : portList) {
1322 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1323 port.getValue(), isBeingAssociated);
1324 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> {
1325 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1326 List<ListenableFuture<Void>> futures = new ArrayList<>();
1327 updateVpnInterface(newVpnId, oldVpnId, NeutronvpnUtils.getNeutronPort(dataBroker, port),
1328 isBeingAssociated, false, wrtConfigTxn);
1329 futures.add(wrtConfigTxn.submit());
1337 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1338 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1339 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1342 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1343 synchronized (routerId.getValue().intern()) {
1344 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1346 Optional<RouterInterfaces> optRouterInterfaces =
1347 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1348 routerInterfacesId);
1349 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1350 .setInterfaceId(interfaceName).build();
1351 if (optRouterInterfaces.isPresent()) {
1352 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1353 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1356 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1357 List<Interfaces> interfaces = new ArrayList<>();
1358 interfaces.add(routerInterface);
1359 // TODO Shouldn't we be doing something with builder and interfaces?
1360 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
1361 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)),
1364 } catch (ReadFailedException e) {
1365 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1370 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1371 synchronized (routerId.getValue().intern()) {
1372 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1374 Optional<RouterInterfaces> optRouterInterfaces =
1375 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1376 routerInterfacesId);
1377 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1378 .setInterfaceId(interfaceName).build();
1379 if (optRouterInterfaces.isPresent()) {
1380 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1381 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1382 if (interfaces != null && interfaces.remove(routerInterface)) {
1383 if (interfaces.isEmpty()) {
1384 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1386 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1387 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1391 } catch (ReadFailedException e) {
1392 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1398 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1399 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1400 * route will be ignored.
1402 * @param vpnName the VPN identifier
1403 * @param interVpnLinkRoutes The list of static routes
1404 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1406 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1407 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1408 for (Routes route : interVpnLinkRoutes) {
1409 String nexthop = String.valueOf(route.getNexthop().getValue());
1410 String destination = String.valueOf(route.getDestination().getValue());
1411 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1412 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1413 AddStaticRouteInput rpcInput =
1414 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1415 .setVpnInstanceName(vpnName.getValue())
1417 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1418 RpcResult<AddStaticRouteOutput> rpcResult;
1420 rpcResult = labelOuputFtr.get();
1421 if (rpcResult.isSuccessful()) {
1422 LOG.debug("Label generated for destination {} is: {}",
1423 destination, rpcResult.getResult().getLabel());
1425 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1426 destination, nexthop, rpcResult.getErrors());
1428 } catch (InterruptedException | ExecutionException e) {
1429 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
1430 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
1433 // Any other case is a fault.
1434 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1435 String.valueOf(route.getDestination().getValue()), nexthop);
1442 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1443 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1445 * @param vpnName the VPN identifier
1446 * @param interVpnLinkRoutes The list of static routes
1447 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1449 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1450 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1451 for (Routes route : interVpnLinkRoutes) {
1452 String nexthop = String.valueOf(route.getNexthop().getValue());
1453 String destination = String.valueOf(route.getDestination().getValue());
1454 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1455 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1456 RemoveStaticRouteInput rpcInput =
1457 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1458 .setVpnInstanceName(vpnName.getValue())
1460 vpnRpcService.removeStaticRoute(rpcInput);
1462 // Any other case is a fault.
1463 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1464 String.valueOf(route.getDestination().getValue()), nexthop);
1471 * Returns true if the specified nexthop is the other endpoint in an
1472 * InterVpnLink, regarding one of the VPN's point of view.
1474 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1476 interVpnLink != null
1477 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1478 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
1479 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1480 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
1483 protected List<Adjacency> getAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList, String fixedIp) {
1484 List<Adjacency> adjList = new ArrayList<>();
1485 Map<String, List<String>> adjMap = new HashMap<>();
1486 for (Routes route : routeList) {
1487 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1488 LOG.error("Incorrect input received for extra route. {}", route);
1490 String nextHop = String.valueOf(route.getNexthop().getValue());
1491 String destination = String.valueOf(route.getDestination().getValue());
1492 if (!nextHop.equals(fixedIp)) {
1493 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1496 LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} ", destination,
1497 vpnId.getValue(), nextHop);
1498 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1499 if (!hops.contains(nextHop)) {
1505 for (String destination : adjMap.keySet()) {
1506 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1507 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(adjMap.get(destination))
1508 .setKey(new AdjacencyKey(destination)).build();
1514 // TODO Clean up the exception handling
1515 @SuppressWarnings("checkstyle:IllegalCatch")
1516 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1517 for (Routes route : routeList) {
1518 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1519 LOG.error("Incorrect input received for extra route. {}", route);
1521 String nextHop = String.valueOf(route.getNexthop().getValue());
1522 String destination = String.valueOf(route.getDestination().getValue());
1523 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1525 if (infName != null) {
1526 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
1527 destination, vpnId.getValue(), nextHop, infName);
1528 boolean isLockAcquired = false;
1530 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
1531 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1532 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
1533 .child(Adjacency.class, new AdjacencyKey(destination));
1534 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1535 .setNextHopIpList(Collections.singletonList(nextHop)).setKey(new AdjacencyKey(destination))
1536 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
1537 isLockAcquired = NeutronUtils.lock(infName);
1538 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, erAdj);
1539 } catch (Exception e) {
1540 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
1541 destination, nextHop, e);
1543 if (isLockAcquired) {
1544 NeutronUtils.unlock(infName);
1548 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1549 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1555 // TODO Clean up the exception handling
1556 @SuppressWarnings("checkstyle:IllegalCatch")
1557 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
1558 for (Routes route : routeList) {
1559 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
1560 boolean isLockAcquired = false;
1561 String nextHop = String.valueOf(route.getNexthop().getValue());
1562 String destination = String.valueOf(route.getDestination().getValue());
1563 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1565 if (infName == null) {
1566 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
1567 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1568 // Proceed to remove the next extra-route
1571 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
1572 destination, vpnId.getValue(), nextHop, infName);
1574 InstanceIdentifier<Adjacency> adjacencyIdentifier =
1575 InstanceIdentifier.builder(VpnInterfaces.class)
1576 .child(VpnInterface.class, new VpnInterfaceKey(infName))
1577 .augmentation(Adjacencies.class)
1578 .child(Adjacency.class, new AdjacencyKey(destination))
1581 // Looking for existing prefix in MDSAL database
1582 Optional<Adjacency> adjacency = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1583 adjacencyIdentifier);
1584 boolean updateNextHops = false;
1585 List<String> nextHopList = new ArrayList<>();
1586 if (adjacency.isPresent()) {
1587 List<String> nhListRead = adjacency.get().getNextHopIpList();
1588 if (nhListRead.size() > 1) { // ECMP case
1589 for (String nextHopRead : nhListRead) {
1590 if (nextHopRead.equals(nextHop)) {
1591 updateNextHops = true;
1593 nextHopList.add(nextHopRead);
1600 isLockAcquired = NeutronUtils.lock(infName);
1601 if (updateNextHops) {
1602 // An update must be done, not including the current next hop
1603 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
1604 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1605 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
1606 .setNextHopIpList(nextHopList)
1607 .setKey(new AdjacencyKey(destination))
1609 Adjacencies erAdjs =
1610 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
1611 VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
1612 .addAugmentation(Adjacencies.class, erAdjs).build();
1613 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
1615 // Remove the whole route
1616 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1617 LOG.trace("extra route {} deleted successfully", route);
1619 } catch (Exception e) {
1620 LOG.error("exception in deleting extra route with destination {} for interface {}",
1621 destination, infName, e);
1623 if (isLockAcquired) {
1624 NeutronUtils.unlock(infName);
1628 LOG.error("Incorrect input received for extra route: {}", route);
1633 public void removeVpn(Uuid id) {
1635 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, id);
1636 Uuid router = vpnMap != null ? vpnMap.getRouterId() : null;
1637 // dissociate router
1638 if (router != null) {
1639 dissociateRouterFromVpn(id, router);
1641 // dissociate networks
1642 if (!id.equals(router)) {
1643 dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
1645 // remove entire vpnMaps node
1646 deleteVpnMapsNode(id);
1648 // remove vpn-instance
1649 deleteVpnInstance(id);
1652 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet) {
1653 LOG.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
1654 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1655 if (vpnMap == null) {
1656 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1657 vpnId.getValue(), subnet.getValue());
1660 Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1661 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1662 if (isVpnOfTypeL2(vpnInstance)) {
1663 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1664 NeutronEvpnUtils.Operation.DELETE);
1667 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1668 List<Uuid> portList = sn.getPortList();
1669 if (portList != null) {
1670 for (final Uuid portId : portList) {
1671 LOG.debug("removing vpn-interface for port {}", portId.getValue());
1672 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1673 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1674 List<ListenableFuture<Void>> futures = new ArrayList<>();
1675 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1678 deleteVpnInterface(vpnId, port, wrtConfigTxn);
1680 LOG.warn("Cannot proceed with deleteVpnInterface for port {} in subnet {} since port is "
1681 + "absent in Neutron config DS", portId.getValue(), subnet.getValue());
1683 futures.add(wrtConfigTxn.submit());
1688 // update subnet-vpn association
1689 removeFromSubnetNode(subnet, null, null, vpnId, null);
1691 LOG.error("Subnetmap for subnet {} not found", subnet.getValue());
1695 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
1696 return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
1699 // TODO Clean up the exception handling
1700 @SuppressWarnings("checkstyle:IllegalCatch")
1701 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
1702 updateVpnMaps(vpnId, null, routerId, null, null);
1703 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
1704 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1705 if (routerSubnets != null) {
1706 for (Uuid subnetId : routerSubnets) {
1707 Subnetmap sn = updateVpnForSubnet(routerId, vpnId, subnetId, true);
1708 if (NeutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(dataBroker, sn, vpnId)) {
1709 NeutronvpnUtils.updateVpnInstanceWithIpFamily(dataBroker, vpnId.getValue(),
1710 NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
1715 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
1716 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
1718 } catch (Exception e) {
1719 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
1720 .getValue(), vpnId.getValue(), e);
1724 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
1725 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1726 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
1727 for (Uuid subnet : routerSubnets) {
1728 addSubnetToVpn(vpnId, subnet);
1732 // TODO Clean up the exception handling
1733 @SuppressWarnings("checkstyle:IllegalCatch")
1734 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
1736 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1737 boolean vpnInstanceIpVersionsRemoved = false;
1738 IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
1739 if (routerSubnets != null) {
1740 for (Uuid subnetId : routerSubnets) {
1741 Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnetId);
1742 if (NeutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(dataBroker, sn, vpnId)) {
1743 vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
1744 .getIpVersionFromString(sn.getSubnetIp()));
1745 vpnInstanceIpVersionsRemoved = true;
1747 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
1748 updateVpnForSubnet(vpnId, routerId, subnetId, false);
1751 if (vpnInstanceIpVersionsRemoved) {
1752 NeutronvpnUtils.updateVpnInstanceWithIpFamily(dataBroker, vpnId.getValue(),
1753 vpnInstanceIpVersionsToRemove, false);
1755 clearFromVpnMaps(vpnId, routerId, null);
1757 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
1758 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
1760 } catch (Exception e) {
1761 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
1762 .getValue(), vpnId.getValue(), e);
1766 protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
1767 List<String> failedNwList = new ArrayList<>();
1768 List<Uuid> passedNwList = new ArrayList<>();
1769 if (!networks.isEmpty()) {
1770 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpn.getValue());
1771 if (vpnInstance == null) {
1772 LOG.error("VPN %s not present when associating network to it", vpn.getValue());
1773 failedNwList.add(String.format("Failed to associate network on vpn %s as vpn is not present",
1775 return failedNwList;
1777 // process corresponding subnets for VPN
1778 for (Uuid nw : networks) {
1779 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1780 NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
1781 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
1782 LOG.error("MultiSegmented networks not supported in VPN. Failed to associate network {} on vpn {}",
1783 nw.getValue(), vpn.getValue());
1784 failedNwList.add(String.format("Failed to associate network %s on vpn %s as it is multisegmented.",
1785 nw.getValue(), vpn.getValue()));
1789 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1790 if (network == null) {
1791 failedNwList.add(String.format("network %s not found", nw.getValue()));
1792 } else if (vpnId != null) {
1793 failedNwList.add(String.format("network %s already associated to another VPN %s", nw.getValue(),
1795 } else if (isVpnOfTypeL2(vpnInstance)
1796 && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
1797 LOG.error("EVPN supports only one network to be associated");
1798 failedNwList.add("EVPN supports only one network to be associated");
1800 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1801 LOG.debug("Adding network subnets...{}", networkSubnets);
1802 if (networkSubnets != null) {
1803 for (Uuid subnet : networkSubnets) {
1804 // check if subnet added as router interface to some router
1805 Uuid subnetVpnId = NeutronvpnUtils.getVpnForSubnet(dataBroker, subnet);
1806 if (subnetVpnId == null) {
1807 Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1808 if (NeutronvpnUtils.shouldVpnHandleIpVersionChangeToAdd(dataBroker, sn, vpn)) {
1809 NeutronvpnUtils.updateVpnInstanceWithIpFamily(dataBroker, vpn.getValue(),
1810 NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()), true);
1812 addSubnetToVpn(vpn, subnet);
1813 passedNwList.add(nw);
1816 String.format("subnet %s already added as router interface bound to "
1817 + "internal/external VPN %s", subnet.getValue(),
1818 subnetVpnId.getValue()));
1822 if (NeutronvpnUtils.getIsExternal(network)) {
1823 nvpnNatManager.addExternalNetworkToVpn(network, vpn);
1826 } catch (ReadFailedException e) {
1827 LOG.error("Error determining whether {} is associated", vpnInstance, e);
1828 failedNwList.add("Error determining whether VPN " + vpn.getValue() + " is associated");
1831 updateVpnMaps(vpn, null, null, null, passedNwList);
1833 return failedNwList;
1836 protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
1837 List<String> failedNwList = new ArrayList<>();
1838 List<Uuid> passedNwList = new ArrayList<>();
1839 if (networks != null && !networks.isEmpty()) {
1840 // process corresponding subnets for VPN
1841 for (Uuid nw : networks) {
1842 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1843 if (network == null) {
1844 failedNwList.add(String.format("network %s not found", nw.getValue()));
1846 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1847 if (vpn.equals(vpnId)) {
1848 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1849 LOG.debug("Removing network subnets...");
1850 if (networkSubnets != null) {
1851 boolean vpnInstanceIpVersionsRemoved = false;
1852 IpVersionChoice vpnInstanceIpVersionsToRemove = IpVersionChoice.UNDEFINED;
1853 for (Uuid subnet : networkSubnets) {
1854 Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1855 if (NeutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(dataBroker, sn, vpn)) {
1856 vpnInstanceIpVersionsToRemove.addVersion(NeutronvpnUtils
1857 .getIpVersionFromString(sn.getSubnetIp()));
1858 vpnInstanceIpVersionsRemoved = true;
1860 removeSubnetFromVpn(vpn, subnet);
1862 passedNwList.add(nw);
1864 if (vpnInstanceIpVersionsRemoved) {
1865 NeutronvpnUtils.updateVpnInstanceWithIpFamily(dataBroker, vpn.getValue(),
1866 vpnInstanceIpVersionsToRemove, false);
1870 if (vpnId == null) {
1871 failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
1874 failedNwList.add(String.format("input network %s associated to a another vpn %s instead "
1875 + "of the one given as input", nw.getValue(), vpnId.getValue()));
1878 if (NeutronvpnUtils.getIsExternal(network)) {
1879 nvpnNatManager.removeExternalNetworkFromVpn(network);
1883 clearFromVpnMaps(vpn, null, passedNwList);
1885 return failedNwList;
1889 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
1892 // TODO Clean up the exception handling
1893 @SuppressWarnings("checkstyle:IllegalCatch")
1894 public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1896 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
1897 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
1898 LOG.debug("associateNetworks {}", input);
1899 StringBuilder returnMsg = new StringBuilder();
1900 Uuid vpnId = input.getVpnId();
1903 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1904 List<Uuid> netIds = input.getNetworkId();
1905 if (netIds != null && !netIds.isEmpty()) {
1906 List<String> failed = associateNetworksToVpn(vpnId, netIds);
1907 if (!failed.isEmpty()) {
1908 returnMsg.append(failed);
1912 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1914 if (returnMsg.length() != 0) {
1915 String message = String.format("associate Networks to vpn %s failed due to %s",
1916 vpnId.getValue(), returnMsg);
1918 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
1920 opBuilder.setResponse(errorResponse);
1921 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
1923 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
1925 } catch (Exception ex) {
1926 String message = String.format("associate Networks to vpn %s failed due to %s",
1927 input.getVpnId().getValue(), ex.getMessage());
1928 LOG.error(message, ex);
1929 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1932 LOG.debug("associateNetworks returns..");
1937 * It handles the invocations to the neutronvpn:associateRouter RPC method.
1940 // TODO Clean up the exception handling
1941 @SuppressWarnings("checkstyle:IllegalCatch")
1942 public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1944 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1945 LOG.debug("associateRouter {}", input);
1946 StringBuilder returnMsg = new StringBuilder();
1947 Uuid vpnId = input.getVpnId();
1948 Uuid routerId = input.getRouterId();
1950 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1951 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1952 if (vpnMap != null) {
1954 Uuid extVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1955 if (vpnMap.getRouterId() != null) {
1956 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
1957 .append(vpnMap.getRouterId().getValue());
1958 } else if (extVpnId != null) {
1959 returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
1960 + "another VPN ").append(extVpnId.getValue());
1962 associateRouterToVpn(vpnId, routerId);
1965 returnMsg.append("router not found : ").append(routerId.getValue());
1968 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1970 if (returnMsg.length() != 0) {
1971 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1974 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1977 result.set(RpcResultBuilder.<Void>success().build());
1979 } catch (Exception ex) {
1980 String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
1981 vpnId.getValue(), ex.getMessage());
1982 LOG.error(message, ex);
1983 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1985 LOG.debug("associateRouter returns..");
1989 /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
1992 // TODO Clean up the exception handling
1993 @SuppressWarnings("checkstyle:IllegalCatch")
1994 public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
1995 GetFixedIPsForNeutronPortInput input) {
1996 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
1997 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
1998 Uuid portId = input.getPortId();
1999 StringBuilder returnMsg = new StringBuilder();
2001 List<String> fixedIPList = new ArrayList<>();
2002 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
2004 List<FixedIps> fixedIPs = port.getFixedIps();
2005 for (FixedIps ip : fixedIPs) {
2006 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
2009 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2011 if (returnMsg.length() != 0) {
2012 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
2014 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
2015 .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
2017 opBuilder.setFixedIPs(fixedIPList);
2018 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2020 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2022 } catch (Exception ex) {
2023 String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s",
2024 portId.getValue(), ex.getMessage());
2025 LOG.error(message, ex);
2026 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
2027 .withError(ErrorType.APPLICATION, message).build());
2033 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2036 // TODO Clean up the exception handling
2037 @SuppressWarnings("checkstyle:IllegalCatch")
2038 public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2040 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2041 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2043 LOG.debug("dissociateNetworks {}", input);
2044 StringBuilder returnMsg = new StringBuilder();
2045 Uuid vpnId = input.getVpnId();
2048 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
2049 List<Uuid> netIds = input.getNetworkId();
2050 if (netIds != null && !netIds.isEmpty()) {
2051 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2052 if (!failed.isEmpty()) {
2053 returnMsg.append(failed);
2057 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2059 if (returnMsg.length() != 0) {
2060 String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
2063 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
2065 opBuilder.setResponse(errorResponse);
2066 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2068 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2070 } catch (Exception ex) {
2071 String message = String.format("dissociate Networks to vpn %s failed due to %s",
2072 input.getVpnId().getValue(), ex.getMessage());
2073 LOG.error(message, ex);
2074 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
2077 LOG.debug("dissociateNetworks returns..");
2082 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2085 // TODO Clean up the exception handling
2086 @SuppressWarnings("checkstyle:IllegalCatch")
2087 public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
2089 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
2091 LOG.debug("dissociateRouter {}", input);
2092 StringBuilder returnMsg = new StringBuilder();
2093 Uuid vpnId = input.getVpnId();
2094 Uuid routerId = input.getRouterId();
2096 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
2097 if (routerId != null) {
2098 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
2100 Uuid routerVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
2101 if (vpnId.equals(routerVpnId)) {
2102 dissociateRouterFromVpn(vpnId, routerId);
2104 if (routerVpnId == null) {
2105 returnMsg.append("input router ").append(routerId.getValue())
2106 .append(" not associated to any vpn yet");
2108 returnMsg.append("input router ").append(routerId.getValue())
2109 .append(" associated to vpn ")
2110 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2114 returnMsg.append("router not found : ").append(routerId.getValue());
2118 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2120 if (returnMsg.length() != 0) {
2121 String message = String.format("dissociate router %s to vpn %s failed due to %s", routerId.getValue(),
2122 vpnId.getValue(), returnMsg);
2124 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
2126 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
2129 result.set(RpcResultBuilder.<Void>success().build());
2131 } catch (Exception ex) {
2132 String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
2133 vpnId.getValue(), ex.getMessage());
2134 LOG.error(message, ex);
2135 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
2137 LOG.debug("dissociateRouter returns..");
2142 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
2143 // check if the router is associated to some VPN
2144 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
2145 if (vpnId != null) {
2146 // remove existing external vpn interfaces
2147 for (Uuid subnetId : routerSubnetIds) {
2148 removeSubnetFromVpn(vpnId, subnetId);
2150 clearFromVpnMaps(vpnId, routerId, null);
2152 // remove existing internal vpn interfaces
2153 for (Uuid subnetId : routerSubnetIds) {
2154 removeSubnetFromVpn(routerId, subnetId);
2157 // delete entire vpnMaps node for internal VPN
2158 deleteVpnMapsNode(routerId);
2160 // delete vpn-instance for internal VPN
2161 deleteVpnInstance(routerId);
2164 protected Subnet getNeutronSubnet(Uuid subnetId) {
2165 return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
2168 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2169 Subnet sn = NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
2171 return sn.getGatewayIp();
2177 protected Network getNeutronNetwork(Uuid networkId) {
2178 return NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
2181 protected Port getNeutronPort(String name) {
2182 return NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(name));
2185 protected Port getNeutronPort(Uuid portId) {
2186 return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
2189 protected Uuid getNetworkForSubnet(Uuid subnetId) {
2190 return NeutronvpnUtils.getNetworkForSubnet(dataBroker, subnetId);
2193 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2194 return NeutronvpnUtils.getNetworksforVpn(dataBroker, vpnId);
2198 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2200 * @return a List of String to be printed on screen
2201 * @throws ReadFailedException if there was a problem reading from the data store
2203 public List<String> showNeutronPortsCLI() throws ReadFailedException {
2204 List<String> result = new ArrayList<>();
2205 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2207 result.add("-------------------------------------------------------------------------------------------");
2208 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2210 Optional<Ports> ports = syncReadOptional(dataBroker, CONFIGURATION, portidentifier);
2211 if (ports.isPresent() && ports.get().getPort() != null) {
2212 for (Port port : ports.get().getPort()) {
2213 List<FixedIps> fixedIPs = port.getFixedIps();
2214 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2215 List<String> ipList = new ArrayList<>();
2216 for (FixedIps fixedIp : fixedIPs) {
2217 IpAddress ipAddress = fixedIp.getIpAddress();
2218 if (ipAddress.getIpv4Address() != null) {
2219 ipList.add(ipAddress.getIpv4Address().getValue());
2221 ipList.add(ipAddress.getIpv6Address().getValue());
2224 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2225 .getMacAddress().getValue(), NeutronvpnUtils.getIPPrefixFromPort(dataBroker, port),
2226 ipList.toString()));
2228 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2229 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2238 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2240 * @param vpnuuid Uuid of the VPN whose config must be shown
2241 * @return formatted output list
2242 * @throws InterruptedException if there was a thread related problem getting the data to display
2243 * @throws ExecutionException if there was any other problem getting the data to display
2245 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2246 List<String> result = new ArrayList<>();
2247 if (vpnuuid == null) {
2249 result.add("Displaying VPN config for all VPNs");
2250 result.add("To display VPN config for a particular VPN, use the following syntax");
2251 result.add(getshowVpnConfigCLIHelp());
2253 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2254 if (rpcResult.isSuccessful()) {
2256 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2258 result.add(String.format(" %-80s ", "Import-RTs"));
2260 result.add(String.format(" %-80s ", "Export-RTs"));
2262 result.add(String.format(" %-76s ", "Subnet IDs"));
2264 result.add("------------------------------------------------------------------------------------");
2266 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2267 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2268 .rev150602.VpnInstance vpn : vpnList) {
2269 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2271 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2272 vpn.getRouteDistinguisher()));
2274 result.add(String.format(" %-80s ", vpn.getImportRT()));
2276 result.add(String.format(" %-80s ", vpn.getExportRT()));
2279 Uuid vpnid = vpn.getId();
2280 List<Uuid> subnetList = NeutronvpnUtils.getSubnetsforVpn(dataBroker, vpnid);
2281 if (!subnetList.isEmpty()) {
2282 for (Uuid subnetuuid : subnetList) {
2283 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2286 result.add(String.format(" %-76s ", "\" \""));
2289 result.add("----------------------------------------");
2293 String errortag = rpcResult.getErrors().iterator().next().getTag();
2294 if (Objects.equals(errortag, "")) {
2296 result.add("No VPN has been configured yet");
2297 } else if (Objects.equals(errortag, "invalid-value")) {
2299 result.add("VPN " + vpnuuid.getValue() + " is not present");
2301 result.add("error getting VPN info : " + rpcResult.getErrors());
2302 result.add(getshowVpnConfigCLIHelp());
2308 protected void createExternalVpnInterfaces(Uuid extNetId) {
2309 if (extNetId == null) {
2310 LOG.error("createExternalVpnInterfaces: external network is null");
2314 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2315 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2316 LOG.error("No external ports attached to external network {}", extNetId.getValue());
2320 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2321 for (String elanInterface : extElanInterfaces) {
2322 createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
2324 wrtConfigTxn.submit();
2327 // TODO Clean up the exception handling
2328 @SuppressWarnings("checkstyle:IllegalCatch")
2329 protected void removeExternalVpnInterfaces(Uuid extNetId) {
2330 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2331 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2332 LOG.error("No external ports attached for external network {}", extNetId.getValue());
2337 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2338 for (String elanInterface : extElanInterfaces) {
2339 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2340 .buildVpnInterfaceIdentifier(elanInterface);
2341 LOG.info("Removing vpn interface {}", elanInterface);
2342 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2344 wrtConfigTxn.submit();
2346 } catch (Exception ex) {
2347 LOG.error("Removal of vpninterfaces {} failed", extElanInterfaces, ex);
2351 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2352 writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, wrtConfigTxn);
2355 // TODO Clean up the exception handling
2356 @SuppressWarnings("checkstyle:IllegalCatch")
2357 private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
2358 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2359 if (vpnId == null || infName == null) {
2360 LOG.error("vpn id or interface is null");
2364 Boolean wrtConfigTxnPresent = true;
2365 if (wrtConfigTxn == null) {
2366 wrtConfigTxnPresent = false;
2367 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2370 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2371 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2373 .setVpnInstanceName(vpnId.getValue())
2374 .setRouterInterface(isRouterInterface);
2375 if (adjacencies != null) {
2376 vpnb.addAugmentation(Adjacencies.class, adjacencies);
2378 VpnInterface vpnIf = vpnb.build();
2380 LOG.info("Creating vpn interface {}", vpnIf);
2381 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2382 } catch (Exception ex) {
2383 LOG.error("Creation of vpninterface {} failed", infName, ex);
2386 if (!wrtConfigTxnPresent) {
2387 wrtConfigTxn.submit();
2391 private String getshowVpnConfigCLIHelp() {
2392 StringBuilder help = new StringBuilder("Usage:");
2393 help.append("display vpn-config [-vid/--vpnid <id>]");
2394 return help.toString();
2397 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
2398 InterruptedException {
2399 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
2400 .setVpnId(vpnId).build();
2401 LOG.info("publishing notification upon association of router to VPN");
2402 notificationPublishService.putNotification(routerAssociatedToVpn);
2405 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
2406 InterruptedException {
2407 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
2408 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
2409 LOG.info("publishing notification upon disassociation of router from VPN");
2410 notificationPublishService.putNotification(routerDisassociatedFromVpn);
2413 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
2414 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
2418 public Future<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
2419 return neutronEvpnManager.createEVPN(input);
2423 public Future<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
2424 return neutronEvpnManager.getEVPN(input);
2428 public Future<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
2429 return neutronEvpnManager.deleteEVPN(input);