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.EventListener;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.List;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Future;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
28 import org.opendaylight.genius.mdsalutil.MDSALUtil;
29 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
30 import org.opendaylight.netvirt.elanmanager.api.IElanService;
31 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
32 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
34 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
35 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
42 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
43 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
44 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.L3vpnInstance;
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.rev150712.Neutron;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
115 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
116 import org.opendaylight.yangtools.yang.common.RpcError;
117 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
118 import org.opendaylight.yangtools.yang.common.RpcResult;
119 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
120 import org.slf4j.Logger;
121 import org.slf4j.LoggerFactory;
123 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
124 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
125 private final DataBroker dataBroker;
126 private final NeutronvpnNatManager nvpnNatManager;
127 private final NotificationPublishService notificationPublishService;
128 private final VpnRpcService vpnRpcService;
129 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
130 private final NeutronvpnConfig neutronvpnConfig;
131 private final IMdsalApiManager mdsalUtil;
132 private final IElanService elanService;
134 public NeutronvpnManager(
135 final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
136 final NotificationPublishService notiPublishService, final NeutronvpnNatManager vpnNatMgr,
137 final VpnRpcService vpnRpcSrv, final IElanService elanService,
138 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
139 final NeutronvpnConfig neutronvpnConfig) {
140 this.dataBroker = dataBroker;
141 mdsalUtil = mdsalManager;
142 nvpnNatManager = vpnNatMgr;
143 notificationPublishService = notiPublishService;
144 vpnRpcService = vpnRpcSrv;
145 this.elanService = elanService;
146 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
147 LOG.info("neutronvpnConfig: {}", neutronvpnConfig);
148 this.neutronvpnConfig = neutronvpnConfig;
152 public void close() throws Exception {
153 LOG.info("{} close", getClass().getSimpleName());
156 public NeutronvpnConfig getNeutronvpnConfig() {
157 return neutronvpnConfig;
160 // TODO Clean up the exception handling
161 @SuppressWarnings("checkstyle:IllegalCatch")
162 protected void updateSubnetNodeWithFixedIps(Uuid subnetId, Uuid routerId,
163 Uuid routerInterfaceName, String fixedIp,
164 String routerIntfMacAddress) {
165 Subnetmap subnetmap = null;
166 SubnetmapBuilder builder = null;
167 InstanceIdentifier<Subnetmap> id =
168 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
170 synchronized (subnetId.getValue().intern()) {
171 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
172 if (sn.isPresent()) {
173 builder = new SubnetmapBuilder(sn.get());
174 LOG.debug("WithRouterFixedIPs: Updating existing subnetmap node for subnet ID {}",
175 subnetId.getValue());
177 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
178 LOG.debug("WithRouterFixedIPs: creating new subnetmap node for subnet ID {}",
179 subnetId.getValue());
182 builder.setRouterId(routerId);
183 builder.setRouterInterfaceName(routerInterfaceName);
184 builder.setRouterIntfMacAddress(routerIntfMacAddress);
186 if (fixedIp != null) {
187 List<String> fixedIps = builder.getRouterInterfaceFixedIps();
188 if (fixedIps == null) {
189 fixedIps = new ArrayList<>();
191 fixedIps.add(fixedIp);
192 builder.setRouterInterfaceFixedIps(fixedIps);
194 builder.setRouterInterfaceFixedIps(null);
196 subnetmap = builder.build();
197 LOG.debug("WithRouterFixedIPs Creating/Updating subnetMap node for Router FixedIps: {} ",
198 subnetId.getValue());
199 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
201 } catch (Exception e) {
202 LOG.error("WithRouterFixedIPs: Updation of subnetMap for Router FixedIps failed for node: {}",
203 subnetId.getValue());
207 // TODO Clean up the exception handling
208 @SuppressWarnings("checkstyle:IllegalCatch")
209 protected Subnetmap updateSubnetNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId, Uuid routerId,
211 Subnetmap subnetmap = null;
212 SubnetmapBuilder builder = null;
213 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
214 .child(Subnetmap.class, new SubnetmapKey(subnetId))
217 synchronized (subnetId.getValue().intern()) {
218 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
219 if (sn.isPresent()) {
220 builder = new SubnetmapBuilder(sn.get());
221 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
223 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
224 LOG.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
227 if (subnetIp != null) {
228 builder.setSubnetIp(subnetIp);
230 if (routerId != null) {
231 builder.setRouterId(routerId);
233 if (networkId != null) {
234 builder.setNetworkId(networkId);
237 builder.setVpnId(vpnId);
239 if (tenantId != null) {
240 builder.setTenantId(tenantId);
243 subnetmap = builder.build();
244 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
245 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
247 } catch (Exception e) {
248 LOG.error("Updation of subnetMap failed for node: {}", subnetId.getValue());
253 // TODO Clean up the exception handling
254 @SuppressWarnings("checkstyle:IllegalCatch")
255 protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
256 Subnetmap subnetmap = null;
257 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
258 .child(Subnetmap.class, new SubnetmapKey(subnetId))
261 synchronized (subnetId.getValue().intern()) {
262 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
263 if (sn.isPresent()) {
264 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
265 if (routerId != null) {
266 builder.setRouterId(null);
268 if (networkId != null) {
269 builder.setNetworkId(null);
272 builder.setVpnId(null);
274 if (portId != null && builder.getPortList() != null) {
275 List<Uuid> portList = builder.getPortList();
276 portList.remove(portId);
277 builder.setPortList(portList);
280 subnetmap = builder.build();
281 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
282 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
284 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
287 } catch (Exception e) {
288 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
293 // TODO Clean up the exception handling
294 @SuppressWarnings("checkstyle:IllegalCatch")
295 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, Uuid portId, Uuid directPortId) {
296 Subnetmap subnetmap = null;
297 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
298 new SubnetmapKey(subnetId)).build();
300 synchronized (subnetId.getValue().intern()) {
301 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
302 if (sn.isPresent()) {
303 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
304 if (null != portId) {
305 List<Uuid> portList = builder.getPortList();
306 if (null == portList) {
307 portList = new ArrayList<>();
309 portList.add(portId);
310 builder.setPortList(portList);
311 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
314 if (null != directPortId) {
315 List<Uuid> directPortList = builder.getDirectPortList();
316 if (null == directPortList) {
317 directPortList = new ArrayList<>();
319 directPortList.add(directPortId);
320 builder.setDirectPortList(directPortList);
321 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
322 directPortId.getValue());
324 subnetmap = builder.build();
325 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
327 LOG.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
330 } catch (Exception e) {
331 LOG.error("Updating port list of a given subnetMap failed for node: {} with exception{}",
332 subnetId.getValue(), e);
337 // TODO Clean up the exception handling
338 @SuppressWarnings("checkstyle:IllegalCatch")
339 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, Uuid portId, Uuid directPortId) {
340 Subnetmap subnetmap = null;
341 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
342 new SubnetmapKey(subnetId)).build();
344 synchronized (subnetId.getValue().intern()) {
345 Optional<Subnetmap> sn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
346 if (sn.isPresent()) {
347 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
348 if (null != portId && null != builder.getPortList()) {
349 List<Uuid> portList = builder.getPortList();
350 portList.remove(portId);
351 builder.setPortList(portList);
352 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
353 subnetId.getValue());
355 if (null != directPortId && null != builder.getDirectPortList()) {
356 List<Uuid> directPortList = builder.getDirectPortList();
357 directPortList.remove(directPortId);
358 builder.setDirectPortList(directPortList);
359 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
360 .getValue(), subnetId.getValue());
362 subnetmap = builder.build();
363 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
365 LOG.error("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
368 } catch (Exception e) {
369 LOG.error("Removing a port from port list of a subnetmap failed for node: {} with expection {}",
370 subnetId.getValue(), e);
375 // TODO Clean up the exception handling
376 @SuppressWarnings("checkstyle:IllegalCatch")
377 protected void deleteSubnetMapNode(Uuid subnetId) {
378 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
379 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,new SubnetmapKey(subnetId)).build();
380 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
382 synchronized (subnetId.getValue().intern()) {
383 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
385 } catch (Exception e) {
386 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
390 // TODO Clean up the exception handling
391 @SuppressWarnings("checkstyle:IllegalCatch")
392 private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert) {
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);
409 if (irt != null && !irt.isEmpty()) {
410 if (ert != null && !ert.isEmpty()) {
411 List<String> commonRT = new ArrayList<>(irt);
412 commonRT.retainAll(ert);
414 for (String common : commonRT) {
417 VpnTarget vpnTarget =
418 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
419 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
420 vpnTargetList.add(vpnTarget);
423 for (String importRT : irt) {
424 VpnTarget vpnTarget =
425 new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
426 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
427 vpnTargetList.add(vpnTarget);
431 if (ert != null && !ert.isEmpty()) {
432 for (String exportRT : ert) {
433 VpnTarget vpnTarget =
434 new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
435 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
436 vpnTargetList.add(vpnTarget);
440 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
442 Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
444 if (rd != null && !rd.isEmpty()) {
445 ipv4vpnBuilder.setRouteDistinguisher(rd.get(0));
448 VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
449 isLockAcquired = NeutronvpnUtils.lock(vpnName);
450 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
451 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
452 } catch (Exception e) {
453 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
455 if (isLockAcquired) {
456 NeutronvpnUtils.unlock(vpnName);
461 // TODO Clean up the exception handling
462 @SuppressWarnings("checkstyle:IllegalCatch")
463 private void deleteVpnMapsNode(Uuid vpnid) {
464 boolean isLockAcquired = false;
465 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
466 .child(VpnMap.class, new VpnMapKey(vpnid))
468 LOG.debug("removing vpnMaps node: {} ", vpnid.getValue());
470 isLockAcquired = NeutronvpnUtils.lock(vpnid.getValue());
471 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
472 } catch (Exception e) {
473 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnid.getValue());
475 if (isLockAcquired) {
476 NeutronvpnUtils.unlock(vpnid.getValue());
481 // TODO Clean up the exception handling
482 @SuppressWarnings("checkstyle:IllegalCatch")
483 private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
484 VpnMapBuilder builder;
485 boolean isLockAcquired = false;
486 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
487 .child(VpnMap.class, new VpnMapKey(vpnId))
490 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
492 if (optionalVpnMap.isPresent()) {
493 builder = new VpnMapBuilder(optionalVpnMap.get());
495 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
499 builder.setName(name);
501 if (tenantId != null) {
502 builder.setTenantId(tenantId);
504 if (router != null) {
505 builder.setRouterId(router);
507 if (networks != null) {
508 List<Uuid> nwList = builder.getNetworkIds();
509 if (nwList == null) {
510 nwList = new ArrayList<>();
512 nwList.addAll(networks);
513 builder.setNetworkIds(nwList);
516 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
517 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
518 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
519 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
520 } catch (Exception e) {
521 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
523 if (isLockAcquired) {
524 NeutronvpnUtils.unlock(vpnId.getValue());
529 // TODO Clean up the exception handling
530 @SuppressWarnings("checkstyle:IllegalCatch")
531 private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
532 boolean isLockAcquired = false;
533 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
534 .child(VpnMap.class, new VpnMapKey(vpnId))
536 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
538 if (optionalVpnMap.isPresent()) {
539 VpnMap vpnMap = optionalVpnMap.get();
540 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
541 if (routerId != null) {
542 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
544 // remove entire node in case of internal VPN
545 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
546 LOG.debug("removing vpnMaps node: {} ", vpnId);
547 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
548 } catch (Exception e) {
549 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
551 if (isLockAcquired) {
552 NeutronvpnUtils.unlock(vpnId.getValue());
557 vpnMapBuilder.setRouterId(null);
559 if (networkIds != null) {
560 List<Uuid> vpnNw = vpnMap.getNetworkIds();
561 for (Uuid nw : networkIds) {
564 if (vpnNw.isEmpty()) {
565 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
566 vpnMapBuilder.setNetworkIds(null);
568 vpnMapBuilder.setNetworkIds(vpnNw);
573 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
574 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
575 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
576 vpnMapBuilder.build());
577 } catch (Exception e) {
578 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
580 if (isLockAcquired) {
581 NeutronvpnUtils.unlock(vpnId.getValue());
585 LOG.error("VPN : {} not found", vpnId.getValue());
587 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
590 // TODO Clean up the exception handling
591 @SuppressWarnings("checkstyle:IllegalCatch")
592 private void deleteVpnInstance(Uuid vpnId) {
593 boolean isLockAcquired = false;
594 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
595 .child(VpnInstance.class,
596 new VpnInstanceKey(vpnId.getValue()))
599 isLockAcquired = NeutronvpnUtils.lock(vpnId.getValue());
600 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
601 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
602 } catch (Exception e) {
603 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
605 if (isLockAcquired) {
606 NeutronvpnUtils.unlock(vpnId.getValue());
611 protected void createVpnInterface(Uuid vpnId, Uuid routerId, Port port,
612 WriteTransaction wrtConfigTxn) {
613 String infName = port.getUuid().getValue();
614 List<Adjacency> adjList = new ArrayList<>();
615 Boolean isRouterInterface = false;
616 if (port.getDeviceOwner() != null) {
617 isRouterInterface = port.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF);
619 LOG.trace("createVpnInterface - isRouterInterface:{}", isRouterInterface);
621 if (routerId != null) {
622 rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
624 List<FixedIps> ips = port.getFixedIps();
625 // create adjacency list
626 for (FixedIps ip : ips) {
627 // create vm adjacency
628 String ipValue = String.valueOf(ip.getIpAddress().getValue());
629 String ipPrefix = (ip.getIpAddress().getIpv4Address() != null) ? ipValue + "/32" : ipValue + "/128";
630 Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
631 .setMacAddress(port.getMacAddress().getValue()).setPrimaryAdjacency(true)
632 .setSubnetId(ip.getSubnetId()).build();
634 // create extra route adjacency
635 if (rtr != null && rtr.getRoutes() != null) {
636 List<Routes> routeList = rtr.getRoutes();
637 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(vpnId, routeList, ipValue);
638 if (erAdjList != null && !erAdjList.isEmpty()) {
639 adjList.addAll(erAdjList);
642 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
643 .getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
645 // create vpn-interface on this neutron port
646 Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
647 writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
648 if (routerId != null) {
649 addToNeutronRouterInterfacesMap(routerId, infName);
653 // TODO Clean up the exception handling
654 @SuppressWarnings("checkstyle:IllegalCatch")
655 protected void deleteVpnInterface(Uuid vpnId, Uuid routerId, Port port, WriteTransaction wrtConfigTxn) {
656 Boolean wrtConfigTxnPresent = true;
657 if (wrtConfigTxn == null) {
658 wrtConfigTxnPresent = false;
659 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
661 String infName = port.getUuid().getValue();
662 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
664 LOG.debug("Deleting vpn interface {}", infName);
665 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
667 List<FixedIps> ips = port.getFixedIps();
668 for (FixedIps ip : ips) {
669 String ipValue = String.valueOf(ip.getIpAddress().getValue());
670 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, vpnId.getValue(),
671 ipValue, wrtConfigTxn);
673 } catch (Exception ex) {
674 LOG.error("Deletion of vpninterface {} failed due to {}", infName, ex);
676 if (routerId != null) {
677 removeFromNeutronRouterInterfacesMap(routerId, infName);
679 if (!wrtConfigTxnPresent) {
680 wrtConfigTxn.submit();
684 // TODO Clean up the exception handling
685 @SuppressWarnings("checkstyle:IllegalCatch")
686 protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
687 boolean isSubnetIp) {
688 if (vpnId == null || port == null) {
691 boolean isLockAcquired = false;
692 String infName = port.getUuid().getValue();
693 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
696 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
697 isLockAcquired = NeutronvpnUtils.lock(infName);
698 Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
699 .CONFIGURATION, vpnIfIdentifier);
700 if (optionalVpnInterface.isPresent()) {
701 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
702 .setVpnInstanceName(vpnId.getValue());
703 LOG.debug("Updating vpn interface {}", infName);
704 if (!isBeingAssociated) {
705 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
706 List<Adjacency> adjacencyList = (adjs != null) ? adjs.getAdjacency() : new ArrayList<>();
707 Iterator<Adjacency> adjacencyIter = adjacencyList.iterator();
708 while (adjacencyIter.hasNext()) {
709 Adjacency adjacency = adjacencyIter.next();
710 String mipToQuery = adjacency.getIpAddress().split("/")[0];
711 InstanceIdentifier<LearntVpnVipToPort> id =
712 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
713 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
714 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
715 if (optionalVpnVipToPort.isPresent()) {
716 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
717 + "from VPN " + "{}", infName, vpnId, oldVpnId);
718 adjacencyIter.remove();
719 NeutronvpnUtils.removeLearntVpnVipToPort(dataBroker, oldVpnId.getValue(), mipToQuery);
720 LOG.trace("Entry for fixedIP {} for port {} on VPN removed from "
721 + "VpnPortFixedIPToPortData", mipToQuery, infName, vpnId.getValue());
724 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
725 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
727 List<FixedIps> ips = port.getFixedIps();
728 for (FixedIps ip : ips) {
729 String ipValue = String.valueOf(ip.getIpAddress().getValue());
730 if (oldVpnId != null) {
731 NeutronvpnUtils.removeVpnPortFixedIpToPort(dataBroker, oldVpnId.getValue(),
732 ipValue, writeConfigTxn);
734 NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
735 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
737 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
739 writeConfigTxn.submit();
741 LOG.error("VPN Interface {} not found", infName);
743 } catch (Exception ex) {
744 LOG.error("Updation of vpninterface {} failed due to {}", infName, ex);
746 if (isLockAcquired) {
747 NeutronvpnUtils.unlock(infName);
752 public void createL3InternalVpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt,
753 List<String> ert, Uuid router, List<Uuid> networks) {
755 // Update VPN Instance node
756 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
758 // Update local vpn-subnet DS
759 updateVpnMaps(vpn, name, router, tenant, networks);
761 if (router != null) {
762 Uuid existingVpn = NeutronvpnUtils.getVpnForRouter(dataBroker, router, true);
763 if (existingVpn != null) {
764 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
766 // if before reboot, router was already associated to VPN, should not proceed associating router to
767 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
768 // preserved upon reboot.
769 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
770 // RouterInterfacesMap via #createVPNInterface call.
771 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
772 + "to external VPN {}", vpn.getValue(), router.getValue(), existingVpn.getValue());
775 associateRouterToInternalVpn(vpn, router);
780 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
781 * specified Neutron Networks and Routers.
783 * @param vpn Uuid of the VPN tp be created
784 * @param name Representative name of the new VPN
785 * @param tenant Uuid of the Tenant under which the VPN is going to be created
786 * @param rd Route-distinguisher for the VPN
787 * @param irt A list of Import Route Targets
788 * @param ert A list of Export Route Targets
789 * @param router UUID of the neutron router the VPN may be associated to
790 * @param networks UUID of the neutron network the VPN may be associated to
791 * @throws Exception if association of L3VPN failed
793 public void createL3Vpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
794 Uuid router, List<Uuid> networks) throws Exception {
796 // Update VPN Instance node
797 updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
799 // Please note that router and networks will be filled into VPNMaps
800 // by subsequent calls here to associateRouterToVpn and
801 // associateNetworksToVpn
802 updateVpnMaps(vpn, name, null, tenant, null);
804 if (router != null) {
805 associateRouterToVpn(vpn, router);
807 if (networks != null) {
808 List<String> failStrings = associateNetworksToVpn(vpn, networks);
809 if (failStrings != null && !failStrings.isEmpty()) {
810 LOG.error("L3VPN {} association to networks failed with error message {}. ",
811 vpn.getValue(), failStrings.get(0));
812 throw new Exception(failStrings.get(0));
818 * It handles the invocations to the createL3VPN RPC method.
821 // TODO Clean up the exception handling
822 @SuppressWarnings("checkstyle:IllegalCatch")
823 public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
825 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
826 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
827 List<RpcError> errorList = new ArrayList<>();
828 int failurecount = 0;
829 int warningcount = 0;
831 List<L3vpn> vpns = input.getL3vpn();
832 for (L3vpn vpn : vpns) {
833 List<String> existingRDs = NeutronvpnUtils.getExistingRDs(dataBroker);
834 RpcError error = null;
836 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
837 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
838 vpn.getId().getValue());
840 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
841 errorList.add(error);
845 if (vpn.getRouteDistinguisher().size() > 1) {
846 msg = String.format("Creation of L3VPN failed for VPN %s due to multiple RD input %s",
847 vpn.getId().getValue(), vpn.getRouteDistinguisher());
849 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
850 errorList.add(error);
854 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
855 msg = String.format("Creation of L3VPN failed for VPN %s as another VPN with the same RD %s "
856 + "is already configured",
857 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0));
859 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
860 errorList.add(error);
864 if (vpn.getRouterId() != null) {
865 if (NeutronvpnUtils.getNeutronRouter(dataBroker, vpn.getRouterId()) == null) {
866 msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
867 vpn.getId().getValue(), vpn.getRouterId().getValue());
869 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
870 errorList.add(error);
874 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, vpn.getRouterId(), true);
876 msg = String.format("Creation of L3VPN failed for VPN %s due to router %s already associated to "
877 + "another VPN %s", vpn.getId().getValue(), vpn.getRouterId().getValue(),
880 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
881 errorList.add(error);
886 if (vpn.getNetworkIds() != null) {
887 for (Uuid nw : vpn.getNetworkIds()) {
888 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
889 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
890 if (network == null) {
891 msg = String.format("Creation of L3VPN failed for VPN %s due to network not found %s",
892 vpn.getId().getValue(), nw.getValue());
894 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
895 errorList.add(error);
897 } else if (vpnId != null) {
898 msg = String.format("Creation of L3VPN failed for VPN %s due to network %s already associated"
899 + " to another VPN %s", vpn.getId().getValue(), nw.getValue(),
902 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
903 errorList.add(error);
912 createL3Vpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
913 vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds());
914 } catch (Exception ex) {
915 msg = String.format("Creation of L3VPN failed for VPN %s", vpn.getId().getValue());
917 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
918 errorList.add(error);
922 // if at least one succeeds; result is success
923 // if none succeeds; result is failure
924 if (failurecount + warningcount == vpns.size()) {
925 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
927 List<String> errorResponseList = new ArrayList<>();
928 if (!errorList.isEmpty()) {
929 for (RpcError rpcError : errorList) {
930 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
931 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
932 errorResponseList.add(errorResponse);
935 errorResponseList.add("Operation successful with no errors");
937 opBuilder.setResponse(errorResponseList);
938 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
944 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
947 // TODO Clean up the exception handling
948 @SuppressWarnings("checkstyle:IllegalCatch")
949 public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
951 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
952 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
953 Uuid inputVpnId = input.getId();
954 List<VpnInstance> vpns = new ArrayList<>();
957 if (inputVpnId == null) {
959 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
961 Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
962 .CONFIGURATION, vpnsIdentifier);
963 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
964 for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
965 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
966 // from getL3VPN output
967 if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
973 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
977 String name = inputVpnId.getValue();
978 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
979 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
980 // read VpnInstance Info
981 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
983 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
985 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
986 vpns.add(optionalVpn.get());
988 String message = String.format("GetL3VPN failed because VPN %s is not present", name);
990 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL,
991 "invalid-value", message).build());
994 List<L3vpnInstances> l3vpnList = new ArrayList<>();
995 for (VpnInstance vpnInstance : vpns) {
996 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
998 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
999 .class, new VpnMapKey(vpnId)).build();
1000 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1002 List<String> rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(","));
1003 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
1005 List<String> ertList = new ArrayList<>();
1006 List<String> irtList = new ArrayList<>();
1008 for (VpnTarget vpnTarget : vpnTargetList) {
1009 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1010 ertList.add(vpnTarget.getVrfRTValue());
1012 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1013 irtList.add(vpnTarget.getVrfRTValue());
1015 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1016 ertList.add(vpnTarget.getVrfRTValue());
1017 irtList.add(vpnTarget.getVrfRTValue());
1021 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1022 Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1024 if (optionalVpnMap.isPresent()) {
1025 VpnMap vpnMap = optionalVpnMap.get();
1026 l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1027 .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1029 l3vpnList.add(l3vpn.build());
1032 opBuilder.setL3vpnInstances(l3vpnList);
1033 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1035 } catch (Exception ex) {
1036 String message = String.format("GetL3VPN failed due to %s", ex.getMessage());
1037 LOG.error(message, ex);
1038 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
1044 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1047 // TODO Clean up the exception handling
1048 @SuppressWarnings("checkstyle:IllegalCatch")
1049 public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1051 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1052 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1053 List<RpcError> errorList = new ArrayList<>();
1055 int failurecount = 0;
1056 int warningcount = 0;
1057 List<Uuid> vpns = input.getId();
1058 for (Uuid vpn : vpns) {
1062 InstanceIdentifier<VpnInstance> vpnIdentifier =
1063 InstanceIdentifier.builder(VpnInstances.class)
1064 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1065 Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1066 .CONFIGURATION, vpnIdentifier);
1067 if (optionalVpn.isPresent()) {
1070 msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
1072 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
1073 errorList.add(error);
1076 } catch (Exception ex) {
1077 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
1079 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1080 errorList.add(error);
1084 // if at least one succeeds; result is success
1085 // if none succeeds; result is failure
1086 if (failurecount + warningcount == vpns.size()) {
1087 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1089 List<String> errorResponseList = new ArrayList<>();
1090 if (!errorList.isEmpty()) {
1091 for (RpcError rpcError : errorList) {
1092 String errorResponse = String.format("ErrorType: %s, ErrorTag: %s, ErrorMessage: %s", rpcError
1093 .getErrorType(), rpcError.getTag(), rpcError.getMessage());
1094 errorResponseList.add(errorResponse);
1097 errorResponseList.add("Operation successful with no errors");
1099 opBuilder.setResponse(errorResponseList);
1100 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1105 protected void addSubnetToVpn(final Uuid vpnId, Uuid subnet) {
1106 LOG.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
1107 Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1108 final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1109 // Check if there are ports on this subnet and add corresponding
1111 List<Uuid> portList = sn.getPortList();
1112 if (portList != null) {
1113 for (final Uuid portId : sn.getPortList()) {
1114 LOG.debug("adding vpn-interface for port {}", portId.getValue());
1115 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1116 portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1117 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1118 List<ListenableFuture<Void>> futures = new ArrayList<>();
1119 createVpnInterface(vpnId, routerId, NeutronvpnUtils.getNeutronPort(dataBroker, portId),
1121 futures.add(wrtConfigTxn.submit());
1128 protected void updateVpnForSubnet(Uuid vpnId, Uuid subnet, boolean isBeingAssociated) {
1129 LOG.debug("Updating VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
1130 // Read the subnet first to see if its already associated to a VPN
1131 Uuid oldVpnId = null;
1132 InstanceIdentifier<Subnetmap> snId = InstanceIdentifier.builder(Subnetmaps.class)
1133 .child(Subnetmap.class, new SubnetmapKey(subnet)).build();
1134 Subnetmap sn = null;
1135 Optional<Subnetmap> optSn = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, snId);
1136 if (optSn.isPresent()) {
1138 oldVpnId = sn.getVpnId();
1139 List<String> ips = sn.getRouterInterfaceFixedIps();
1140 for (String ipValue : ips) {
1141 // Update the association of router-interface to external vpn
1143 NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, oldVpnId.getValue(), ipValue);
1144 if (portName != null) {
1145 updateVpnInterface(vpnId, oldVpnId,
1146 NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(portName)),
1147 isBeingAssociated, true);
1151 sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
1152 // Check for ports on this subnet and update association of
1153 // corresponding vpn-interfaces to external vpn
1154 List<Uuid> portList = sn.getPortList();
1155 if (portList != null) {
1156 for (Uuid port : sn.getPortList()) {
1157 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1158 port.getValue(), isBeingAssociated);
1159 updateVpnInterface(vpnId, oldVpnId, NeutronvpnUtils.getNeutronPort(dataBroker, port),
1160 isBeingAssociated, false);
1165 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1166 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1167 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1170 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1171 synchronized (routerId.getValue().intern()) {
1172 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1173 Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1174 .CONFIGURATION, routerInterfacesId);
1175 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1176 .setInterfaceId(interfaceName).build();
1177 if (optRouterInterfaces.isPresent()) {
1178 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1179 .class, new InterfacesKey(interfaceName)), routerInterface);
1181 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1182 List<Interfaces> interfaces = new ArrayList<>();
1183 interfaces.add(routerInterface);
1184 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces
1185 .class, new InterfacesKey(interfaceName)), routerInterface);
1190 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1191 synchronized (routerId.getValue().intern()) {
1192 InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1193 Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
1194 .CONFIGURATION, routerInterfacesId);
1195 Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName))
1196 .setInterfaceId(interfaceName).build();
1197 if (optRouterInterfaces.isPresent()) {
1198 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1199 List<Interfaces> interfaces = routerInterfaces.getInterfaces();
1200 if (interfaces != null && interfaces.remove(routerInterface)) {
1201 if (interfaces.isEmpty()) {
1202 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1204 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1205 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1213 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1214 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1215 * route will be ignored.
1217 * @param vpnName the VPN identifier
1218 * @param interVpnLinkRoutes The list of static routes
1219 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1221 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1222 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1223 for ( Routes route : interVpnLinkRoutes ) {
1224 String nexthop = String.valueOf(route.getNexthop().getValue());
1225 String destination = String.valueOf(route.getDestination().getValue());
1226 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1227 if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
1228 AddStaticRouteInput rpcInput =
1229 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1230 .setVpnInstanceName(vpnName.getValue())
1232 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1233 RpcResult<AddStaticRouteOutput> rpcResult;
1235 rpcResult = labelOuputFtr.get();
1236 if ( rpcResult.isSuccessful() ) {
1237 LOG.debug("Label generated for destination {} is: {}",
1238 destination, rpcResult.getResult().getLabel());
1240 LOG.warn("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1241 destination, nexthop, rpcResult.getErrors());
1243 } catch (InterruptedException | ExecutionException e) {
1244 LOG.warn("Error happened while invoking addStaticRoute RPC: ", e);
1247 // Any other case is a fault.
1248 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1249 String.valueOf(route.getDestination().getValue()), nexthop );
1256 * Removes the corresponding static routes from the specified VPN. These static routes point to an
1257 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
1259 * @param vpnName the VPN identifier
1260 * @param interVpnLinkRoutes The list of static routes
1261 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1263 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1264 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1265 for ( Routes route : interVpnLinkRoutes ) {
1266 String nexthop = String.valueOf(route.getNexthop().getValue());
1267 String destination = String.valueOf(route.getDestination().getValue());
1268 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1269 if ( isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink) ) {
1270 RemoveStaticRouteInput rpcInput =
1271 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1272 .setVpnInstanceName(vpnName.getValue())
1274 vpnRpcService.removeStaticRoute(rpcInput);
1276 // Any other case is a fault.
1277 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
1278 String.valueOf(route.getDestination().getValue()), nexthop );
1285 * Returns true if the specified nexthop is the other endpoint in an
1286 * InterVpnLink, regarding one of the VPN's point of view.
1288 private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1290 interVpnLink != null
1291 && ( (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
1292 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop))
1293 || (interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid )
1294 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop)) );
1297 protected List<Adjacency> getAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList, String fixedIp) {
1298 List<Adjacency> adjList = new ArrayList<>();
1299 Map<String, List<String>> adjMap = new HashMap<>();
1300 for (Routes route : routeList) {
1301 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1302 LOG.error("Incorrect input received for extra route. {}", route);
1304 String nextHop = String.valueOf(route.getNexthop().getValue());
1305 String destination = String.valueOf(route.getDestination().getValue());
1306 if (!nextHop.equals(fixedIp)) {
1307 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
1310 LOG.trace("Adding extra route for destination {} onto vpn {} with nexthop {} ", destination,
1311 vpnId.getValue(), nextHop);
1312 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
1313 if (!hops.contains(nextHop)) {
1319 for (String destination : adjMap.keySet()) {
1320 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1321 .setNextHopIpList(adjMap.get(destination)).setKey(new AdjacencyKey(destination)).build();
1327 // TODO Clean up the exception handling
1328 @SuppressWarnings("checkstyle:IllegalCatch")
1329 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
1330 for (Routes route : routeList) {
1331 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
1332 LOG.error("Incorrect input received for extra route. {}", route);
1334 String nextHop = String.valueOf(route.getNexthop().getValue());
1335 String destination = String.valueOf(route.getDestination().getValue());
1336 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1338 if (infName != null) {
1339 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
1340 destination, vpnId.getValue(), nextHop, infName);
1341 boolean isLockAcquired = false;
1343 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
1344 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1345 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
1346 .child(Adjacency.class, new AdjacencyKey(destination));
1347 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
1348 .setNextHopIpList(Arrays.asList(nextHop)).setKey(new AdjacencyKey(destination)).build();
1349 isLockAcquired = NeutronvpnUtils.lock(infName);
1350 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, erAdj);
1351 } catch (Exception e) {
1352 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
1353 destination, nextHop, e);
1355 if (isLockAcquired) {
1356 NeutronvpnUtils.unlock(infName);
1360 LOG.debug("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1361 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1367 // TODO Clean up the exception handling
1368 @SuppressWarnings("checkstyle:IllegalCatch")
1369 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
1370 for (Routes route : routeList) {
1371 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
1372 boolean isLockAcquired = false;
1373 String nextHop = String.valueOf(route.getNexthop().getValue());
1374 String destination = String.valueOf(route.getDestination().getValue());
1375 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1377 if (infName == null) {
1378 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
1379 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1380 // Proceed to remove the next extra-route
1383 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
1384 destination, vpnId.getValue(), nextHop, infName);
1386 InstanceIdentifier<Adjacency> adjacencyIdentifier =
1387 InstanceIdentifier.builder(VpnInterfaces.class)
1388 .child(VpnInterface.class, new VpnInterfaceKey(infName))
1389 .augmentation(Adjacencies.class)
1390 .child(Adjacency.class, new AdjacencyKey(destination))
1393 // Looking for existing prefix in MDSAL database
1394 Optional<Adjacency> adjacency = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1395 adjacencyIdentifier);
1396 boolean updateNextHops = false;
1397 List<String> nextHopList = new ArrayList<>();
1398 if (adjacency.isPresent()) {
1399 List<String> nhListRead = adjacency.get().getNextHopIpList();
1400 if (nhListRead.size() > 1) { // ECMP case
1401 for (String nextHopRead : nhListRead) {
1402 if (nextHopRead.equals(nextHop)) {
1403 updateNextHops = true;
1405 nextHopList.add(nextHopRead);
1412 isLockAcquired = NeutronvpnUtils.lock(infName);
1413 if (updateNextHops) {
1414 // An update must be done, not including the current next hop
1415 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
1416 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
1417 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
1418 .setNextHopIpList(nextHopList)
1419 .setKey(new AdjacencyKey(destination))
1421 Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(newAdj)).build();
1422 VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
1423 .addAugmentation(Adjacencies.class, erAdjs).build();
1424 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
1426 // Remove the whole route
1427 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1428 LOG.trace("extra route {} deleted successfully", route);
1430 } catch (Exception e) {
1431 LOG.error("exception in deleting extra route: {}" + e);
1433 if (isLockAcquired) {
1434 NeutronvpnUtils.unlock(infName);
1438 LOG.error("Incorrect input received for extra route. {}", route);
1443 protected void removeL3Vpn(Uuid id) {
1445 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, id);
1446 Uuid router = (vpnMap != null) ? vpnMap.getRouterId() : null;
1447 // dissociate router
1448 if (router != null) {
1449 dissociateRouterFromVpn(id, router);
1451 // dissociate networks
1452 if (!id.equals(router)) {
1453 dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
1455 // remove entire vpnMaps node
1456 deleteVpnMapsNode(id);
1458 // remove vpn-instance
1459 deleteVpnInstance(id);
1462 protected void removeSubnetFromVpn(final Uuid vpnId, Uuid subnet) {
1463 LOG.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
1464 final Uuid routerId = NeutronvpnUtils.getVpnMap(dataBroker, vpnId).getRouterId();
1465 Subnetmap sn = NeutronvpnUtils.getSubnetmap(dataBroker, subnet);
1467 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1468 List<Uuid> portList = sn.getPortList();
1469 if (portList != null) {
1470 for (final Uuid portId : sn.getPortList()) {
1471 LOG.debug("removing vpn-interface for port {}", portId.getValue());
1472 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1473 portDataStoreCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1474 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
1475 List<ListenableFuture<Void>> futures = new ArrayList<>();
1476 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1478 deleteVpnInterface(vpnId, routerId, port, wrtConfigTxn);
1480 LOG.error("Cannot proceed with deleteVpnInterface for port {} in subnet {} since port is "
1481 + "absent in Neutron config DS", portId.getValue(), subnet.getValue());
1483 futures.add(wrtConfigTxn.submit());
1488 // update subnet-vpn association
1489 removeFromSubnetNode(subnet, null, null, vpnId, null);
1491 LOG.warn("Subnetmap for subnet {} not found", subnet.getValue());
1495 // TODO Clean up the exception handling
1496 @SuppressWarnings("checkstyle:IllegalCatch")
1497 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
1498 updateVpnMaps(vpnId, null, routerId, null, null);
1499 LOG.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
1500 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1501 if (routerSubnets != null) {
1502 for (Uuid subnetId : routerSubnets) {
1503 updateVpnForSubnet(vpnId, subnetId, true);
1507 checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
1508 LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
1510 } catch (Exception e) {
1511 LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
1512 .getValue(), vpnId.getValue(), e);
1516 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
1517 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1518 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
1519 for (Uuid subnet : routerSubnets) {
1520 addSubnetToVpn(vpnId, subnet);
1524 // TODO Clean up the exception handling
1525 @SuppressWarnings("checkstyle:IllegalCatch")
1526 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
1528 List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(dataBroker, routerId);
1529 if (routerSubnets != null) {
1530 for (Uuid subnetId : routerSubnets) {
1531 LOG.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
1532 updateVpnForSubnet(routerId, subnetId, false);
1535 clearFromVpnMaps(vpnId, routerId, null);
1537 checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
1538 LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
1540 } catch (Exception e) {
1541 LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
1542 .getValue(), vpnId.getValue(), e);
1546 protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
1547 List<String> failedNwList = new ArrayList<>();
1548 List<Uuid> passedNwList = new ArrayList<>();
1549 if (!networks.isEmpty()) {
1550 // process corresponding subnets for VPN
1551 for (Uuid nw : networks) {
1552 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1553 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1554 if (network == null) {
1555 failedNwList.add(String.format("network %s not found", nw.getValue()));
1556 } else if (vpnId != null) {
1557 failedNwList.add(String.format("network %s already associated to another VPN %s", nw.getValue(),
1560 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1561 LOG.debug("Adding network subnets...{}", networkSubnets);
1562 if (networkSubnets != null) {
1563 for (Uuid subnet : networkSubnets) {
1564 // check if subnet added as router interface to some router
1565 Uuid subnetVpnId = NeutronvpnUtils.getVpnForSubnet(dataBroker, subnet);
1566 if (subnetVpnId == null) {
1567 addSubnetToVpn(vpn, subnet);
1568 passedNwList.add(nw);
1570 failedNwList.add(String.format("subnet %s already added as router interface bound to "
1571 + "internal/external VPN %s", subnet.getValue(), subnetVpnId.getValue()));
1575 if (NeutronvpnUtils.getIsExternal(network)) {
1576 nvpnNatManager.addExternalNetworkToVpn(network, vpn);
1580 updateVpnMaps(vpn, null, null, null, passedNwList);
1582 return failedNwList;
1585 protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
1586 List<String> failedNwList = new ArrayList<>();
1587 List<Uuid> passedNwList = new ArrayList<>();
1588 if (networks != null && !networks.isEmpty()) {
1589 // process corresponding subnets for VPN
1590 for (Uuid nw : networks) {
1591 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, nw);
1592 if (network == null) {
1593 failedNwList.add(String.format("network %s not found", nw.getValue()));
1595 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, nw);
1596 if (vpn.equals(vpnId)) {
1597 List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(dataBroker, nw);
1598 LOG.debug("Removing network subnets...");
1599 if (networkSubnets != null) {
1600 for (Uuid subnet : networkSubnets) {
1601 removeSubnetFromVpn(vpn, subnet);
1602 passedNwList.add(nw);
1606 if (vpnId == null) {
1607 failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
1610 failedNwList.add(String.format("input network %s associated to a another vpn %s instead "
1611 + "of the one given as input", nw.getValue(), vpnId.getValue()));
1614 if (NeutronvpnUtils.getIsExternal(network)) {
1615 nvpnNatManager.removeExternalNetworkFromVpn(network);
1619 clearFromVpnMaps(vpn, null, passedNwList);
1621 return failedNwList;
1625 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
1628 // TODO Clean up the exception handling
1629 @SuppressWarnings("checkstyle:IllegalCatch")
1630 public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1632 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
1633 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
1634 LOG.debug("associateNetworks {}", input);
1635 StringBuilder returnMsg = new StringBuilder();
1636 Uuid vpnId = input.getVpnId();
1639 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1640 List<Uuid> netIds = input.getNetworkId();
1641 if (netIds != null && !netIds.isEmpty()) {
1642 List<String> failed = associateNetworksToVpn(vpnId, netIds);
1643 if (!failed.isEmpty()) {
1644 returnMsg.append(failed);
1648 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1650 if (returnMsg.length() != 0) {
1651 String message = String.format("associate Networks to vpn %s failed due to %s",
1652 vpnId.getValue(), returnMsg);
1654 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
1656 opBuilder.setResponse(errorResponse);
1657 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
1659 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
1661 } catch (Exception ex) {
1662 String message = String.format("associate Networks to vpn %s failed due to %s",
1663 input.getVpnId().getValue(), ex.getMessage());
1664 LOG.error(message, ex);
1665 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1668 LOG.debug("associateNetworks returns..");
1673 * It handles the invocations to the neutronvpn:associateRouter RPC method.
1676 // TODO Clean up the exception handling
1677 @SuppressWarnings("checkstyle:IllegalCatch")
1678 public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1680 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1681 LOG.debug("associateRouter {}", input);
1682 StringBuilder returnMsg = new StringBuilder();
1683 Uuid vpnId = input.getVpnId();
1684 Uuid routerId = input.getRouterId();
1686 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1687 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1688 if (vpnMap != null) {
1690 Uuid extVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1691 if (vpnMap.getRouterId() != null) {
1692 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
1693 .append(vpnMap.getRouterId().getValue());
1694 } else if (extVpnId != null) {
1695 returnMsg.append("router ").append(routerId.getValue()).append(" already associated to "
1696 + "another VPN ").append(extVpnId.getValue());
1698 associateRouterToVpn(vpnId, routerId);
1701 returnMsg.append("router not found : ").append(routerId.getValue());
1704 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1706 if (returnMsg.length() != 0) {
1707 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1710 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1713 result.set(RpcResultBuilder.<Void>success().build());
1715 } catch (Exception ex) {
1716 String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
1717 vpnId.getValue(), ex.getMessage());
1718 LOG.error(message, ex);
1719 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1721 LOG.debug("associateRouter returns..");
1725 /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
1728 // TODO Clean up the exception handling
1729 @SuppressWarnings("checkstyle:IllegalCatch")
1730 public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
1731 GetFixedIPsForNeutronPortInput input) {
1732 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
1733 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
1734 Uuid portId = input.getPortId();
1735 StringBuilder returnMsg = new StringBuilder();
1737 List<String> fixedIPList = new ArrayList<>();
1738 Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1740 List<FixedIps> fixedIPs = port.getFixedIps();
1741 for (FixedIps ip : fixedIPs) {
1742 fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
1745 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
1747 if (returnMsg.length() != 0) {
1748 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
1750 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1751 .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
1753 opBuilder.setFixedIPs(fixedIPList);
1754 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
1756 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
1758 } catch (Exception ex) {
1759 String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s",
1760 portId.getValue(), ex.getMessage());
1761 LOG.error(message, ex);
1762 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1763 .withError(ErrorType.APPLICATION, message).build());
1769 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
1772 // TODO Clean up the exception handling
1773 @SuppressWarnings("checkstyle:IllegalCatch")
1774 public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
1776 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
1777 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
1779 LOG.debug("dissociateNetworks {}", input);
1780 StringBuilder returnMsg = new StringBuilder();
1781 Uuid vpnId = input.getVpnId();
1784 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1785 List<Uuid> netIds = input.getNetworkId();
1786 if (netIds != null && !netIds.isEmpty()) {
1787 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
1788 if (!failed.isEmpty()) {
1789 returnMsg.append(failed);
1793 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1795 if (returnMsg.length() != 0) {
1796 String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
1799 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1801 opBuilder.setResponse(errorResponse);
1802 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
1804 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
1806 } catch (Exception ex) {
1807 String message = String.format("dissociate Networks to vpn %s failed due to %s",
1808 input.getVpnId().getValue(), ex.getMessage());
1809 LOG.error(message, ex);
1810 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1813 LOG.debug("dissociateNetworks returns..");
1818 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
1821 // TODO Clean up the exception handling
1822 @SuppressWarnings("checkstyle:IllegalCatch")
1823 public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
1825 SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1827 LOG.debug("dissociateRouter {}", input);
1828 StringBuilder returnMsg = new StringBuilder();
1829 Uuid vpnId = input.getVpnId();
1830 Uuid routerId = input.getRouterId();
1832 if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
1833 if (routerId != null) {
1834 Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1836 Uuid routerVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1837 if (vpnId.equals(routerVpnId)) {
1838 dissociateRouterFromVpn(vpnId, routerId);
1840 if (routerVpnId == null) {
1841 returnMsg.append("input router ").append(routerId.getValue())
1842 .append(" not associated to any vpn yet");
1844 returnMsg.append("input router ").append(routerId.getValue())
1845 .append(" associated to vpn ")
1846 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
1850 returnMsg.append("router not found : ").append(routerId.getValue());
1854 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1856 if (returnMsg.length() != 0) {
1857 String message = String.format("dissociate router %s to vpn %s failed due to %s", routerId.getValue(),
1858 vpnId.getValue(), returnMsg);
1860 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
1862 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1865 result.set(RpcResultBuilder.<Void>success().build());
1867 } catch (Exception ex) {
1868 String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
1869 vpnId.getValue(), ex.getMessage());
1870 LOG.error(message, ex);
1871 result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1873 LOG.debug("dissociateRouter returns..");
1878 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
1879 // check if the router is associated to some VPN
1880 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
1881 if (vpnId != null) {
1882 // remove existing external vpn interfaces
1883 for (Uuid subnetId : routerSubnetIds) {
1884 removeSubnetFromVpn(vpnId, subnetId);
1886 clearFromVpnMaps(vpnId, routerId, null);
1888 // remove existing internal vpn interfaces
1889 for (Uuid subnetId : routerSubnetIds) {
1890 removeSubnetFromVpn(routerId, subnetId);
1893 // delete entire vpnMaps node for internal VPN
1894 deleteVpnMapsNode(routerId);
1896 // delete vpn-instance for internal VPN
1897 deleteVpnInstance(routerId);
1900 protected Subnet getNeutronSubnet(Uuid subnetId) {
1901 return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1904 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
1905 Subnet sn = NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
1907 return sn.getGatewayIp();
1913 protected Network getNeutronNetwork(Uuid networkId) {
1914 return NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
1917 protected Port getNeutronPort(String name) {
1918 return NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(name));
1921 protected Port getNeutronPort(Uuid portId) {
1922 return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1925 protected List<Uuid> getSubnetsforVpn(Uuid vpnid) {
1926 List<Uuid> subnets = new ArrayList<>();
1928 InstanceIdentifier<Subnetmaps> subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build();
1929 Optional<Subnetmaps> subnetmaps = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
1931 if (subnetmaps.isPresent() && subnetmaps.get().getSubnetmap() != null) {
1932 List<Subnetmap> subnetMapList = subnetmaps.get().getSubnetmap();
1933 for (Subnetmap subnetMap : subnetMapList) {
1934 if (subnetMap.getVpnId() != null && subnetMap.getVpnId().equals(vpnid)) {
1935 subnets.add(subnetMap.getId());
1943 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
1945 * @return a List of String to be printed on screen
1947 // TODO Clean up the exception handling and the console output
1948 @SuppressWarnings({"checkstyle:IllegalCatch", "checkstyle:RegexpSinglelineJava"})
1949 public List<String> showNeutronPortsCLI() {
1950 List<String> result = new ArrayList<>();
1951 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
1953 result.add("-------------------------------------------------------------------------------------------");
1954 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
1956 Optional<Ports> ports =
1957 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
1958 if (ports.isPresent() && ports.get().getPort() != null) {
1959 for (Port port : ports.get().getPort()) {
1960 List<FixedIps> fixedIPs = port.getFixedIps();
1962 if (fixedIPs != null && !fixedIPs.isEmpty()) {
1963 List<String> ipList = new ArrayList<>();
1964 for (FixedIps fixedIp : fixedIPs) {
1965 IpAddress ipAddress = fixedIp.getIpAddress();
1966 if (ipAddress.getIpv4Address() != null) {
1967 ipList.add(ipAddress.getIpv4Address().getValue());
1969 ipList.add((ipAddress.getIpv6Address().getValue()));
1972 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
1973 .getMacAddress().getValue(), NeutronvpnUtils.getIPPrefixFromPort(dataBroker, port),
1974 ipList.toString()));
1976 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
1977 .getMacAddress().getValue(), "Not Assigned", "Not " + "Assigned"));
1979 } catch (Exception e) {
1980 LOG.error("Failed to retrieve neutronPorts info for port {}: ", port.getUuid().getValue(),
1982 System.out.println("Failed to retrieve neutronPorts info for port: " + port.getUuid()
1983 .getValue() + ": " + e.getMessage());
1987 } catch (Exception e) {
1988 LOG.error("Failed to retrieve neutronPorts info : ", e);
1989 System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
1995 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
1997 * @param vpnuuid Uuid of the VPN whose config must be shown
1998 * @return formatted output list
2000 @SuppressWarnings("checkstyle:RegexpSinglelineJava")
2001 public List<String> showVpnConfigCLI(Uuid vpnuuid) {
2002 List<String> result = new ArrayList<>();
2003 if (vpnuuid == null) {
2004 System.out.println("");
2005 System.out.println("Displaying VPN config for all VPNs");
2006 System.out.println("To display VPN config for a particular VPN, use the following syntax");
2007 System.out.println(getshowVpnConfigCLIHelp());
2010 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2011 if (rpcResult.isSuccessful()) {
2013 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2015 result.add(String.format(" %-80s ", "Import-RTs"));
2017 result.add(String.format(" %-80s ", "Export-RTs"));
2019 result.add(String.format(" %-76s ", "Subnet IDs"));
2021 result.add("------------------------------------------------------------------------------------");
2023 List<L3vpnInstances> vpnList = rpcResult.getResult().getL3vpnInstances();
2024 for (L3vpnInstance vpn : vpnList) {
2025 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
2027 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2028 vpn.getRouteDistinguisher()));
2030 result.add(String.format(" %-80s ", vpn.getImportRT()));
2032 result.add(String.format(" %-80s ", vpn.getExportRT()));
2035 Uuid vpnid = vpn.getId();
2036 List<Uuid> subnetList = getSubnetsforVpn(vpnid);
2037 if (!subnetList.isEmpty()) {
2038 for (Uuid subnetuuid : subnetList) {
2039 result.add(String.format(" %-76s ", subnetuuid.getValue()));
2042 result.add(String.format(" %-76s ", "\" \""));
2045 result.add("----------------------------------------");
2049 String errortag = rpcResult.getErrors().iterator().next().getTag();
2050 if (errortag == "") {
2051 System.out.println("");
2052 System.out.println("No VPN has been configured yet");
2053 } else if (errortag == "invalid-value") {
2054 System.out.println("");
2055 System.out.println("VPN " + vpnuuid.getValue() + " is not present");
2057 System.out.println("error getting VPN info : " + rpcResult.getErrors());
2058 System.out.println(getshowVpnConfigCLIHelp());
2061 } catch (InterruptedException | ExecutionException e) {
2062 LOG.error("error getting VPN info : ", e);
2063 System.out.println("error getting VPN info : " + e.getMessage());
2068 protected void createExternalVpnInterfaces(Uuid extNetId) {
2069 if (extNetId == null) {
2070 LOG.trace("external network is null");
2074 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2075 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2076 LOG.trace("No external ports attached to external network {}", extNetId.getValue());
2080 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2081 for (String elanInterface : extElanInterfaces) {
2082 createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
2084 wrtConfigTxn.submit();
2087 // TODO Clean up the exception handling
2088 @SuppressWarnings("checkstyle:IllegalCatch")
2089 protected void removeExternalVpnInterfaces(Uuid extNetId) {
2090 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
2091 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
2092 LOG.trace("No external ports attached for external network {}", extNetId);
2097 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2098 for (String elanInterface : extElanInterfaces) {
2099 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
2100 .buildVpnInterfaceIdentifier(elanInterface);
2101 LOG.info("Removing vpn interface {}", elanInterface);
2102 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
2104 wrtConfigTxn.submit();
2106 } catch (Exception ex) {
2107 LOG.error("Removal of vpninterfaces {} failed due to {}", extElanInterfaces, ex);
2111 private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2112 writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, wrtConfigTxn);
2115 // TODO Clean up the exception handling
2116 @SuppressWarnings("checkstyle:IllegalCatch")
2117 private void writeVpnInterfaceToDs(Uuid vpnId, String infName, Adjacencies adjacencies,
2118 Boolean isRouterInterface, WriteTransaction wrtConfigTxn) {
2119 if (vpnId == null || infName == null) {
2120 LOG.debug("vpn id or interface is null");
2124 Boolean wrtConfigTxnPresent = true;
2125 if (wrtConfigTxn == null) {
2126 wrtConfigTxnPresent = false;
2127 wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2130 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2131 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2133 .setVpnInstanceName(vpnId.getValue())
2134 .setIsRouterInterface(isRouterInterface);
2135 if (adjacencies != null) {
2136 vpnb.addAugmentation(Adjacencies.class, adjacencies);
2138 VpnInterface vpnIf = vpnb.build();
2140 LOG.info("Creating vpn interface {}", vpnIf);
2141 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
2142 } catch (Exception ex) {
2143 LOG.error("Creation of vpninterface {} failed due to {}", infName, ex);
2146 if (!wrtConfigTxnPresent) {
2147 wrtConfigTxn.submit();
2151 private String getshowVpnConfigCLIHelp() {
2152 StringBuilder help = new StringBuilder("Usage:");
2153 help.append("display vpn-config [-vid/--vpnid <id>]");
2154 return help.toString();
2157 private void checkAndPublishRouterAssociatedtoVpnNotification(Uuid routerId, Uuid vpnId) throws
2158 InterruptedException {
2159 RouterAssociatedToVpn routerAssociatedToVpn = new RouterAssociatedToVpnBuilder().setRouterId(routerId)
2160 .setVpnId(vpnId).build();
2161 LOG.info("publishing notification upon association of router to VPN");
2162 notificationPublishService.putNotification(routerAssociatedToVpn);
2165 private void checkAndPublishRouterDisassociatedFromVpnNotification(Uuid routerId, Uuid vpnId) throws
2166 InterruptedException {
2167 RouterDisassociatedFromVpn routerDisassociatedFromVpn =
2168 new RouterDisassociatedFromVpnBuilder().setRouterId(routerId).setVpnId(vpnId).build();
2169 LOG.info("publishing notification upon disassociation of router from VPN");
2170 notificationPublishService.putNotification(routerDisassociatedFromVpn);
2173 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
2174 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);