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.Arrays;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.EventListener;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
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.mdsalutil.MDSALUtil;
30 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
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 NeutronvpnConfig neutronvpnConfig;
132 private final IMdsalApiManager mdsalUtil;
133 private final IElanService elanService;
135 public NeutronvpnManager(
136 final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
137 final NotificationPublishService notiPublishService, final NeutronvpnNatManager vpnNatMgr,
138 final VpnRpcService vpnRpcSrv, final IElanService elanService,
139 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
140 final NeutronvpnConfig neutronvpnConfig) {
141 this.dataBroker = dataBroker;
142 mdsalUtil = mdsalManager;
143 nvpnNatManager = vpnNatMgr;
144 notificationPublishService = notiPublishService;
145 vpnRpcService = vpnRpcSrv;
146 this.elanService = elanService;
147 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
148 LOG.info("neutronvpnConfig: {}", neutronvpnConfig);
149 this.neutronvpnConfig = neutronvpnConfig;
153 public void close() throws Exception {
154 LOG.info("{} close", getClass().getSimpleName());
157 public NeutronvpnConfig getNeutronvpnConfig() {
158 return neutronvpnConfig;
161 // TODO Clean up the exception handling
162 @SuppressWarnings("checkstyle:IllegalCatch")
163 protected void updateSubnetNodeWithFixedIps(Uuid subnetId, Uuid routerId,
164 Uuid routerInterfaceName, String fixedIp,
165 String routerIntfMacAddress) {
166 Subnetmap subnetmap = null;
167 SubnetmapBuilder builder = null;
168 InstanceIdentifier<Subnetmap> id =
169 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
171 synchronized (subnetId.getValue().intern()) {
172 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
173 if (sn.isPresent()) {
174 builder = new SubnetmapBuilder(sn.get());
175 LOG.debug("WithRouterFixedIPs: Updating existing subnetmap node for subnet ID {}",
176 subnetId.getValue());
178 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
179 LOG.debug("WithRouterFixedIPs: creating new subnetmap node for subnet ID {}",
180 subnetId.getValue());
182 builder.setRouterId(routerId);
183 builder.setRouterInterfaceName(routerInterfaceName);
184 builder.setRouterIntfMacAddress(routerIntfMacAddress);
185 if (fixedIp != null) {
186 List<String> fixedIps = builder.getRouterInterfaceFixedIps();
187 if (fixedIps == null) {
188 fixedIps = new ArrayList<>();
190 fixedIps.add(fixedIp);
191 builder.setRouterInterfaceFixedIps(fixedIps);
193 builder.setRouterInterfaceFixedIps(null);
195 subnetmap = builder.build();
196 LOG.debug("WithRouterFixedIPs Creating/Updating subnetMap node for Router FixedIps: {} ",
197 subnetId.getValue());
198 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
200 } catch (Exception e) {
201 LOG.error("WithRouterFixedIPs: Updation of subnetMap for Router FixedIps failed for node: {}",
202 subnetId.getValue());
206 // TODO Clean up the exception handling
207 @SuppressWarnings("checkstyle:IllegalCatch")
208 protected Subnetmap updateSubnetNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId, Uuid routerId,
210 Subnetmap subnetmap = null;
211 SubnetmapBuilder builder = null;
212 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
213 .child(Subnetmap.class, new SubnetmapKey(subnetId))
216 synchronized (subnetId.getValue().intern()) {
217 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
218 if (sn.isPresent()) {
219 builder = new SubnetmapBuilder(sn.get());
220 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
222 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
223 LOG.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
226 if (subnetIp != null) {
227 builder.setSubnetIp(subnetIp);
229 if (routerId != null) {
230 builder.setRouterId(routerId);
232 if (networkId != null) {
233 builder.setNetworkId(networkId);
236 builder.setVpnId(vpnId);
238 if (tenantId != null) {
239 builder.setTenantId(tenantId);
242 subnetmap = builder.build();
243 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
244 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
246 } catch (Exception e) {
247 LOG.error("Updation of subnetMap failed for node: {}", subnetId.getValue());
252 // TODO Clean up the exception handling
253 @SuppressWarnings("checkstyle:IllegalCatch")
254 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
255 Subnetmap subnetmap = null;
256 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
257 .child(Subnetmap.class, new SubnetmapKey(subnetId))
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 (routerId != null) {
265 builder.setRouterId(null);
267 if (networkId != null) {
268 builder.setNetworkId(null);
271 builder.setVpnId(null);
273 if (portId != null && builder.getPortList() != null) {
274 List<Uuid> portList = builder.getPortList();
275 portList.remove(portId);
276 builder.setPortList(portList);
279 subnetmap = builder.build();
280 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
281 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
283 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
286 } catch (Exception e) {
287 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
292 // TODO Clean up the exception handling
293 @SuppressWarnings("checkstyle:IllegalCatch")
294 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
295 Subnetmap subnetmap = null;
296 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
297 new SubnetmapKey(subnetId)).build();
299 synchronized (subnetId.getValue().intern()) {
300 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
301 if (sn.isPresent()) {
302 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
303 if (null != portId) {
304 List<Uuid> portList = builder.getPortList();
305 if (null == portList) {
306 portList = new ArrayList<>();
308 portList.add(portId);
309 builder.setPortList(portList);
310 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
313 if (null != directPortId) {
314 List<Uuid> directPortList = builder.getDirectPortList();
315 if (null == directPortList) {
316 directPortList = new ArrayList<>();
318 directPortList.add(directPortId);
319 builder.setDirectPortList(directPortList);
320 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
321 directPortId.getValue());
323 subnetmap = builder.build();
324 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
326 LOG.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
329 } catch (Exception e) {
330 LOG.error("Updating port list of a given subnetMap failed for node: {} with exception{}",
331 subnetId.getValue(), e);
336 // TODO Clean up the exception handling
337 @SuppressWarnings("checkstyle:IllegalCatch")
338 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
339 Subnetmap subnetmap = null;
340 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
341 new SubnetmapKey(subnetId)).build();
343 synchronized (subnetId.getValue().intern()) {
344 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
345 if (sn.isPresent()) {
346 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
347 if (null != portId && null != builder.getPortList()) {
348 List<Uuid> portList = builder.getPortList();
349 portList.remove(portId);
350 builder.setPortList(portList);
351 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
352 subnetId.getValue());
354 if (null != directPortId && null != builder.getDirectPortList()) {
355 List<Uuid> directPortList = builder.getDirectPortList();
356 directPortList.remove(directPortId);
357 builder.setDirectPortList(directPortList);
358 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
359 .getValue(), subnetId.getValue());
361 subnetmap = builder.build();
362 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
364 LOG.error("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
367 } catch (Exception e) {
368 LOG.error("Removing a port from port list of a subnetmap failed for node: {} with expection {}",
369 subnetId.getValue(), e);
374 // TODO Clean up the exception handling
375 @SuppressWarnings("checkstyle:IllegalCatch")
376 protected void deleteSubnetMapNode(Uuid subnetId) {
377 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
378 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
379 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
381 synchronized (subnetId.getValue().intern()) {
382 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
384 } catch (Exception e) {
385 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
389 // TODO Clean up the exception handling
390 @SuppressWarnings("checkstyle:IllegalCatch")
391 private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert,
392 VpnInstance.Type type, long l3vni) {
394 VpnInstanceBuilder builder = null;
395 List<VpnTarget> vpnTargetList = new ArrayList<>();
396 boolean isLockAcquired = false;
397 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
398 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
400 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
402 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
403 if (optionalVpn.isPresent()) {
404 builder = new VpnInstanceBuilder(optionalVpn.get());
405 LOG.debug("updating existing vpninstance node");
407 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
408 .setType(type).setL3vni(l3vni);
410 if (irt != null && !irt.isEmpty()) {
411 if (ert != null && !ert.isEmpty()) {
412 List<String> commonRT = new ArrayList<>(irt);
413 commonRT.retainAll(ert);
415 for (String common : commonRT) {
418 VpnTarget vpnTarget =
419 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
420 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
421 vpnTargetList.add(vpnTarget);
424 for (String importRT : irt) {
425 VpnTarget vpnTarget =
426 new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
427 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
428 vpnTargetList.add(vpnTarget);
432 if (ert != null && !ert.isEmpty()) {
433 for (String exportRT : ert) {
434 VpnTarget vpnTarget =
435 new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
436 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
437 vpnTargetList.add(vpnTarget);
441 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
443 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
445 if (rd != null && !rd.isEmpty()) {
446 ipv4vpnBuilder.setRouteDistinguisher(rd.get(0));
449 VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
450 isLockAcquired = NeutronvpnUtils.lock(vpnName);
451 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
452 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
453 } catch (Exception e) {
454 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
456 if (isLockAcquired) {
457 NeutronvpnUtils.unlock(vpnName);
462 // TODO Clean up the exception handling
463 @SuppressWarnings("checkstyle:IllegalCatch")
464 private void deleteVpnMapsNode(Uuid vpnid) {
465 boolean isLockAcquired = false;
466 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
467 .child(VpnMap.class, new VpnMapKey(vpnid))
469 LOG.debug("removing vpnMaps node: {} ", vpnid.getValue());
471 isLockAcquired = NeutronvpnUtils.lock(vpnid.getValue());
472 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
473 } catch (Exception e) {
474 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnid.getValue());
476 if (isLockAcquired) {
477 NeutronvpnUtils.unlock(vpnid.getValue());
482 // TODO Clean up the exception handling
483 @SuppressWarnings("checkstyle:IllegalCatch")
484 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
485 VpnMapBuilder builder;
486 boolean isLockAcquired = false;
487 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
488 .child(VpnMap.class, new VpnMapKey(vpnId))
491 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
493 if (optionalVpnMap.isPresent()) {
494 builder = new VpnMapBuilder(optionalVpnMap.get());
496 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
500 builder.setName(name);
502 if (tenantId != null) {
503 builder.setTenantId(tenantId);
505 if (router != null) {
506 builder.setRouterId(router);
508 if (networks != null) {
509 List<Uuid> nwList = builder.getNetworkIds();
510 if (nwList == null) {
511 nwList = new ArrayList<>();
513 nwList.addAll(networks);
514 builder.setNetworkIds(nwList);
517 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
518 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
519 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
520 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
521 } catch (Exception e) {
522 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
524 if (isLockAcquired) {
525 NeutronvpnUtils.unlock(vpnId.getValue());
530 // TODO Clean up the exception handling
531 @SuppressWarnings("checkstyle:IllegalCatch")
532 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
533 boolean isLockAcquired = false;
534 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
535 .child(VpnMap.class, new VpnMapKey(vpnId))
537 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
539 if (optionalVpnMap.isPresent()) {
540 VpnMap vpnMap = optionalVpnMap.get();
541 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
542 if (routerId != null) {
543 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
545 // remove entire node in case of internal VPN
546 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
547 LOG.debug("removing vpnMaps node: {} ", vpnId);
548 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
549 } catch (Exception e) {
550 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
552 if (isLockAcquired) {
553 NeutronvpnUtils.unlock(vpnId.getValue());
558 vpnMapBuilder.setRouterId(null);
560 if (networkIds != null) {
561 List<Uuid> vpnNw = vpnMap.getNetworkIds();
562 for (Uuid nw : networkIds) {
565 if (vpnNw.isEmpty()) {
566 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
567 vpnMapBuilder.setNetworkIds(null);
569 vpnMapBuilder.setNetworkIds(vpnNw);
574 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
575 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
576 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
577 vpnMapBuilder.build());
578 } catch (Exception e) {
579 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
581 if (isLockAcquired) {
582 NeutronvpnUtils.unlock(vpnId.getValue());
586 LOG.error("VPN : {} not found", vpnId.getValue());
588 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
591 // TODO Clean up the exception handling
592 @SuppressWarnings("checkstyle:IllegalCatch")
593 private void deleteVpnInstance(Uuid vpnId) {
594 boolean isLockAcquired = false;
595 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
596 .child(VpnInstance.class,
597 new VpnInstanceKey(vpnId.getValue()))
600 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
601 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
602 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
603 } catch (Exception e) {
604 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
606 if (isLockAcquired) {
607 NeutronvpnUtils.unlock(vpnId.getValue());
612 protected void createVpnInterface(Uuid vpnId, Uuid routerId, Port port,
613 WriteTransaction wrtConfigTxn) {
614 String infName = port.getUuid().getValue();
615 List<Adjacency> adjList = new ArrayList<>();
616 Boolean isRouterInterface = false;
617 if (port.getDeviceOwner() != null) {
618 isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
620 LOG.trace("createVpnInterface - isRouterInterface:{}", isRouterInterface);
622 if (routerId != null) {
623 rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
625 List<FixedIps> ips = port.getFixedIps();
626 // create adjacency list
627 for (FixedIps ip : ips) {
628 // create vm adjacency
629 String ipValue = String.valueOf(ip.getIpAddress().getValue());
630 String ipPrefix = (ip.getIpAddress().getIpv4Address() != null) ? ipValue + "/32" : ipValue + "/128";
631 Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
632 .setMacAddress(port.getMacAddress().getValue()).setPrimaryAdjacency(true)
633 .setSubnetId(ip.getSubnetId()).build();
635 // create extra route adjacency
636 if (rtr != null && rtr.getRoutes() != null) {
637 List<Routes> routeList = rtr.getRoutes();
638 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(vpnId, routeList, ipValue);
639 if (erAdjList != null && !erAdjList.isEmpty()) {
640 adjList.addAll(erAdjList);
643 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
644 .getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
646 // create vpn-interface on this neutron port
647 Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
648 writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
649 if (routerId != null) {
650 addToNeutronRouterInterfacesMap(routerId, infName);
654 // TODO Clean up the exception handling
655 @SuppressWarnings("checkstyle:IllegalCatch")
656 protected void deleteVpnInterface(Uuid vpnId, Uuid routerId, Port port, WriteTransaction wrtConfigTxn) {
657 Boolean wrtConfigTxnPresent = true;
658 if (wrtConfigTxn == null) {
659 wrtConfigTxnPresent = false;
660 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
662 String infName = port.getUuid().getValue();
663 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
665 LOG.debug("Deleting vpn interface {}", infName);
666 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
668 List<FixedIps> ips = port.getFixedIps();
669 for (FixedIps ip : ips) {
670 String ipValue = String.valueOf(ip.getIpAddress().getValue());
671 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(),
672 ipValue, wrtConfigTxn);
674 } catch (Exception ex) {
675 LOG.error("Deletion of vpninterface {} failed due to {}", infName, ex);
677 if (routerId != null) {
678 removeFromNeutronRouterInterfacesMap(routerId, infName);
680 if (!wrtConfigTxnPresent) {
681 wrtConfigTxn.submit();
685 // TODO Clean up the exception handling
686 @SuppressWarnings("checkstyle:IllegalCatch")
687 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
688 boolean isSubnetIp) {
689 if (vpnId == null || port == null) {
692 boolean isLockAcquired = false;
693 String infName = port.getUuid().getValue();
694 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
697 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
698 isLockAcquired = NeutronvpnUtils.lock(infName);
699 Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
700 .CONFIGURATION, vpnIfIdentifier);
701 if (optionalVpnInterface.isPresent()) {
702 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
703 .setVpnInstanceName(vpnId.getValue());
704 LOG.debug("Updating vpn interface {}", infName);
705 if (!isBeingAssociated) {
706 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
707 List<Adjacency> adjacencyList = (adjs != null) ? adjs.getAdjacency() : new ArrayList<>();
708 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
709 while (adjacencyIter.hasNext()) {
710 Adjacency adjacency = adjacencyIter.next();
711 String mipToQuery = adjacency.getIpAddress().split("/")[0];
712 InstanceIdentifier<LearntVpnVipToPort> id =
713 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
714 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
715 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
716 if (optionalVpnVipToPort.isPresent()) {
717 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
718 + "from VPN " + "{}", infName, vpnId, oldVpnId);
719 adjacencyIter.remove();
720 NeutronvpnUtils.removeLearntVpnVipToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
721 LOG.trace("Entry for fixedIP {} for port {} on VPN removed from "
722 + "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
725 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
726 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
728 List<FixedIps> ips = port.getFixedIps();
729 for (FixedIps ip : ips) {
730 String ipValue = String.valueOf(ip.getIpAddress().getValue());
731 if (oldVpnId != null) {
732 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(),
733 ipValue, writeConfigTxn);
735 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
736 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
738 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
740 writeConfigTxn.submit();
742 LOG.error("VPN Interface {} not found", infName);
744 } catch (Exception ex) {
745 LOG.error("Updation of vpninterface {} failed due to {}", infName, ex);
747 if (isLockAcquired) {
748 NeutronvpnUtils.unlock(infName);
753 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
754 List<String> ert, Uuid router, List<Uuid> networks) {
756 // Update VPN Instance node
757 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/);
759 // Update local vpn-subnet DS
760 updateVpnMaps(vpn, name, router, tenant, networks);
762 if (router != null) {
763 Uuid existingVpn = NeutronvpnUtils.getVpnForRouter(dataBroker, router, true);
764 if (existingVpn != null) {
765 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
767 // if before reboot, router was already associated to VPN, should not proceed associating router to
768 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
769 // preserved upon reboot.
770 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
771 // RouterInterfacesMap via #createVPNInterface call.
772 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
773 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
776 associateRouterToInternalVpn(vpn, router);
781 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
782 * specified Neutron Networks and Routers.
784 * @param vpn Uuid of the VPN tp be created
785 * @param name Representative name of the new VPN
786 * @param tenant Uuid of the Tenant under which the VPN is going to be created
787 * @param rd Route-distinguisher for the VPN
788 * @param irt A list of Import Route Targets
789 * @param ert A list of Export Route Targets
790 * @param router UUID of the neutron router the VPN may be associated to
791 * @param networks UUID of the neutron network the VPN may be associated to
792 * @param type Type of the VPN Instance
793 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
794 * @throws Exception if association of L3VPN failed
796 public void createVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
797 Uuid router, List<Uuid> networks, VpnInstance.Type type, long l3vni) throws Exception {
799 // Update VPN Instance node
800 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, type, l3vni);
802 // Please note that router and networks will be filled into VPNMaps
803 // by subsequent calls here to associateRouterToVpn and
804 // associateNetworksToVpn
805 updateVpnMaps(vpn, name, null, tenant, null);
807 if (router != null) {
808 associateRouterToVpn(vpn, router);
810 if (networks != null) {
811 List<String> failStrings = associateNetworksToVpn(vpn, networks);
812 if (failStrings != null && !failStrings.isEmpty()) {
813 LOG.error("VPN {} association to networks failed with error message {}. ",
814 vpn.getValue(), failStrings.get(0));
815 throw new Exception(failStrings.get(0));
821 * It handles the invocations to the createVPN RPC method.
824 // TODO Clean up the exception handling
825 @SuppressWarnings("checkstyle:IllegalCatch")
826 public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
828 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
829 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
830 List<RpcError> errorList = new ArrayList<>();
831 int failurecount = 0;
832 int warningcount = 0;
834 List<L3vpn> vpns = input.getL3vpn();
835 for (L3vpn vpn : vpns) {
836 RpcError error = null;
838 if (NeutronvpnUtils.doesVpnExist(dataBroker, vpn.getId())) {
839 msg = String.format("Creation of L3VPN failed for VPN %s due to VPN with the same ID already present",
840 vpn.getId().getValue());
842 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
843 errorList.add(error);
847 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
848 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
849 vpn.getId().getValue());
851 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
852 errorList.add(error);
856 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
858 if (vpn.getL3vni() != null) {
859 l3vni = vpn.getL3vni();
862 if (vpn.getRouteDistinguisher().size() > 1) {
863 msg = String.format("Creation of VPN failed for VPN %s due to multiple RD input %s",
864 vpn.getId().getValue(), vpn.getRouteDistinguisher());
866 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
867 errorList.add(error);
871 List<String> existingRDs = NeutronvpnUtils.getExistingRDs(dataBroker);
872 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
873 msg = String.format("Creation of L3VPN failed for VPN %s as another VPN with the same RD %s "
874 + "is already configured",
875 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0));
877 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
878 errorList.add(error);
882 if (vpn.getRouterId() != null) {
883 if (NeutronvpnUtils.getNeutronRouter(dataBroker, vpn.getRouterId()) == null) {
884 msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
885 vpn.getId().getValue(), vpn.getRouterId().getValue());
887 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
888 errorList.add(error);
892 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, vpn.getRouterId(), true);
894 msg = String.format("Creation of L3VPN failed for VPN %s due to router %s already associated to "
895 + "another VPN %s", vpn.getId().getValue(), vpn.getRouterId().getValue(),
898 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
899 errorList.add(error);
904 if (vpn.getNetworkIds() != null) {
905 for (Uuid nw : vpn.getNetworkIds()) {
906 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
907 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
908 if (network == null) {
909 msg = String.format("Creation of L3VPN failed for VPN %s due to network not found %s",
910 vpn.getId().getValue(), nw.getValue());
912 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
913 errorList.add(error);
915 } else if (vpnId != null) {
916 msg = String.format("Creation of L3VPN failed for VPN %s due to network %s already associated"
917 + " to another VPN %s", vpn.getId().getValue(), nw.getValue(),
920 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
921 errorList.add(error);
930 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
931 vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds(),
932 vpnInstanceType, l3vni);
933 } catch (Exception ex) {
934 msg = String.format("Creation of VPN failed for VPN %s", vpn.getId().getValue());
936 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
937 errorList.add(error);
941 // if at least one succeeds; result is success
942 // if none succeeds; result is failure
943 if (failurecount + warningcount == vpns.size()) {
944 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
946 List<String> errorResponseList = new ArrayList<>();
947 if (!errorList.isEmpty()) {
948 for (RpcError rpcError : errorList) {
949 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
950 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
951 errorResponseList.add(errorResponse);
954 errorResponseList.add("Operation successful with no errors");
956 opBuilder.setResponse(errorResponseList);
957 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
963 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
966 // TODO Clean up the exception handling
967 @SuppressWarnings("checkstyle:IllegalCatch")
968 public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
970 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
971 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
972 Uuid inputVpnId = input.getId();
973 List<VpnInstance> vpns = new ArrayList<>();
976 if (inputVpnId == null) {
978 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
980 Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
981 .CONFIGURATION, vpnsIdentifier);
982 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
983 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
984 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
985 // from getL3VPN output
986 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
992 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
996 String name = inputVpnId.getValue();
997 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
998 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
999 // read VpnInstance Info
1000 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1002 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1004 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1005 vpns.add(optionalVpn.get());
1007 String message = String.format("GetL3VPN failed because VPN %s is not present", name);
1009 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL,
1010 "invalid-value", message).build());
1013 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1014 for (VpnInstance vpnInstance : vpns) {
1015 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1016 // create VpnMaps id
1017 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1019 List<String> rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(","));
1020 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1022 List<String> ertList = new ArrayList<>();
1023 List<String> irtList = new ArrayList<>();
1025 for (VpnTarget vpnTarget : vpnTargetList) {
1026 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1027 ertList.add(vpnTarget.getVrfRTValue());
1029 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1030 irtList.add(vpnTarget.getVrfRTValue());
1032 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1033 ertList.add(vpnTarget.getVrfRTValue());
1034 irtList.add(vpnTarget.getVrfRTValue());
1038 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1039 if (vpnInstance.getL3vni() != null) {
1040 l3vpn.setL3vni(vpnInstance.getL3vni());
1042 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1043 .class, new VpnMapKey(vpnId)).build();
1044 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1046 if (optionalVpnMap.isPresent()) {
1047 VpnMap vpnMap = optionalVpnMap.get();
1048 l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1049 .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1051 l3vpnList.add(l3vpn.build());
1054 opBuilder.setL3vpnInstances(l3vpnList);
1055 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1057 } catch (Exception ex) {
1058 String message = String.format("GetVPN failed due to %s", ex.getMessage());
1059 LOG.error(message, ex);
1060 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
1066 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1069 // TODO Clean up the exception handling
1070 @SuppressWarnings("checkstyle:IllegalCatch")
1071 public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1073 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1074 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1075 List<RpcError> errorList = new ArrayList<>();
1077 int failurecount = 0;
1078 int warningcount = 0;
1079 List<Uuid> vpns = input.getId();
1080 for (Uuid vpn : vpns) {
1084 InstanceIdentifier<VpnInstance> vpnIdentifier =
1085 InstanceIdentifier.builder(VpnInstances.class)
1086 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1087 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1088 .CONFIGURATION, vpnIdentifier);
1089 if (optionalVpn.isPresent()) {
1092 msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
1094 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
1095 errorList.add(error);
1098 } catch (Exception ex) {
1099 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
1101 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1102 errorList.add(error);
1106 // if at least one succeeds; result is success
1107 // if none succeeds; result is failure
1108 if (failurecount + warningcount == vpns.size()) {
1109 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1111 List<String> errorResponseList = new ArrayList<>();
1112 if (!errorList.isEmpty()) {
1113 for (RpcError rpcError : errorList) {
1114 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
1115 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
1116 errorResponseList.add(errorResponse);
1119 errorResponseList.add("Operation successful with no errors");
1121 opBuilder.setResponse(errorResponseList);
1122 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1127 protected void addSubnetToVpn(final Uuid vpnId, Uuid subnet) {
1128 LOG.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
1129 Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1130 final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1131 // Check if there are ports on this subnet and add corresponding
1133 List<Uuid> portList = sn.getPortList();
1134 if (portList != null) {
1135 for (final Uuid portId : sn.getPortList()) {
1136 LOG.debug("adding vpn-interface for port {}", portId.getValue());
1137 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1138 portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1139 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1140 List<ListenableFuture<Void>> futures = new ArrayList<>();
1141 createVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
1143 futures.add(wrtConfigTxn.submit());
1150 protected void updateVpnForSubnet(Uuid vpnId, Uuid subnet, boolean isBeingAssociated) {
1151 LOG.debug("Updating VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
1152 // Read the subnet first to see if its already associated to a VPN
1153 Uuid oldVpnId = null;
1154 InstanceIdentifier<Subnetmap> snId = InstanceIdentifier.builder(Subnetmaps.class)
1155 .child(Subnetmap.class, new SubnetmapKey(subnet)).build();
1156 Subnetmap sn = null;
1157 Optional<Subnetmap> optSn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, snId);
1158 if (optSn.isPresent()) {
1160 oldVpnId = sn.getVpnId();
1161 List<String> ips = sn.getRouterInterfaceFixedIps();
1162 for (String ipValue : ips) {
1163 // Update the association of router-interface to external vpn
1165 NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, oldVpnId.getValue(), ipValue);
1166 if (portName != null) {
1167 updateVpnInterface(vpnId, oldVpnId,
1168 NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(portName)),
1169 isBeingAssociated, true);
1173 sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1174 // Check for ports on this subnet and update association of
1175 // corresponding vpn-interfaces to external vpn
1176 List<Uuid> portList = sn.getPortList();
1177 if (portList != null) {
1178 for (Uuid port : sn.getPortList()) {
1179 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1180 port.getValue(), isBeingAssociated);
1181 updateVpnInterface(vpnId, oldVpnId, NeutronvpnUtils.getNeutronPort(dataBroker, port),
1182 isBeingAssociated, false);
1187 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1188 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1189 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1192 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1193 synchronized (routerId.getValue().intern()) {
1194 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1195 Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1196 .CONFIGURATION, routerInterfacesId);
1197 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1198 .setInterfaceId(interfaceName).build();
1199 if (optRouterInterfaces.isPresent()) {
1200 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1201 .class, new InterfacesKey(interfaceName)), routerInterface);
1203 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1204 List<Interfaces> interfaces = new ArrayList<>();
1205 interfaces.add(routerInterface);
1206 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1207 .class, new InterfacesKey(interfaceName)), routerInterface);
1212 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1213 synchronized (routerId.getValue().intern()) {
1214 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1215 Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1216 .CONFIGURATION, routerInterfacesId);
1217 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1218 .setInterfaceId(interfaceName).build();
1219 if (optRouterInterfaces.isPresent()) {
1220 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1221 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1222 if (interfaces != null && interfaces.remove(routerInterface)) {
1223 if (interfaces.isEmpty()) {
1224 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1226 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1227 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1235 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1236 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1237 * route will be ignored.
1239 * @param vpnName the VPN identifier
1240 * @param interVpnLinkRoutes The list of static routes
1241 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1243 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1244 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1245 for ( Routes route : interVpnLinkRoutes ) {
1246 String nexthop = String.valueOf(route.getNexthop().getValue());
1247 String destination = String.valueOf(route.getDestination().getValue());
1248 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1249 if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
1250 AddStaticRouteInput rpcInput =
1251 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1252 .setVpnInstanceName(vpnName.getValue())
1254 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1255 RpcResult<AddStaticRouteOutput> rpcResult;
1257 rpcResult = labelOuputFtr.get();
1258 if ( rpcResult.isSuccessful() ) {
1259 LOG.debug("Label generated for destination {} is: {}",
1260 destination, rpcResult.getResult().getLabel());
1262 LOG.warn("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1263 destination, nexthop, rpcResult.getErrors());
1265 } catch (InterruptedException | ExecutionException e) {
1266 LOG.warn("Error happened while invoking addStaticRoute RPC: ", e);
1269 // Any other case is a fault.
1270 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1271 String.valueOf(route.getDestination().getValue()), nexthop );
1278 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1279 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1281 * @param vpnName the VPN identifier
1282 * @param interVpnLinkRoutes The list of static routes
1283 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1285 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1286 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1287 for ( Routes route : interVpnLinkRoutes ) {
1288 String nexthop = String.valueOf(route.getNexthop().getValue());
1289 String destination = String.valueOf(route.getDestination().getValue());
1290 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1291 if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
1292 RemoveStaticRouteInput rpcInput =
1293 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1294 .setVpnInstanceName(vpnName.getValue())
1296 vpnRpcService.removeStaticRoute(rpcInput);
1298 // Any other case is a fault.
1299 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1300 String.valueOf(route.getDestination().getValue()), nexthop );
1307 * Returns true if the specified nexthop is the other endpoint in an
1308 * InterVpnLink, regarding one of the VPN's point of view.
1310 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1312 interVpnLink != null
1313 && ( (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1314 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop))
1315 || (interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid )
1316 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)) );
1319 protected List<Adjacency> getAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList, String fixedIp) {
1320 List<Adjacency> adjList = new ArrayList<>();
1321 Map<String, List<String>> adjMap = new HashMap<>();
1322 for (Routes route : routeList) {
1323 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1324 LOG.error("Incorrect input received for extra route. {}", route);
1326 String nextHop = String.valueOf(route.getNexthop().getValue());
1327 String destination = String.valueOf(route.getDestination().getValue());
1328 if (!nextHop.equals(fixedIp)) {
1329 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1332 LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} ", destination,
1333 vpnId.getValue(), nextHop);
1334 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1335 if (!hops.contains(nextHop)) {
1341 for (String destination : adjMap.keySet()) {
1342 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1343 .setNextHopIpList(adjMap.get(destination)).setKey(new AdjacencyKey(destination)).build();
1349 // TODO Clean up the exception handling
1350 @SuppressWarnings("checkstyle:IllegalCatch")
1351 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1352 for (Routes route : routeList) {
1353 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1354 LOG.error("Incorrect input received for extra route. {}", route);
1356 String nextHop = String.valueOf(route.getNexthop().getValue());
1357 String destination = String.valueOf(route.getDestination().getValue());
1358 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1360 if (infName != null) {
1361 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
1362 destination, vpnId.getValue(), nextHop, infName);
1363 boolean isLockAcquired = false;
1365 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
1366 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1367 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
1368 .child(Adjacency.class, new AdjacencyKey(destination));
1369 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1370 .setNextHopIpList(Collections.singletonList(nextHop)).setKey(new AdjacencyKey(destination))
1372 isLockAcquired = NeutronvpnUtils.lock(infName);
1373 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, erAdj);
1374 } catch (Exception e) {
1375 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
1376 destination, nextHop, e);
1378 if (isLockAcquired) {
1379 NeutronvpnUtils.unlock(infName);
1383 LOG.debug("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1384 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1390 // TODO Clean up the exception handling
1391 @SuppressWarnings("checkstyle:IllegalCatch")
1392 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
1393 for (Routes route : routeList) {
1394 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
1395 boolean isLockAcquired = false;
1396 String nextHop = String.valueOf(route.getNexthop().getValue());
1397 String destination = String.valueOf(route.getDestination().getValue());
1398 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1400 if (infName == null) {
1401 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
1402 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1403 // Proceed to remove the next extra-route
1406 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
1407 destination, vpnId.getValue(), nextHop, infName);
1409 InstanceIdentifier<Adjacency> adjacencyIdentifier =
1410 InstanceIdentifier.builder(VpnInterfaces.class)
1411 .child(VpnInterface.class, new VpnInterfaceKey(infName))
1412 .augmentation(Adjacencies.class)
1413 .child(Adjacency.class, new AdjacencyKey(destination))
1416 // Looking for existing prefix in MDSAL database
1417 Optional<Adjacency> adjacency = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1418 adjacencyIdentifier);
1419 boolean updateNextHops = false;
1420 List<String> nextHopList = new ArrayList<>();
1421 if (adjacency.isPresent()) {
1422 List<String> nhListRead = adjacency.get().getNextHopIpList();
1423 if (nhListRead.size() > 1) { // ECMP case
1424 for (String nextHopRead : nhListRead) {
1425 if (nextHopRead.equals(nextHop)) {
1426 updateNextHops = true;
1428 nextHopList.add(nextHopRead);
1435 isLockAcquired = NeutronvpnUtils.lock(infName);
1436 if (updateNextHops) {
1437 // An update must be done, not including the current next hop
1438 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
1439 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1440 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
1441 .setNextHopIpList(nextHopList)
1442 .setKey(new AdjacencyKey(destination))
1444 Adjacencies erAdjs =
1445 new AdjacenciesBuilder().setAdjacency(Collections.singletonList(newAdj)).build();
1446 VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
1447 .addAugmentation(Adjacencies.class, erAdjs).build();
1448 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
1450 // Remove the whole route
1451 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1452 LOG.trace("extra route {} deleted successfully", route);
1454 } catch (Exception e) {
1455 LOG.error("exception in deleting extra route: {}" + e);
1457 if (isLockAcquired) {
1458 NeutronvpnUtils.unlock(infName);
1462 LOG.error("Incorrect input received for extra route. {}", route);
1467 protected void removeVpn(Uuid id) {
1469 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, id);
1470 Uuid router = (vpnMap != null) ? vpnMap.getRouterId() : null;
1471 // dissociate router
1472 if (router != null) {
1473 dissociateRouterFromVpn(id, router);
1475 // dissociate networks
1476 if (!id.equals(router)) {
1477 dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
1479 // remove entire vpnMaps node
1480 deleteVpnMapsNode(id);
1482 // remove vpn-instance
1483 deleteVpnInstance(id);
1486 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet) {
1487 LOG.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
1488 final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1489 Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1491 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1492 List<Uuid> portList = sn.getPortList();
1493 if (portList != null) {
1494 for (final Uuid portId : sn.getPortList()) {
1495 LOG.debug("removing vpn-interface for port {}", portId.getValue());
1496 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1497 portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1498 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1499 List<ListenableFuture<Void>> futures = new ArrayList<>();
1500 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1502 deleteVpnInterface(vpnId, routerId, port, wrtConfigTxn);
1504 LOG.error("Cannot proceed with deleteVpnInterface for port {} in subnet {} since port is "
1505 + "absent in Neutron config DS", portId.getValue(), subnet.getValue());
1507 futures.add(wrtConfigTxn.submit());
1512 // update subnet-vpn association
1513 removeFromSubnetNode(subnet, null, null, vpnId, null);
1515 LOG.warn("Subnetmap for subnet {} not found", subnet.getValue());
1519 // TODO Clean up the exception handling
1520 @SuppressWarnings("checkstyle:IllegalCatch")
1521 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
1522 updateVpnMaps(vpnId, null, routerId, null, null);
1523 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
1524 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1525 if (routerSubnets != null) {
1526 for (Uuid subnetId : routerSubnets) {
1527 updateVpnForSubnet(vpnId, subnetId, true);
1531 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
1532 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
1534 } catch (Exception e) {
1535 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
1536 .getValue(), vpnId.getValue(), e);
1540 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
1541 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1542 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
1543 for (Uuid subnet : routerSubnets) {
1544 addSubnetToVpn(vpnId, subnet);
1548 // TODO Clean up the exception handling
1549 @SuppressWarnings("checkstyle:IllegalCatch")
1550 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
1552 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1553 if (routerSubnets != null) {
1554 for (Uuid subnetId : routerSubnets) {
1555 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
1556 updateVpnForSubnet(routerId, subnetId, false);
1559 clearFromVpnMaps(vpnId, routerId, null);
1561 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
1562 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
1564 } catch (Exception e) {
1565 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
1566 .getValue(), vpnId.getValue(), e);
1570 protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
1571 List<String> failedNwList = new ArrayList<>();
1572 List<Uuid> passedNwList = new ArrayList<>();
1573 if (!networks.isEmpty()) {
1574 // process corresponding subnets for VPN
1575 for (Uuid nw : networks) {
1576 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1577 NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
1578 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
1579 LOG.error("MultiSegmented networks not supported in VPN. Failed to associate network {} on vpn {}",
1580 nw.getValue(), vpn.getValue());
1581 failedNwList.add(String.format("Failed to associate network %s on vpn %s as it is multisegmented.",
1582 nw.getValue(), vpn.getValue()));
1585 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1586 if (network == null) {
1587 failedNwList.add(String.format("network %s not found", nw.getValue()));
1588 } else if (vpnId != null) {
1589 failedNwList.add(String.format("network %s already associated to another VPN %s", nw.getValue(),
1592 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1593 LOG.debug("Adding network subnets...{}", networkSubnets);
1594 if (networkSubnets != null) {
1595 for (Uuid subnet : networkSubnets) {
1596 // check if subnet added as router interface to some router
1597 Uuid subnetVpnId = NeutronvpnUtils.getVpnForSubnet(dataBroker, subnet);
1598 if (subnetVpnId == null) {
1599 addSubnetToVpn(vpn, subnet);
1600 passedNwList.add(nw);
1602 failedNwList.add(String.format("subnet %s already added as router interface bound to "
1603 + "internal/external VPN %s", subnet.getValue(), subnetVpnId.getValue()));
1607 if (NeutronvpnUtils.getIsExternal(network)) {
1608 nvpnNatManager.addExternalNetworkToVpn(network, vpn);
1612 updateVpnMaps(vpn, null, null, null, passedNwList);
1614 return failedNwList;
1617 protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
1618 List<String> failedNwList = new ArrayList<>();
1619 List<Uuid> passedNwList = new ArrayList<>();
1620 if (networks != null && !networks.isEmpty()) {
1621 // process corresponding subnets for VPN
1622 for (Uuid nw : networks) {
1623 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1624 if (network == null) {
1625 failedNwList.add(String.format("network %s not found", nw.getValue()));
1627 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1628 if (vpn.equals(vpnId)) {
1629 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1630 LOG.debug("Removing network subnets...");
1631 if (networkSubnets != null) {
1632 for (Uuid subnet : networkSubnets) {
1633 removeSubnetFromVpn(vpn, subnet);
1634 passedNwList.add(nw);
1638 if (vpnId == null) {
1639 failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
1642 failedNwList.add(String.format("input network %s associated to a another vpn %s instead "
1643 + "of the one given as input", nw.getValue(), vpnId.getValue()));
1646 if (NeutronvpnUtils.getIsExternal(network)) {
1647 nvpnNatManager.removeExternalNetworkFromVpn(network);
1651 clearFromVpnMaps(vpn, null, passedNwList);
1653 return failedNwList;
1657 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
1660 // TODO Clean up the exception handling
1661 @SuppressWarnings("checkstyle:IllegalCatch")
1662 public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1664 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
1665 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
1666 LOG.debug("associateNetworks {}", input);
1667 StringBuilder returnMsg = new StringBuilder();
1668 Uuid vpnId = input.getVpnId();
1671 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1672 List<Uuid> netIds = input.getNetworkId();
1673 if (netIds != null && !netIds.isEmpty()) {
1674 List<String> failed = associateNetworksToVpn(vpnId, netIds);
1675 if (!failed.isEmpty()) {
1676 returnMsg.append(failed);
1680 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1682 if (returnMsg.length() != 0) {
1683 String message = String.format("associate Networks to vpn %s failed due to %s",
1684 vpnId.getValue(), returnMsg);
1686 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
1688 opBuilder.setResponse(errorResponse);
1689 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
1691 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
1693 } catch (Exception ex) {
1694 String message = String.format("associate Networks to vpn %s failed due to %s",
1695 input.getVpnId().getValue(), ex.getMessage());
1696 LOG.error(message, ex);
1697 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1700 LOG.debug("associateNetworks returns..");
1705 * It handles the invocations to the neutronvpn:associateRouter RPC method.
1708 // TODO Clean up the exception handling
1709 @SuppressWarnings("checkstyle:IllegalCatch")
1710 public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1712 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1713 LOG.debug("associateRouter {}", input);
1714 StringBuilder returnMsg = new StringBuilder();
1715 Uuid vpnId = input.getVpnId();
1716 Uuid routerId = input.getRouterId();
1718 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1719 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1720 if (vpnMap != null) {
1722 Uuid extVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1723 if (vpnMap.getRouterId() != null) {
1724 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
1725 .append(vpnMap.getRouterId().getValue());
1726 } else if (extVpnId != null) {
1727 returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
1728 + "another VPN ").append(extVpnId.getValue());
1730 associateRouterToVpn(vpnId, routerId);
1733 returnMsg.append("router not found : ").append(routerId.getValue());
1736 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1738 if (returnMsg.length() != 0) {
1739 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1742 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1745 result.set(RpcResultBuilder.<Void>success().build());
1747 } catch (Exception ex) {
1748 String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
1749 vpnId.getValue(), ex.getMessage());
1750 LOG.error(message, ex);
1751 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1753 LOG.debug("associateRouter returns..");
1757 /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
1760 // TODO Clean up the exception handling
1761 @SuppressWarnings("checkstyle:IllegalCatch")
1762 public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
1763 GetFixedIPsForNeutronPortInput input) {
1764 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
1765 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
1766 Uuid portId = input.getPortId();
1767 StringBuilder returnMsg = new StringBuilder();
1769 List<String> fixedIPList = new ArrayList<>();
1770 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1772 List<FixedIps> fixedIPs = port.getFixedIps();
1773 for (FixedIps ip : fixedIPs) {
1774 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
1777 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
1779 if (returnMsg.length() != 0) {
1780 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
1782 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1783 .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
1785 opBuilder.setFixedIPs(fixedIPList);
1786 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
1788 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
1790 } catch (Exception ex) {
1791 String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s",
1792 portId.getValue(), ex.getMessage());
1793 LOG.error(message, ex);
1794 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1795 .withError(ErrorType.APPLICATION, message).build());
1801 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
1804 // TODO Clean up the exception handling
1805 @SuppressWarnings("checkstyle:IllegalCatch")
1806 public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
1808 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
1809 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
1811 LOG.debug("dissociateNetworks {}", input);
1812 StringBuilder returnMsg = new StringBuilder();
1813 Uuid vpnId = input.getVpnId();
1816 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1817 List<Uuid> netIds = input.getNetworkId();
1818 if (netIds != null && !netIds.isEmpty()) {
1819 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
1820 if (!failed.isEmpty()) {
1821 returnMsg.append(failed);
1825 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1827 if (returnMsg.length() != 0) {
1828 String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
1831 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1833 opBuilder.setResponse(errorResponse);
1834 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
1836 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
1838 } catch (Exception ex) {
1839 String message = String.format("dissociate Networks to vpn %s failed due to %s",
1840 input.getVpnId().getValue(), ex.getMessage());
1841 LOG.error(message, ex);
1842 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1845 LOG.debug("dissociateNetworks returns..");
1850 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
1853 // TODO Clean up the exception handling
1854 @SuppressWarnings("checkstyle:IllegalCatch")
1855 public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
1857 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1859 LOG.debug("dissociateRouter {}", input);
1860 StringBuilder returnMsg = new StringBuilder();
1861 Uuid vpnId = input.getVpnId();
1862 Uuid routerId = input.getRouterId();
1864 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1865 if (routerId != null) {
1866 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1868 Uuid routerVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1869 if (vpnId.equals(routerVpnId)) {
1870 dissociateRouterFromVpn(vpnId, routerId);
1872 if (routerVpnId == null) {
1873 returnMsg.append("input router ").append(routerId.getValue())
1874 .append(" not associated to any vpn yet");
1876 returnMsg.append("input router ").append(routerId.getValue())
1877 .append(" associated to vpn ")
1878 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
1882 returnMsg.append("router not found : ").append(routerId.getValue());
1886 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1888 if (returnMsg.length() != 0) {
1889 String message = String.format("dissociate router %s to vpn %s failed due to %s", routerId.getValue(),
1890 vpnId.getValue(), returnMsg);
1892 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1894 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1897 result.set(RpcResultBuilder.<Void>success().build());
1899 } catch (Exception ex) {
1900 String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
1901 vpnId.getValue(), ex.getMessage());
1902 LOG.error(message, ex);
1903 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1905 LOG.debug("dissociateRouter returns..");
1910 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
1911 // check if the router is associated to some VPN
1912 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1913 if (vpnId != null) {
1914 // remove existing external vpn interfaces
1915 for (Uuid subnetId : routerSubnetIds) {
1916 removeSubnetFromVpn(vpnId, subnetId);
1918 clearFromVpnMaps(vpnId, routerId, null);
1920 // remove existing internal vpn interfaces
1921 for (Uuid subnetId : routerSubnetIds) {
1922 removeSubnetFromVpn(routerId, subnetId);
1925 // delete entire vpnMaps node for internal VPN
1926 deleteVpnMapsNode(routerId);
1928 // delete vpn-instance for internal VPN
1929 deleteVpnInstance(routerId);
1932 protected Subnet getNeutronSubnet(Uuid subnetId) {
1933 return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1936 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
1937 Subnet sn = NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1939 return sn.getGatewayIp();
1945 protected Network getNeutronNetwork(Uuid networkId) {
1946 return NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
1949 protected Port getNeutronPort(String name) {
1950 return NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(name));
1953 protected Port getNeutronPort(Uuid portId) {
1954 return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1957 protected Uuid getNetworkForSubnet(Uuid subnetId) {
1958 return NeutronvpnUtils.getNetworkForSubnet(dataBroker, subnetId);
1961 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
1962 return NeutronvpnUtils.getNetworksforVpn(dataBroker, vpnId);
1966 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
1968 * @return a List of String to be printed on screen
1970 // TODO Clean up the exception handling and the console output
1971 @SuppressWarnings({"checkstyle:IllegalCatch", "checkstyle:RegexpSinglelineJava"})
1972 public List<String> showNeutronPortsCLI() {
1973 List<String> result = new ArrayList<>();
1974 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
1976 result.add("-------------------------------------------------------------------------------------------");
1977 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
1979 Optional<Ports> ports =
1980 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
1981 if (ports.isPresent() && ports.get().getPort() != null) {
1982 for (Port port : ports.get().getPort()) {
1983 List<FixedIps> fixedIPs = port.getFixedIps();
1985 if (fixedIPs != null && !fixedIPs.isEmpty()) {
1986 List<String> ipList = new ArrayList<>();
1987 for (FixedIps fixedIp : fixedIPs) {
1988 IpAddress ipAddress = fixedIp.getIpAddress();
1989 if (ipAddress.getIpv4Address() != null) {
1990 ipList.add(ipAddress.getIpv4Address().getValue());
1992 ipList.add((ipAddress.getIpv6Address().getValue()));
1995 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
1996 .getMacAddress().getValue(), NeutronvpnUtils.getIPPrefixFromPort(dataBroker, port),
1997 ipList.toString()));
1999 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
2000 .getMacAddress().getValue(), "Not Assigned", "Not " + "Assigned"));
2002 } catch (Exception e) {
2003 LOG.error("Failed to retrieve neutronPorts info for port {}: ", port.getUuid().getValue(),
2005 System.out.println("Failed to retrieve neutronPorts info for port: " + port.getUuid()
2006 .getValue() + ": " + e.getMessage());
2010 } catch (Exception e) {
2011 LOG.error("Failed to retrieve neutronPorts info : ", e);
2012 System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
2018 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2020 * @param vpnuuid Uuid of the VPN whose config must be shown
2021 * @return formatted output list
2023 @SuppressWarnings("checkstyle:RegexpSinglelineJava")
2024 public List<String> showVpnConfigCLI(Uuid vpnuuid) {
2025 List<String> result = new ArrayList<>();
2026 if (vpnuuid == null) {
2027 System.out.println("");
2028 System.out.println("Displaying VPN config for all VPNs");
2029 System.out.println("To display VPN config for a particular VPN, use the following syntax");
2030 System.out.println(getshowVpnConfigCLIHelp());
2033 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2034 if (rpcResult.isSuccessful()) {
2036 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2038 result.add(String.format(" %-80s ", "Import-RTs"));
2040 result.add(String.format(" %-80s ", "Export-RTs"));
2042 result.add(String.format(" %-76s ", "Subnet IDs"));
2044 result.add("------------------------------------------------------------------------------------");
2046 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2047 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
2048 .rev150602.VpnInstance vpn : vpnList) {
2049 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2051 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2052 vpn.getRouteDistinguisher()));
2054 result.add(String.format(" %-80s ", vpn.getImportRT()));
2056 result.add(String.format(" %-80s ", vpn.getExportRT()));
2059 Uuid vpnid = vpn.getId();
2060 List<Uuid> subnetList = NeutronvpnUtils.getSubnetsforVpn(dataBroker, vpnid);
2061 if (!subnetList.isEmpty()) {
2062 for (Uuid subnetuuid : subnetList) {
2063 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2066 result.add(String.format(" %-76s ", "\" \""));
2069 result.add("----------------------------------------");
2073 String errortag = rpcResult.getErrors().iterator().next().getTag();
2074 if (errortag == "") {
2075 System.out.println("");
2076 System.out.println("No VPN has been configured yet");
2077 } else if (errortag == "invalid-value") {
2078 System.out.println("");
2079 System.out.println("VPN " + vpnuuid.getValue() + " is not present");
2081 System.out.println("error getting VPN info : " + rpcResult.getErrors());
2082 System.out.println(getshowVpnConfigCLIHelp());
2085 } catch (InterruptedException | ExecutionException e) {
2086 LOG.error("error getting VPN info : ", e);
2087 System.out.println("error getting VPN info : " + e.getMessage());
2092 protected void createExternalVpnInterfaces(Uuid extNetId) {
2093 if (extNetId == null) {
2094 LOG.trace("external network is null");
2098 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2099 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2100 LOG.trace("No external ports attached to external network {}", extNetId.getValue());
2104 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2105 for (String elanInterface : extElanInterfaces) {
2106 createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
2108 wrtConfigTxn.submit();
2111 // TODO Clean up the exception handling
2112 @SuppressWarnings("checkstyle:IllegalCatch")
2113 protected void removeExternalVpnInterfaces(Uuid extNetId) {
2114 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2115 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2116 LOG.trace("No external ports attached for external network {}", extNetId);
2121 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2122 for (String elanInterface : extElanInterfaces) {
2123 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2124 .buildVpnInterfaceIdentifier(elanInterface);
2125 LOG.info("Removing vpn interface {}", elanInterface);
2126 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2128 wrtConfigTxn.submit();
2130 } catch (Exception ex) {
2131 LOG.error("Removal of vpninterfaces {} failed due to {}", extElanInterfaces, ex);
2135 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2136 writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, wrtConfigTxn);
2139 // TODO Clean up the exception handling
2140 @SuppressWarnings("checkstyle:IllegalCatch")
2141 private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
2142 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2143 if (vpnId == null || infName == null) {
2144 LOG.debug("vpn id or interface is null");
2148 Boolean wrtConfigTxnPresent = true;
2149 if (wrtConfigTxn == null) {
2150 wrtConfigTxnPresent = false;
2151 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2154 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2155 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2157 .setVpnInstanceName(vpnId.getValue())
2158 .setIsRouterInterface(isRouterInterface);
2159 if (adjacencies != null) {
2160 vpnb.addAugmentation(Adjacencies.class, adjacencies);
2162 VpnInterface vpnIf = vpnb.build();
2164 LOG.info("Creating vpn interface {}", vpnIf);
2165 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2166 } catch (Exception ex) {
2167 LOG.error("Creation of vpninterface {} failed due to {}", infName, ex);
2170 if (!wrtConfigTxnPresent) {
2171 wrtConfigTxn.submit();
2175 private String getshowVpnConfigCLIHelp() {
2176 StringBuilder help = new StringBuilder("Usage:");
2177 help.append("display vpn-config [-vid/--vpnid <id>]");
2178 return help.toString();
2181 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
2182 InterruptedException {
2183 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
2184 .setVpnId(vpnId).build();
2185 LOG.info("publishing notification upon association of router to VPN");
2186 notificationPublishService.putNotification(routerAssociatedToVpn);
2189 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
2190 InterruptedException {
2191 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
2192 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
2193 LOG.info("publishing notification upon disassociation of router from VPN");
2194 notificationPublishService.putNotification(routerDisassociatedFromVpn);
2197 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
2198 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);