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 com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import com.google.common.util.concurrent.SettableFuture;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.EventListener;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.List;
21 import java.util.Objects;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.Future;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
29 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
30 import org.opendaylight.genius.mdsalutil.MDSALUtil;
31 import org.opendaylight.netvirt.elanmanager.api.IElanService;
32 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
34 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
35 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
36 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
42 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
43 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
44 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
46 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpnBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpnBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
116 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
117 import org.opendaylight.yangtools.yang.common.RpcError;
118 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
119 import org.opendaylight.yangtools.yang.common.RpcResult;
120 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
121 import org.slf4j.Logger;
122 import org.slf4j.LoggerFactory;
124 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
125 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
126 private final DataBroker dataBroker;
127 private final NeutronvpnNatManager nvpnNatManager;
128 private final NotificationPublishService notificationPublishService;
129 private final VpnRpcService vpnRpcService;
130 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
131 private final IElanService elanService;
132 private final NeutronvpnConfig neutronvpnConfig;
134 public NeutronvpnManager(
135 final DataBroker dataBroker, final NotificationPublishService notiPublishService,
136 final NeutronvpnNatManager vpnNatMgr, final VpnRpcService vpnRpcSrv, final IElanService elanService,
137 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
138 final NeutronvpnConfig neutronvpnConfig) {
139 this.dataBroker = dataBroker;
140 nvpnNatManager = vpnNatMgr;
141 notificationPublishService = notiPublishService;
142 vpnRpcService = vpnRpcSrv;
143 this.elanService = elanService;
144 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
145 this.neutronvpnConfig = neutronvpnConfig;
149 public void close() throws Exception {
150 LOG.info("{} close", getClass().getSimpleName());
153 public NeutronvpnConfig getNeutronvpnConfig() {
154 return neutronvpnConfig;
157 // TODO Clean up the exception handling
158 @SuppressWarnings("checkstyle:IllegalCatch")
159 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId) {
161 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
162 synchronized (subnetId.getValue().intern()) {
163 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
164 subnetMapIdentifier);
165 SubnetmapBuilder subnetmapBuilder = null;
166 if (sn.isPresent()) {
167 LOG.error("subnetmap node for subnet ID {} already exists, returning", subnetId.getValue());
170 subnetmapBuilder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId)
171 .setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId);
172 LOG.debug("Adding a new subnet node in Subnetmaps DS for subnet {}", subnetId.getValue());
174 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
175 subnetMapIdentifier, subnetmapBuilder.build());
177 } catch (Exception e) {
178 LOG.error("Creating subnetmap node failed for subnet {}", subnetId.getValue());
182 // TODO Clean up the exception handling
183 @SuppressWarnings("checkstyle:IllegalCatch")
184 private Subnetmap updateSubnetNode(Uuid subnetId, Uuid routerId, Uuid vpnId) {
185 Subnetmap subnetmap = null;
186 SubnetmapBuilder builder = null;
187 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
188 .child(Subnetmap.class, new SubnetmapKey(subnetId))
191 synchronized (subnetId.getValue().intern()) {
192 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
193 if (sn.isPresent()) {
194 builder = new SubnetmapBuilder(sn.get());
195 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
197 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
200 if (routerId != null) {
201 builder.setRouterId(routerId);
204 builder.setVpnId(vpnId);
207 subnetmap = builder.build();
208 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
209 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
211 } catch (Exception e) {
212 LOG.error("Updation of subnetMap failed for node: {}", subnetId.getValue());
217 // TODO Clean up the exception handling
218 @SuppressWarnings("checkstyle:IllegalCatch")
219 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, Uuid routerId,
220 Uuid routerInterfacePortId, String fixedIp,
221 String routerIntfMacAddress) {
222 Subnetmap subnetmap = null;
223 SubnetmapBuilder builder = null;
224 InstanceIdentifier<Subnetmap> id =
225 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
227 synchronized (subnetId.getValue().intern()) {
228 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
229 if (sn.isPresent()) {
230 builder = new SubnetmapBuilder(sn.get());
231 LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
232 subnetId.getValue());
234 LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
235 subnetId.getValue());
238 builder.setRouterId(routerId);
239 builder.setRouterInterfacePortId(routerInterfacePortId);
240 builder.setRouterIntfMacAddress(routerIntfMacAddress);
241 builder.setRouterInterfaceFixedIp(fixedIp);
242 subnetmap = builder.build();
243 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
244 subnetId.getValue());
245 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
247 } catch (Exception e) {
248 LOG.error("WithRouterFixedIP: Updation of subnetMap for Router FixedIp failed for node: {}",
249 subnetId.getValue());
253 // TODO Clean up the exception handling
254 @SuppressWarnings("checkstyle:IllegalCatch")
255 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
256 Subnetmap subnetmap = null;
257 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
258 new SubnetmapKey(subnetId)).build();
260 synchronized (subnetId.getValue().intern()) {
261 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
262 if (sn.isPresent()) {
263 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
264 if (null != portId) {
265 List<Uuid> portList = builder.getPortList();
266 if (null == portList) {
267 portList = new ArrayList<>();
269 portList.add(portId);
270 builder.setPortList(portList);
271 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
274 if (null != directPortId) {
275 List<Uuid> directPortList = builder.getDirectPortList();
276 if (null == directPortList) {
277 directPortList = new ArrayList<>();
279 directPortList.add(directPortId);
280 builder.setDirectPortList(directPortList);
281 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
282 directPortId.getValue());
284 subnetmap = builder.build();
285 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
288 LOG.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
291 } catch (Exception e) {
292 LOG.error("Updating port list of a given subnetMap failed for node: {} with exception{}",
293 subnetId.getValue(), e);
298 // TODO Clean up the exception handling
299 @SuppressWarnings("checkstyle:IllegalCatch")
300 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
301 Subnetmap subnetmap = null;
302 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
303 .child(Subnetmap.class, new SubnetmapKey(subnetId))
306 synchronized (subnetId.getValue().intern()) {
307 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
308 if (sn.isPresent()) {
309 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
310 if (routerId != null) {
311 builder.setRouterId(null);
313 if (networkId != null) {
314 builder.setNetworkId(null);
317 builder.setVpnId(null);
319 if (portId != null && builder.getPortList() != null) {
320 List<Uuid> portList = builder.getPortList();
321 portList.remove(portId);
322 builder.setPortList(portList);
325 subnetmap = builder.build();
326 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
327 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
330 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
333 } catch (Exception e) {
334 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
339 // TODO Clean up the exception handling
340 @SuppressWarnings("checkstyle:IllegalCatch")
341 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
342 Subnetmap subnetmap = null;
343 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
344 new SubnetmapKey(subnetId)).build();
346 synchronized (subnetId.getValue().intern()) {
347 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
348 if (sn.isPresent()) {
349 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
350 if (null != portId && null != builder.getPortList()) {
351 List<Uuid> portList = builder.getPortList();
352 portList.remove(portId);
353 builder.setPortList(portList);
354 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
355 subnetId.getValue());
357 if (null != directPortId && null != builder.getDirectPortList()) {
358 List<Uuid> directPortList = builder.getDirectPortList();
359 directPortList.remove(directPortId);
360 builder.setDirectPortList(directPortList);
361 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
362 .getValue(), subnetId.getValue());
364 subnetmap = builder.build();
365 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
368 LOG.error("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
371 } catch (Exception e) {
372 LOG.error("Removing a port from port list of a subnetmap failed for node: {} with expection {}",
373 subnetId.getValue(), e);
378 // TODO Clean up the exception handling
379 @SuppressWarnings("checkstyle:IllegalCatch")
380 protected void deleteSubnetMapNode(Uuid subnetId) {
381 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
382 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
383 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
385 synchronized (subnetId.getValue().intern()) {
386 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
387 subnetMapIdentifier);
389 } catch (Exception e) {
390 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
394 // TODO Clean up the exception handling
395 @SuppressWarnings("checkstyle:IllegalCatch")
396 private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert,
397 VpnInstance.Type type, long l3vni) {
398 VpnInstanceBuilder builder = null;
399 List<VpnTarget> vpnTargetList = new ArrayList<>();
400 boolean isLockAcquired = false;
401 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
402 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
404 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
406 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
407 if (optionalVpn.isPresent()) {
408 builder = new VpnInstanceBuilder(optionalVpn.get());
409 LOG.debug("updating existing vpninstance node");
411 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
412 .setType(type).setL3vni(l3vni);
414 if (irt != null && !irt.isEmpty()) {
415 if (ert != null && !ert.isEmpty()) {
416 List<String> commonRT = new ArrayList<>(irt);
417 commonRT.retainAll(ert);
419 for (String common : commonRT) {
422 VpnTarget vpnTarget =
423 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
424 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
425 vpnTargetList.add(vpnTarget);
428 for (String importRT : irt) {
429 VpnTarget vpnTarget =
430 new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
431 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
432 vpnTargetList.add(vpnTarget);
436 if (ert != null && !ert.isEmpty()) {
437 for (String exportRT : ert) {
438 VpnTarget vpnTarget =
439 new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
440 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
441 vpnTargetList.add(vpnTarget);
445 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
447 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
449 if (rd != null && !rd.isEmpty()) {
450 ipv4vpnBuilder.setRouteDistinguisher(rd);
453 VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
454 isLockAcquired = NeutronvpnUtils.lock(vpnName);
455 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
456 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
457 } catch (Exception e) {
458 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
460 if (isLockAcquired) {
461 NeutronvpnUtils.unlock(vpnName);
466 // TODO Clean up the exception handling
467 @SuppressWarnings("checkstyle:IllegalCatch")
468 private void deleteVpnMapsNode(Uuid vpnid) {
469 boolean isLockAcquired = false;
470 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
471 .child(VpnMap.class, new VpnMapKey(vpnid))
473 LOG.debug("removing vpnMaps node: {} ", vpnid.getValue());
475 isLockAcquired = NeutronvpnUtils.lock(vpnid.getValue());
476 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
477 } catch (Exception e) {
478 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnid.getValue());
480 if (isLockAcquired) {
481 NeutronvpnUtils.unlock(vpnid.getValue());
486 // TODO Clean up the exception handling
487 @SuppressWarnings("checkstyle:IllegalCatch")
488 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
489 VpnMapBuilder builder;
490 boolean isLockAcquired = false;
491 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
492 .child(VpnMap.class, new VpnMapKey(vpnId))
495 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
497 if (optionalVpnMap.isPresent()) {
498 builder = new VpnMapBuilder(optionalVpnMap.get());
500 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
504 builder.setName(name);
506 if (tenantId != null) {
507 builder.setTenantId(tenantId);
509 if (router != null) {
510 builder.setRouterId(router);
512 if (networks != null) {
513 List<Uuid> nwList = builder.getNetworkIds();
514 if (nwList == null) {
515 nwList = new ArrayList<>();
517 nwList.addAll(networks);
518 builder.setNetworkIds(nwList);
521 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
522 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
523 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
524 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
525 } catch (Exception e) {
526 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
528 if (isLockAcquired) {
529 NeutronvpnUtils.unlock(vpnId.getValue());
534 // TODO Clean up the exception handling
535 @SuppressWarnings("checkstyle:IllegalCatch")
536 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
537 boolean isLockAcquired = false;
538 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
539 .child(VpnMap.class, new VpnMapKey(vpnId))
541 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
543 if (optionalVpnMap.isPresent()) {
544 VpnMap vpnMap = optionalVpnMap.get();
545 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
546 if (routerId != null) {
547 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
549 // remove entire node in case of internal VPN
550 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
551 LOG.debug("removing vpnMaps node: {} ", vpnId);
552 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
553 } catch (Exception e) {
554 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
556 if (isLockAcquired) {
557 NeutronvpnUtils.unlock(vpnId.getValue());
562 vpnMapBuilder.setRouterId(null);
564 if (networkIds != null) {
565 List<Uuid> vpnNw = vpnMap.getNetworkIds();
566 for (Uuid nw : networkIds) {
569 if (vpnNw.isEmpty()) {
570 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
571 vpnMapBuilder.setNetworkIds(null);
573 vpnMapBuilder.setNetworkIds(vpnNw);
578 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
579 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
580 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
581 vpnMapBuilder.build());
582 } catch (Exception e) {
583 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
585 if (isLockAcquired) {
586 NeutronvpnUtils.unlock(vpnId.getValue());
590 LOG.error("VPN : {} not found", vpnId.getValue());
592 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
595 // TODO Clean up the exception handling
596 @SuppressWarnings("checkstyle:IllegalCatch")
597 private void deleteVpnInstance(Uuid vpnId) {
598 boolean isLockAcquired = false;
599 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
600 .child(VpnInstance.class,
601 new VpnInstanceKey(vpnId.getValue()))
604 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
605 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
606 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
607 } catch (Exception e) {
608 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
610 if (isLockAcquired) {
611 NeutronvpnUtils.unlock(vpnId.getValue());
616 protected void createVpnInterface(Uuid vpnId, Uuid routerId, Port port,
617 WriteTransaction wrtConfigTxn) {
618 String infName = port.getUuid().getValue();
619 List<Adjacency> adjList = new ArrayList<>();
620 Boolean isRouterInterface = false;
621 if (port.getDeviceOwner() != null) {
622 isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
624 LOG.trace("createVpnInterface - isRouterInterface:{}", isRouterInterface);
626 if (routerId != null) {
627 rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
629 List<FixedIps> ips = port.getFixedIps();
630 // create adjacency list
631 for (FixedIps ip : ips) {
632 // create vm adjacency
633 String ipValue = String.valueOf(ip.getIpAddress().getValue());
634 String ipPrefix = (ip.getIpAddress().getIpv4Address() != null) ? ipValue + "/32" : ipValue + "/128";
635 Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
636 .setMacAddress(port.getMacAddress().getValue()).setPrimaryAdjacency(true)
637 .setSubnetId(ip.getSubnetId()).build();
639 // create extra route adjacency
640 if (rtr != null && rtr.getRoutes() != null) {
641 List<Routes> routeList = rtr.getRoutes();
642 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(vpnId, routeList, ipValue);
643 if (erAdjList != null && !erAdjList.isEmpty()) {
644 adjList.addAll(erAdjList);
647 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
648 .getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
650 // create vpn-interface on this neutron port
651 Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
652 writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
653 if (routerId != null) {
654 addToNeutronRouterInterfacesMap(routerId, infName);
658 // TODO Clean up the exception handling
659 @SuppressWarnings("checkstyle:IllegalCatch")
660 protected void deleteVpnInterface(Uuid vpnId, Uuid routerId, Port port, WriteTransaction wrtConfigTxn) {
661 Boolean wrtConfigTxnPresent = true;
662 if (wrtConfigTxn == null) {
663 wrtConfigTxnPresent = false;
664 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
666 String infName = port.getUuid().getValue();
667 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
669 LOG.debug("Deleting vpn interface {}", infName);
670 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
672 List<FixedIps> ips = port.getFixedIps();
673 for (FixedIps ip : ips) {
674 String ipValue = String.valueOf(ip.getIpAddress().getValue());
675 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(),
676 ipValue, wrtConfigTxn);
678 } catch (Exception ex) {
679 LOG.error("Deletion of vpninterface {} failed due to {}", infName, ex);
681 if (routerId != null) {
682 removeFromNeutronRouterInterfacesMap(routerId, infName);
684 if (!wrtConfigTxnPresent) {
685 wrtConfigTxn.submit();
689 // TODO Clean up the exception handling
690 @SuppressWarnings("checkstyle:IllegalCatch")
691 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
692 boolean isSubnetIp, WriteTransaction writeConfigTxn) {
693 if (vpnId == null || port == null) {
696 boolean isLockAcquired = false;
697 String infName = port.getUuid().getValue();
698 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
701 isLockAcquired = NeutronvpnUtils.lock(infName);
702 Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
703 .CONFIGURATION, vpnIfIdentifier);
704 if (optionalVpnInterface.isPresent()) {
705 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
706 .setVpnInstanceName(vpnId.getValue());
707 LOG.debug("Updating vpn interface {}", infName);
708 if (!isBeingAssociated) {
709 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
710 List<Adjacency> adjacencyList = (adjs != null) ? adjs.getAdjacency() : new ArrayList<>();
711 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
712 while (adjacencyIter.hasNext()) {
713 Adjacency adjacency = adjacencyIter.next();
714 String mipToQuery = adjacency.getIpAddress().split("/")[0];
715 InstanceIdentifier<LearntVpnVipToPort> id =
716 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
717 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
718 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
719 if (optionalVpnVipToPort.isPresent()) {
720 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
721 + "from VPN " + "{}", infName, vpnId, oldVpnId);
722 adjacencyIter.remove();
723 NeutronvpnUtils.removeLearntVpnVipToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
724 LOG.trace("Entry for fixedIP {} for port {} on VPN removed from "
725 + "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
728 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
729 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
731 List<FixedIps> ips = port.getFixedIps();
732 for (FixedIps ip : ips) {
733 String ipValue = String.valueOf(ip.getIpAddress().getValue());
734 if (oldVpnId != null) {
735 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(),
736 ipValue, writeConfigTxn);
738 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
739 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
741 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
744 LOG.error("VPN Interface {} not found", infName);
746 } catch (Exception ex) {
747 LOG.error("Updation of vpninterface {} failed due to {}", infName, ex);
749 if (isLockAcquired) {
750 NeutronvpnUtils.unlock(infName);
755 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
756 List<String> ert, Uuid router, List<Uuid> networks) {
758 // Update VPN Instance node
759 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/);
761 // Update local vpn-subnet DS
762 updateVpnMaps(vpn, name, router, tenant, networks);
764 if (router != null) {
765 Uuid existingVpn = NeutronvpnUtils.getVpnForRouter(dataBroker, router, true);
766 if (existingVpn != null) {
767 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
769 // if before reboot, router was already associated to VPN, should not proceed associating router to
770 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
771 // preserved upon reboot.
772 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
773 // RouterInterfacesMap via #createVPNInterface call.
774 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
775 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
778 associateRouterToInternalVpn(vpn, router);
783 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
784 * specified Neutron Networks and Routers.
786 * @param vpn Uuid of the VPN tp be created
787 * @param name Representative name of the new VPN
788 * @param tenant Uuid of the Tenant under which the VPN is going to be created
789 * @param rd Route-distinguisher for the VPN
790 * @param irt A list of Import Route Targets
791 * @param ert A list of Export Route Targets
792 * @param router UUID of the neutron router the VPN may be associated to
793 * @param networks UUID of the neutron network the VPN may be associated to
794 * @param type Type of the VPN Instance
795 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
796 * @throws Exception if association of L3VPN failed
798 public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
799 Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni) throws Exception {
801 // Update VPN Instance node
802 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, type, l3vni);
804 // Please note that router and networks will be filled into VPNMaps
805 // by subsequent calls here to associateRouterToVpn and
806 // associateNetworksToVpn
807 updateVpnMaps(vpn, name, null, tenant, null);
809 if (router != null) {
810 associateRouterToVpn(vpn, router);
812 if (networks != null) {
813 List<String> failStrings = associateNetworksToVpn(vpn, networks);
814 if (failStrings != null && !failStrings.isEmpty()) {
815 LOG.error("VPN {} association to networks failed with error message {}. ",
816 vpn.getValue(), failStrings.get(0));
817 throw new Exception(failStrings.get(0));
823 * It handles the invocations to the createVPN RPC method.
826 // TODO Clean up the exception handling
827 @SuppressWarnings("checkstyle:IllegalCatch")
828 public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
830 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
831 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
832 List<RpcError> errorList = new ArrayList<>();
833 int failurecount = 0;
834 int warningcount = 0;
836 List<L3vpn> vpns = input.getL3vpn();
837 for (L3vpn vpn : vpns) {
838 RpcError error = null;
840 if (NeutronvpnUtils.doesVpnExist(dataBroker, vpn.getId())) {
841 msg = String.format("Creation of L3VPN failed for VPN %s due to VPN with the same ID already present",
842 vpn.getId().getValue());
844 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
845 errorList.add(error);
849 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
850 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
851 vpn.getId().getValue());
853 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
854 errorList.add(error);
858 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
860 if (vpn.getL3vni() != null) {
861 l3vni = vpn.getL3vni();
864 if (vpn.getRouteDistinguisher().size() > 1) {
865 msg = String.format("Creation of VPN failed for VPN %s due to multiple RD input %s",
866 vpn.getId().getValue(), vpn.getRouteDistinguisher());
868 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
869 errorList.add(error);
873 List<String> existingRDs = NeutronvpnUtils.getExistingRDs(dataBroker);
874 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
875 msg = String.format("Creation of L3VPN failed for VPN %s as another VPN with the same RD %s "
876 + "is already configured",
877 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0));
879 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
880 errorList.add(error);
884 if (vpn.getRouterId() != null) {
885 if (NeutronvpnUtils.getNeutronRouter(dataBroker, vpn.getRouterId()) == null) {
886 msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
887 vpn.getId().getValue(), vpn.getRouterId().getValue());
889 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
890 errorList.add(error);
894 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, vpn.getRouterId(), true);
896 msg = String.format("Creation of L3VPN failed for VPN %s due to router %s already associated to "
897 + "another VPN %s", vpn.getId().getValue(), vpn.getRouterId().getValue(),
900 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
901 errorList.add(error);
906 if (vpn.getNetworkIds() != null) {
907 for (Uuid nw : vpn.getNetworkIds()) {
908 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
909 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
910 if (network == null) {
911 msg = String.format("Creation of L3VPN failed for VPN %s due to network not found %s",
912 vpn.getId().getValue(), nw.getValue());
914 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
915 errorList.add(error);
917 } else if (vpnId != null) {
918 msg = String.format("Creation of L3VPN failed for VPN %s due to network %s already associated"
919 + " to another VPN %s", vpn.getId().getValue(), nw.getValue(),
922 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
923 errorList.add(error);
932 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
933 vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
934 vpnInstanceType, l3vni);
935 } catch (Exception ex) {
936 msg = String.format("Creation of VPN failed for VPN %s", vpn.getId().getValue());
938 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
939 errorList.add(error);
943 // if at least one succeeds; result is success
944 // if none succeeds; result is failure
945 if (failurecount + warningcount == vpns.size()) {
946 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
948 List<String> errorResponseList = new ArrayList<>();
949 if (!errorList.isEmpty()) {
950 for (RpcError rpcError : errorList) {
951 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
952 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
953 errorResponseList.add(errorResponse);
956 errorResponseList.add("Operation successful with no errors");
958 opBuilder.setResponse(errorResponseList);
959 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
965 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
968 // TODO Clean up the exception handling
969 @SuppressWarnings("checkstyle:IllegalCatch")
970 public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
972 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
973 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
974 Uuid inputVpnId = input.getId();
975 List<VpnInstance> vpns = new ArrayList<>();
978 if (inputVpnId == null) {
980 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
982 Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
983 .CONFIGURATION, vpnsIdentifier);
984 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
985 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
986 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
987 // from getL3VPN output
988 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
994 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
998 String name = inputVpnId.getValue();
999 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1000 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1001 // read VpnInstance Info
1002 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1004 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1006 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1007 vpns.add(optionalVpn.get());
1009 String message = String.format("GetL3VPN failed because VPN %s is not present", name);
1011 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL,
1012 "invalid-value", message).build());
1015 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1016 for (VpnInstance vpnInstance : vpns) {
1017 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1018 // create VpnMaps id
1019 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1021 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1022 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1024 List<String> ertList = new ArrayList<>();
1025 List<String> irtList = new ArrayList<>();
1027 for (VpnTarget vpnTarget : vpnTargetList) {
1028 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1029 ertList.add(vpnTarget.getVrfRTValue());
1031 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1032 irtList.add(vpnTarget.getVrfRTValue());
1034 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1035 ertList.add(vpnTarget.getVrfRTValue());
1036 irtList.add(vpnTarget.getVrfRTValue());
1040 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1041 if (vpnInstance.getL3vni() != null) {
1042 l3vpn.setL3vni(vpnInstance.getL3vni());
1044 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1045 .class, new VpnMapKey(vpnId)).build();
1046 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1048 if (optionalVpnMap.isPresent()) {
1049 VpnMap vpnMap = optionalVpnMap.get();
1050 l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1051 .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1053 l3vpnList.add(l3vpn.build());
1056 opBuilder.setL3vpnInstances(l3vpnList);
1057 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1059 } catch (Exception ex) {
1060 String message = String.format("GetVPN failed due to %s", ex.getMessage());
1061 LOG.error(message, ex);
1062 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
1068 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1071 // TODO Clean up the exception handling
1072 @SuppressWarnings("checkstyle:IllegalCatch")
1073 public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1075 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1076 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1077 List<RpcError> errorList = new ArrayList<>();
1079 int failurecount = 0;
1080 int warningcount = 0;
1081 List<Uuid> vpns = input.getId();
1082 for (Uuid vpn : vpns) {
1086 InstanceIdentifier<VpnInstance> vpnIdentifier =
1087 InstanceIdentifier.builder(VpnInstances.class)
1088 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1089 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1090 .CONFIGURATION, vpnIdentifier);
1091 if (optionalVpn.isPresent()) {
1094 msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
1096 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
1097 errorList.add(error);
1100 } catch (Exception ex) {
1101 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
1103 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1104 errorList.add(error);
1108 // if at least one succeeds; result is success
1109 // if none succeeds; result is failure
1110 if (failurecount + warningcount == vpns.size()) {
1111 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1113 List<String> errorResponseList = new ArrayList<>();
1114 if (!errorList.isEmpty()) {
1115 for (RpcError rpcError : errorList) {
1116 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
1117 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
1118 errorResponseList.add(errorResponse);
1121 errorResponseList.add("Operation successful with no errors");
1123 opBuilder.setResponse(errorResponseList);
1124 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1129 public void createVpnInstanceForSubnet(Uuid subnetId) {
1130 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1131 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1134 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1135 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1136 removeVpn(subnetId);
1139 protected void addSubnetToVpn(final Uuid vpnId, Uuid subnet) {
1140 LOG.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
1141 Subnetmap sn = updateSubnetNode(subnet, null, vpnId);
1143 LOG.error("subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(), vpnId.getValue());
1146 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1147 if (vpnMap == null) {
1148 LOG.error("No vpnMap for vpnId {}, cannot add subnet {} to VPN", vpnId.getValue(), subnet.getValue());
1152 final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1153 // Check if there are ports on this subnet and add corresponding
1155 List<Uuid> portList = sn.getPortList();
1156 if (portList != null) {
1157 for (final Uuid portId : sn.getPortList()) {
1158 LOG.debug("adding vpn-interface for port {}", portId.getValue());
1159 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1160 portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1161 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1162 List<ListenableFuture<Void>> futures = new ArrayList<>();
1163 createVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
1165 futures.add(wrtConfigTxn.submit());
1172 private void updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1173 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1174 oldVpnId.getValue(), newVpnId.getValue());
1175 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId);
1177 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1181 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1182 if (sn.getRouterInterfacePortId() != null) {
1183 portDataStoreCoordinator.enqueueJob("PORT-" + sn.getRouterInterfacePortId().getValue(), () -> {
1184 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1185 List<ListenableFuture<Void>> futures = new ArrayList<>();
1186 updateVpnInterface(newVpnId, oldVpnId,
1187 NeutronvpnUtils.getNeutronPort(dataBroker, sn.getRouterInterfacePortId()),
1188 isBeingAssociated, true, wrtConfigTxn);
1189 futures.add(wrtConfigTxn.submit());
1194 // Check for ports on this subnet and update association of
1195 // corresponding vpn-interfaces to external vpn
1196 List<Uuid> portList = sn.getPortList();
1197 if (portList != null) {
1198 for (Uuid port : portList) {
1199 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1200 port.getValue(), isBeingAssociated);
1201 portDataStoreCoordinator.enqueueJob("PORT-" + port.getValue(), () -> {
1202 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1203 List<ListenableFuture<Void>> futures = new ArrayList<>();
1204 updateVpnInterface(newVpnId, oldVpnId, NeutronvpnUtils.getNeutronPort(dataBroker, port),
1205 isBeingAssociated, false, wrtConfigTxn);
1206 futures.add(wrtConfigTxn.submit());
1213 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1214 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1215 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1218 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1219 synchronized (routerId.getValue().intern()) {
1220 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1221 Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1222 .CONFIGURATION, routerInterfacesId);
1223 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1224 .setInterfaceId(interfaceName).build();
1225 if (optRouterInterfaces.isPresent()) {
1226 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1227 .class, new InterfacesKey(interfaceName)), routerInterface);
1229 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1230 List<Interfaces> interfaces = new ArrayList<>();
1231 interfaces.add(routerInterface);
1232 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1233 .class, new InterfacesKey(interfaceName)), routerInterface);
1238 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1239 synchronized (routerId.getValue().intern()) {
1240 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1241 Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1242 .CONFIGURATION, routerInterfacesId);
1243 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1244 .setInterfaceId(interfaceName).build();
1245 if (optRouterInterfaces.isPresent()) {
1246 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1247 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1248 if (interfaces != null && interfaces.remove(routerInterface)) {
1249 if (interfaces.isEmpty()) {
1250 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1252 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1253 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1261 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1262 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1263 * route will be ignored.
1265 * @param vpnName the VPN identifier
1266 * @param interVpnLinkRoutes The list of static routes
1267 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1269 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1270 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1271 for (Routes route : interVpnLinkRoutes) {
1272 String nexthop = String.valueOf(route.getNexthop().getValue());
1273 String destination = String.valueOf(route.getDestination().getValue());
1274 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1275 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1276 AddStaticRouteInput rpcInput =
1277 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1278 .setVpnInstanceName(vpnName.getValue())
1280 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1281 RpcResult<AddStaticRouteOutput> rpcResult;
1283 rpcResult = labelOuputFtr.get();
1284 if (rpcResult.isSuccessful()) {
1285 LOG.debug("Label generated for destination {} is: {}",
1286 destination, rpcResult.getResult().getLabel());
1288 LOG.warn("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1289 destination, nexthop, rpcResult.getErrors());
1291 } catch (InterruptedException | ExecutionException e) {
1292 LOG.warn("Error happened while invoking addStaticRoute RPC: ", e);
1295 // Any other case is a fault.
1296 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1297 String.valueOf(route.getDestination().getValue()), nexthop);
1304 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1305 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1307 * @param vpnName the VPN identifier
1308 * @param interVpnLinkRoutes The list of static routes
1309 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1311 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1312 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1313 for (Routes route : interVpnLinkRoutes) {
1314 String nexthop = String.valueOf(route.getNexthop().getValue());
1315 String destination = String.valueOf(route.getDestination().getValue());
1316 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1317 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1318 RemoveStaticRouteInput rpcInput =
1319 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1320 .setVpnInstanceName(vpnName.getValue())
1322 vpnRpcService.removeStaticRoute(rpcInput);
1324 // Any other case is a fault.
1325 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1326 String.valueOf(route.getDestination().getValue()), nexthop);
1333 * Returns true if the specified nexthop is the other endpoint in an
1334 * InterVpnLink, regarding one of the VPN's point of view.
1336 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1338 interVpnLink != null
1339 && ((interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1340 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop))
1341 || (interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1342 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)));
1345 protected List<Adjacency> getAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList, String fixedIp) {
1346 List<Adjacency> adjList = new ArrayList<>();
1347 Map<String, List<String>> adjMap = new HashMap<>();
1348 for (Routes route : routeList) {
1349 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1350 LOG.error("Incorrect input received for extra route. {}", route);
1352 String nextHop = String.valueOf(route.getNexthop().getValue());
1353 String destination = String.valueOf(route.getDestination().getValue());
1354 if (!nextHop.equals(fixedIp)) {
1355 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1358 LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} ", destination,
1359 vpnId.getValue(), nextHop);
1360 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1361 if (!hops.contains(nextHop)) {
1367 for (String destination : adjMap.keySet()) {
1368 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1369 .setNextHopIpList(adjMap.get(destination)).setKey(new AdjacencyKey(destination)).build();
1375 // TODO Clean up the exception handling
1376 @SuppressWarnings("checkstyle:IllegalCatch")
1377 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1378 for (Routes route : routeList) {
1379 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1380 LOG.error("Incorrect input received for extra route. {}", route);
1382 String nextHop = String.valueOf(route.getNexthop().getValue());
1383 String destination = String.valueOf(route.getDestination().getValue());
1384 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1386 if (infName != null) {
1387 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
1388 destination, vpnId.getValue(), nextHop, infName);
1389 boolean isLockAcquired = false;
1391 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
1392 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1393 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
1394 .child(Adjacency.class, new AdjacencyKey(destination));
1395 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1396 .setNextHopIpList(Collections.singletonList(nextHop)).setKey(new AdjacencyKey(destination))
1398 isLockAcquired = NeutronvpnUtils.lock(infName);
1399 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, erAdj);
1400 } catch (Exception e) {
1401 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
1402 destination, nextHop, e);
1404 if (isLockAcquired) {
1405 NeutronvpnUtils.unlock(infName);
1409 LOG.debug("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1410 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1416 // TODO Clean up the exception handling
1417 @SuppressWarnings("checkstyle:IllegalCatch")
1418 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
1419 for (Routes route : routeList) {
1420 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
1421 boolean isLockAcquired = false;
1422 String nextHop = String.valueOf(route.getNexthop().getValue());
1423 String destination = String.valueOf(route.getDestination().getValue());
1424 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1426 if (infName == null) {
1427 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
1428 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1429 // Proceed to remove the next extra-route
1432 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
1433 destination, vpnId.getValue(), nextHop, infName);
1435 InstanceIdentifier<Adjacency> adjacencyIdentifier =
1436 InstanceIdentifier.builder(VpnInterfaces.class)
1437 .child(VpnInterface.class, new VpnInterfaceKey(infName))
1438 .augmentation(Adjacencies.class)
1439 .child(Adjacency.class, new AdjacencyKey(destination))
1442 // Looking for existing prefix in MDSAL database
1443 Optional<Adjacency> adjacency = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1444 adjacencyIdentifier);
1445 boolean updateNextHops = false;
1446 List<String> nextHopList = new ArrayList<>();
1447 if (adjacency.isPresent()) {
1448 List<String> nhListRead = adjacency.get().getNextHopIpList();
1449 if (nhListRead.size() > 1) { // ECMP case
1450 for (String nextHopRead : nhListRead) {
1451 if (nextHopRead.equals(nextHop)) {
1452 updateNextHops = true;
1454 nextHopList.add(nextHopRead);
1461 isLockAcquired = NeutronvpnUtils.lock(infName);
1462 if (updateNextHops) {
1463 // An update must be done, not including the current next hop
1464 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
1465 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1466 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
1467 .setNextHopIpList(nextHopList)
1468 .setKey(new AdjacencyKey(destination))
1470 Adjacencies erAdjs =
1471 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
1472 VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
1473 .addAugmentation(Adjacencies.class, erAdjs).build();
1474 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
1476 // Remove the whole route
1477 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1478 LOG.trace("extra route {} deleted successfully", route);
1480 } catch (Exception e) {
1481 LOG.error("exception in deleting extra route: {}" + e);
1483 if (isLockAcquired) {
1484 NeutronvpnUtils.unlock(infName);
1488 LOG.error("Incorrect input received for extra route. {}", route);
1493 protected void removeVpn(Uuid id) {
1495 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, id);
1496 Uuid router = (vpnMap != null) ? vpnMap.getRouterId() : null;
1497 // dissociate router
1498 if (router != null) {
1499 dissociateRouterFromVpn(id, router);
1501 // dissociate networks
1502 if (!id.equals(router)) {
1503 dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
1505 // remove entire vpnMaps node
1506 deleteVpnMapsNode(id);
1508 // remove vpn-instance
1509 deleteVpnInstance(id);
1512 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet) {
1513 LOG.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
1514 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1515 if (vpnMap == null) {
1516 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1517 vpnId.getValue(), subnet.getValue());
1521 final Uuid routerId = vpnMap.getRouterId();
1522 Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1524 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1525 List<Uuid> portList = sn.getPortList();
1526 if (portList != null) {
1527 for (final Uuid portId : sn.getPortList()) {
1528 LOG.debug("removing vpn-interface for port {}", portId.getValue());
1529 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1530 portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1531 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1532 List<ListenableFuture<Void>> futures = new ArrayList<>();
1533 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1535 deleteVpnInterface(vpnId, routerId, port, wrtConfigTxn);
1537 LOG.error("Cannot proceed with deleteVpnInterface for port {} in subnet {} since port is "
1538 + "absent in Neutron config DS", portId.getValue(), subnet.getValue());
1540 futures.add(wrtConfigTxn.submit());
1545 // update subnet-vpn association
1546 removeFromSubnetNode(subnet, null, null, vpnId, null);
1548 LOG.warn("Subnetmap for subnet {} not found", subnet.getValue());
1552 // TODO Clean up the exception handling
1553 @SuppressWarnings("checkstyle:IllegalCatch")
1554 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
1555 updateVpnMaps(vpnId, null, routerId, null, null);
1556 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
1557 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1558 if (routerSubnets != null) {
1559 for (Uuid subnetId : routerSubnets) {
1560 updateVpnForSubnet(routerId, vpnId, subnetId, true);
1564 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
1565 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
1567 } catch (Exception e) {
1568 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
1569 .getValue(), vpnId.getValue(), e);
1573 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
1574 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1575 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
1576 for (Uuid subnet : routerSubnets) {
1577 addSubnetToVpn(vpnId, subnet);
1581 // TODO Clean up the exception handling
1582 @SuppressWarnings("checkstyle:IllegalCatch")
1583 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
1585 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1586 if (routerSubnets != null) {
1587 for (Uuid subnetId : routerSubnets) {
1588 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
1589 updateVpnForSubnet(vpnId, routerId, subnetId, false);
1592 clearFromVpnMaps(vpnId, routerId, null);
1594 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
1595 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
1597 } catch (Exception e) {
1598 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
1599 .getValue(), vpnId.getValue(), e);
1603 protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
1604 List<String> failedNwList = new ArrayList<>();
1605 List<Uuid> passedNwList = new ArrayList<>();
1606 if (!networks.isEmpty()) {
1607 // process corresponding subnets for VPN
1608 for (Uuid nw : networks) {
1609 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1610 NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
1611 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
1612 LOG.error("MultiSegmented networks not supported in VPN. Failed to associate network {} on vpn {}",
1613 nw.getValue(), vpn.getValue());
1614 failedNwList.add(String.format("Failed to associate network %s on vpn %s as it is multisegmented.",
1615 nw.getValue(), vpn.getValue()));
1618 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1619 if (network == null) {
1620 failedNwList.add(String.format("network %s not found", nw.getValue()));
1621 } else if (vpnId != null) {
1622 failedNwList.add(String.format("network %s already associated to another VPN %s", nw.getValue(),
1625 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1626 LOG.debug("Adding network subnets...{}", networkSubnets);
1627 if (networkSubnets != null) {
1628 for (Uuid subnet : networkSubnets) {
1629 // check if subnet added as router interface to some router
1630 Uuid subnetVpnId = NeutronvpnUtils.getVpnForSubnet(dataBroker, subnet);
1631 if (subnetVpnId == null) {
1632 addSubnetToVpn(vpn, subnet);
1633 passedNwList.add(nw);
1635 failedNwList.add(String.format("subnet %s already added as router interface bound to "
1636 + "internal/external VPN %s", subnet.getValue(), subnetVpnId.getValue()));
1640 if (NeutronvpnUtils.getIsExternal(network)) {
1641 nvpnNatManager.addExternalNetworkToVpn(network, vpn);
1645 updateVpnMaps(vpn, null, null, null, passedNwList);
1647 return failedNwList;
1650 protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
1651 List<String> failedNwList = new ArrayList<>();
1652 List<Uuid> passedNwList = new ArrayList<>();
1653 if (networks != null && !networks.isEmpty()) {
1654 // process corresponding subnets for VPN
1655 for (Uuid nw : networks) {
1656 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1657 if (network == null) {
1658 failedNwList.add(String.format("network %s not found", nw.getValue()));
1660 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1661 if (vpn.equals(vpnId)) {
1662 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1663 LOG.debug("Removing network subnets...");
1664 if (networkSubnets != null) {
1665 for (Uuid subnet : networkSubnets) {
1666 removeSubnetFromVpn(vpn, subnet);
1667 passedNwList.add(nw);
1671 if (vpnId == null) {
1672 failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
1675 failedNwList.add(String.format("input network %s associated to a another vpn %s instead "
1676 + "of the one given as input", nw.getValue(), vpnId.getValue()));
1679 if (NeutronvpnUtils.getIsExternal(network)) {
1680 nvpnNatManager.removeExternalNetworkFromVpn(network);
1684 clearFromVpnMaps(vpn, null, passedNwList);
1686 return failedNwList;
1690 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
1693 // TODO Clean up the exception handling
1694 @SuppressWarnings("checkstyle:IllegalCatch")
1695 public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1697 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
1698 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
1699 LOG.debug("associateNetworks {}", input);
1700 StringBuilder returnMsg = new StringBuilder();
1701 Uuid vpnId = input.getVpnId();
1704 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1705 List<Uuid> netIds = input.getNetworkId();
1706 if (netIds != null && !netIds.isEmpty()) {
1707 List<String> failed = associateNetworksToVpn(vpnId, netIds);
1708 if (!failed.isEmpty()) {
1709 returnMsg.append(failed);
1713 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1715 if (returnMsg.length() != 0) {
1716 String message = String.format("associate Networks to vpn %s failed due to %s",
1717 vpnId.getValue(), returnMsg);
1719 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
1721 opBuilder.setResponse(errorResponse);
1722 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
1724 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
1726 } catch (Exception ex) {
1727 String message = String.format("associate Networks to vpn %s failed due to %s",
1728 input.getVpnId().getValue(), ex.getMessage());
1729 LOG.error(message, ex);
1730 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1733 LOG.debug("associateNetworks returns..");
1738 * It handles the invocations to the neutronvpn:associateRouter RPC method.
1741 // TODO Clean up the exception handling
1742 @SuppressWarnings("checkstyle:IllegalCatch")
1743 public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1745 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1746 LOG.debug("associateRouter {}", input);
1747 StringBuilder returnMsg = new StringBuilder();
1748 Uuid vpnId = input.getVpnId();
1749 Uuid routerId = input.getRouterId();
1751 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1752 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1753 if (vpnMap != null) {
1755 Uuid extVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1756 if (vpnMap.getRouterId() != null) {
1757 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
1758 .append(vpnMap.getRouterId().getValue());
1759 } else if (extVpnId != null) {
1760 returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
1761 + "another VPN ").append(extVpnId.getValue());
1763 associateRouterToVpn(vpnId, routerId);
1766 returnMsg.append("router not found : ").append(routerId.getValue());
1769 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1771 if (returnMsg.length() != 0) {
1772 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1775 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1778 result.set(RpcResultBuilder.<Void>success().build());
1780 } catch (Exception ex) {
1781 String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
1782 vpnId.getValue(), ex.getMessage());
1783 LOG.error(message, ex);
1784 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1786 LOG.debug("associateRouter returns..");
1790 /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
1793 // TODO Clean up the exception handling
1794 @SuppressWarnings("checkstyle:IllegalCatch")
1795 public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
1796 GetFixedIPsForNeutronPortInput input) {
1797 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
1798 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
1799 Uuid portId = input.getPortId();
1800 StringBuilder returnMsg = new StringBuilder();
1802 List<String> fixedIPList = new ArrayList<>();
1803 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1805 List<FixedIps> fixedIPs = port.getFixedIps();
1806 for (FixedIps ip : fixedIPs) {
1807 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
1810 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
1812 if (returnMsg.length() != 0) {
1813 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
1815 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1816 .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
1818 opBuilder.setFixedIPs(fixedIPList);
1819 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
1821 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
1823 } catch (Exception ex) {
1824 String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s",
1825 portId.getValue(), ex.getMessage());
1826 LOG.error(message, ex);
1827 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1828 .withError(ErrorType.APPLICATION, message).build());
1834 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
1837 // TODO Clean up the exception handling
1838 @SuppressWarnings("checkstyle:IllegalCatch")
1839 public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
1841 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
1842 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
1844 LOG.debug("dissociateNetworks {}", input);
1845 StringBuilder returnMsg = new StringBuilder();
1846 Uuid vpnId = input.getVpnId();
1849 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1850 List<Uuid> netIds = input.getNetworkId();
1851 if (netIds != null && !netIds.isEmpty()) {
1852 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
1853 if (!failed.isEmpty()) {
1854 returnMsg.append(failed);
1858 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1860 if (returnMsg.length() != 0) {
1861 String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
1864 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1866 opBuilder.setResponse(errorResponse);
1867 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
1869 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
1871 } catch (Exception ex) {
1872 String message = String.format("dissociate Networks to vpn %s failed due to %s",
1873 input.getVpnId().getValue(), ex.getMessage());
1874 LOG.error(message, ex);
1875 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1878 LOG.debug("dissociateNetworks returns..");
1883 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
1886 // TODO Clean up the exception handling
1887 @SuppressWarnings("checkstyle:IllegalCatch")
1888 public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
1890 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1892 LOG.debug("dissociateRouter {}", input);
1893 StringBuilder returnMsg = new StringBuilder();
1894 Uuid vpnId = input.getVpnId();
1895 Uuid routerId = input.getRouterId();
1897 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1898 if (routerId != null) {
1899 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1901 Uuid routerVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1902 if (vpnId.equals(routerVpnId)) {
1903 dissociateRouterFromVpn(vpnId, routerId);
1905 if (routerVpnId == null) {
1906 returnMsg.append("input router ").append(routerId.getValue())
1907 .append(" not associated to any vpn yet");
1909 returnMsg.append("input router ").append(routerId.getValue())
1910 .append(" associated to vpn ")
1911 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
1915 returnMsg.append("router not found : ").append(routerId.getValue());
1919 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1921 if (returnMsg.length() != 0) {
1922 String message = String.format("dissociate router %s to vpn %s failed due to %s", routerId.getValue(),
1923 vpnId.getValue(), returnMsg);
1925 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1927 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1930 result.set(RpcResultBuilder.<Void>success().build());
1932 } catch (Exception ex) {
1933 String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
1934 vpnId.getValue(), ex.getMessage());
1935 LOG.error(message, ex);
1936 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1938 LOG.debug("dissociateRouter returns..");
1943 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
1944 // check if the router is associated to some VPN
1945 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1946 if (vpnId != null) {
1947 // remove existing external vpn interfaces
1948 for (Uuid subnetId : routerSubnetIds) {
1949 removeSubnetFromVpn(vpnId, subnetId);
1951 clearFromVpnMaps(vpnId, routerId, null);
1953 // remove existing internal vpn interfaces
1954 for (Uuid subnetId : routerSubnetIds) {
1955 removeSubnetFromVpn(routerId, subnetId);
1958 // delete entire vpnMaps node for internal VPN
1959 deleteVpnMapsNode(routerId);
1961 // delete vpn-instance for internal VPN
1962 deleteVpnInstance(routerId);
1965 protected Subnet getNeutronSubnet(Uuid subnetId) {
1966 return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1969 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
1970 Subnet sn = NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1972 return sn.getGatewayIp();
1978 protected Network getNeutronNetwork(Uuid networkId) {
1979 return NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
1982 protected Port getNeutronPort(String name) {
1983 return NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(name));
1986 protected Port getNeutronPort(Uuid portId) {
1987 return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1990 protected Uuid getNetworkForSubnet(Uuid subnetId) {
1991 return NeutronvpnUtils.getNetworkForSubnet(dataBroker, subnetId);
1994 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
1995 return NeutronvpnUtils.getNetworksforVpn(dataBroker, vpnId);
1999 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2001 * @return a List of String to be printed on screen
2003 // TODO Clean up the exception handling and the console output
2004 @SuppressWarnings({"checkstyle:IllegalCatch", "checkstyle:RegexpSinglelineJava"})
2005 public List<String> showNeutronPortsCLI() {
2006 List<String> result = new ArrayList<>();
2007 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
2009 result.add("-------------------------------------------------------------------------------------------");
2010 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2012 Optional<Ports> ports =
2013 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
2014 if (ports.isPresent() && ports.get().getPort() != null) {
2015 for (Port port : ports.get().getPort()) {
2016 List<FixedIps> fixedIPs = port.getFixedIps();
2018 if (fixedIPs != null && !fixedIPs.isEmpty()) {
2019 List<String> ipList = new ArrayList<>();
2020 for (FixedIps fixedIp : fixedIPs) {
2021 IpAddress ipAddress = fixedIp.getIpAddress();
2022 if (ipAddress.getIpv4Address() != null) {
2023 ipList.add(ipAddress.getIpv4Address().getValue());
2025 ipList.add((ipAddress.getIpv6Address().getValue()));
2028 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2029 .getMacAddress().getValue(), NeutronvpnUtils.getIPPrefixFromPort(dataBroker, port),
2030 ipList.toString()));
2032 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2033 .getMacAddress().getValue(), "Not Assigned", "Not " + "Assigned"));
2035 } catch (Exception e) {
2036 LOG.error("Failed to retrieve neutronPorts info for port {}: ", port.getUuid().getValue(),
2038 System.out.println("Failed to retrieve neutronPorts info for port: " + port.getUuid()
2039 .getValue() + ": " + e.getMessage());
2043 } catch (Exception e) {
2044 LOG.error("Failed to retrieve neutronPorts info : ", e);
2045 System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
2051 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2053 * @param vpnuuid Uuid of the VPN whose config must be shown
2054 * @return formatted output list
2056 @SuppressWarnings("checkstyle:RegexpSinglelineJava")
2057 public List<String> showVpnConfigCLI(Uuid vpnuuid) {
2058 List<String> result = new ArrayList<>();
2059 if (vpnuuid == null) {
2060 System.out.println("");
2061 System.out.println("Displaying VPN config for all VPNs");
2062 System.out.println("To display VPN config for a particular VPN, use the following syntax");
2063 System.out.println(getshowVpnConfigCLIHelp());
2066 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2067 if (rpcResult.isSuccessful()) {
2069 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2071 result.add(String.format(" %-80s ", "Import-RTs"));
2073 result.add(String.format(" %-80s ", "Export-RTs"));
2075 result.add(String.format(" %-76s ", "Subnet IDs"));
2077 result.add("------------------------------------------------------------------------------------");
2079 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2080 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2081 .rev150602.VpnInstance vpn : vpnList) {
2082 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2084 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2085 vpn.getRouteDistinguisher()));
2087 result.add(String.format(" %-80s ", vpn.getImportRT()));
2089 result.add(String.format(" %-80s ", vpn.getExportRT()));
2092 Uuid vpnid = vpn.getId();
2093 List<Uuid> subnetList = NeutronvpnUtils.getSubnetsforVpn(dataBroker, vpnid);
2094 if (!subnetList.isEmpty()) {
2095 for (Uuid subnetuuid : subnetList) {
2096 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2099 result.add(String.format(" %-76s ", "\" \""));
2102 result.add("----------------------------------------");
2106 String errortag = rpcResult.getErrors().iterator().next().getTag();
2107 if (Objects.equals(errortag, "")) {
2108 System.out.println("");
2109 System.out.println("No VPN has been configured yet");
2110 } else if (Objects.equals(errortag, "invalid-value")) {
2111 System.out.println("");
2112 System.out.println("VPN " + vpnuuid.getValue() + " is not present");
2114 System.out.println("error getting VPN info : " + rpcResult.getErrors());
2115 System.out.println(getshowVpnConfigCLIHelp());
2118 } catch (InterruptedException | ExecutionException e) {
2119 LOG.error("error getting VPN info : ", e);
2120 System.out.println("error getting VPN info : " + e.getMessage());
2125 protected void createExternalVpnInterfaces(Uuid extNetId) {
2126 if (extNetId == null) {
2127 LOG.trace("external network is null");
2131 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2132 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2133 LOG.trace("No external ports attached to external network {}", extNetId.getValue());
2137 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2138 for (String elanInterface : extElanInterfaces) {
2139 createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
2141 wrtConfigTxn.submit();
2144 // TODO Clean up the exception handling
2145 @SuppressWarnings("checkstyle:IllegalCatch")
2146 protected void removeExternalVpnInterfaces(Uuid extNetId) {
2147 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2148 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2149 LOG.trace("No external ports attached for external network {}", extNetId);
2154 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2155 for (String elanInterface : extElanInterfaces) {
2156 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2157 .buildVpnInterfaceIdentifier(elanInterface);
2158 LOG.info("Removing vpn interface {}", elanInterface);
2159 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2161 wrtConfigTxn.submit();
2163 } catch (Exception ex) {
2164 LOG.error("Removal of vpninterfaces {} failed due to {}", extElanInterfaces, ex);
2168 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2169 writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, wrtConfigTxn);
2172 // TODO Clean up the exception handling
2173 @SuppressWarnings("checkstyle:IllegalCatch")
2174 private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
2175 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2176 if (vpnId == null || infName == null) {
2177 LOG.debug("vpn id or interface is null");
2181 Boolean wrtConfigTxnPresent = true;
2182 if (wrtConfigTxn == null) {
2183 wrtConfigTxnPresent = false;
2184 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2187 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2188 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2190 .setVpnInstanceName(vpnId.getValue())
2191 .setIsRouterInterface(isRouterInterface);
2192 if (adjacencies != null) {
2193 vpnb.addAugmentation(Adjacencies.class, adjacencies);
2195 VpnInterface vpnIf = vpnb.build();
2197 LOG.info("Creating vpn interface {}", vpnIf);
2198 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2199 } catch (Exception ex) {
2200 LOG.error("Creation of vpninterface {} failed due to {}", infName, ex);
2203 if (!wrtConfigTxnPresent) {
2204 wrtConfigTxn.submit();
2208 private String getshowVpnConfigCLIHelp() {
2209 StringBuilder help = new StringBuilder("Usage:");
2210 help.append("display vpn-config [-vid/--vpnid <id>]");
2211 return help.toString();
2214 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
2215 InterruptedException {
2216 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
2217 .setVpnId(vpnId).build();
2218 LOG.info("publishing notification upon association of router to VPN");
2219 notificationPublishService.putNotification(routerAssociatedToVpn);
2222 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
2223 InterruptedException {
2224 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
2225 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
2226 LOG.info("publishing notification upon disassociation of router from VPN");
2227 notificationPublishService.putNotification(routerDisassociatedFromVpn);
2230 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
2231 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);