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