Lower log level for non errors
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronvpnManager.java
1 /*
2  * Copyright © 2015, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.neutronvpn;
9
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12
13 import com.google.common.base.Optional;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.SettableFuture;
16
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;
24 import java.util.Map;
25 import java.util.Objects;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.Future;
29
30 import javax.annotation.PreDestroy;
31 import javax.inject.Inject;
32 import javax.inject.Singleton;
33
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;
155
156 @Singleton
157 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
158
159     private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
160
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<>();
172
173     @Inject
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);
189
190         configureFeatures();
191     }
192
193     @Override
194     @PreDestroy
195     public void close() throws Exception {
196         LOG.info("{} close", getClass().getSimpleName());
197     }
198
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();
204         try {
205             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
206         } catch (TransactionCommitFailedException e) {
207             LOG.warn("Error configuring feature {}", feature, e);
208         }
209     }
210
211     public String getOpenDaylightVniRangesConfig() {
212         return neutronvpnConfig.getOpendaylightVniRanges();
213     }
214
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) {
219         try {
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());
228                     return;
229                 }
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());
237             }
238         } catch (Exception e) {
239             LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
240         }
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());
247             }
248         }
249     }
250
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))
256                 .build();
257         try {
258             synchronized (subnetId.getValue().intern()) {
259                 Optional<Subnetmap> sn =
260                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
261                                 id);
262                 if (sn.isPresent()) {
263                     builder = new SubnetmapBuilder(sn.get());
264                     LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
265                 } else {
266                     LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
267                     return null;
268                 }
269                 if (routerId != null) {
270                     builder.setRouterId(routerId);
271                 }
272                 if (vpnId != null) {
273                     builder.setVpnId(vpnId);
274                 }
275                 subnetmap = builder.build();
276                 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
277                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
278             }
279         } catch (ReadFailedException | TransactionCommitFailedException e) {
280             LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
281         }
282         return subnetmap;
283     }
284
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();
292         try {
293             synchronized (subnetId.getValue().intern()) {
294                 Optional<Subnetmap> sn =
295                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
296                                 id);
297                 if (sn.isPresent()) {
298                     builder = new SubnetmapBuilder(sn.get());
299                     LOG.debug("WithRouterFixedIP: Updating existing subnetmap node for subnet ID {}",
300                         subnetId.getValue());
301                 } else {
302                     LOG.error("WithRouterFixedIP: subnetmap node for subnet {} does not exist, returning ",
303                         subnetId.getValue());
304                     return;
305                 }
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);
314             }
315         } catch (ReadFailedException | TransactionCommitFailedException e) {
316             LOG.error("WithRouterFixedIP: subnet map for Router FixedIp failed for node {}",
317                 subnetId.getValue(), e);
318         }
319     }
320
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());
326         try {
327             synchronized (subnetId.getValue().intern()) {
328                 Optional<Subnetmap> sn =
329                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
330                                 id);
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<>();
337                         }
338                         portList.add(portId);
339                         builder.setPortList(portList);
340                         LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
341                             subnetId.getValue(), portId.getValue());
342                     }
343                     if (null != directPortId) {
344                         List<Uuid> directPortList = builder.getDirectPortList();
345                         if (null == directPortList) {
346                             directPortList = new ArrayList<>();
347                         }
348                         directPortList.add(directPortId);
349                         builder.setDirectPortList(directPortList);
350                         LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
351                                 directPortId.getValue());
352                     }
353                     subnetmap = builder.build();
354                     SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
355                             subnetmap);
356                 } else {
357                     LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
358                         + "cache ", subnetId.getValue(), portId.getValue());
359                     unprocessedPortsMap.put(portId, subnetId);
360                 }
361             }
362         } catch (ReadFailedException | TransactionCommitFailedException e) {
363             LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
364         }
365         return subnetmap;
366     }
367
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))
372                 .build();
373         try {
374             synchronized (subnetId.getValue().intern()) {
375                 Optional<Subnetmap> sn =
376                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
377                                 id);
378                 if (sn.isPresent()) {
379                     SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
380                     if (routerId != null) {
381                         builder.setRouterId(null);
382                     }
383                     if (networkId != null) {
384                         builder.setNetworkId(null);
385                     }
386                     if (vpnId != null) {
387                         builder.setVpnId(null);
388                     }
389                     if (portId != null && builder.getPortList() != null) {
390                         List<Uuid> portList = builder.getPortList();
391                         portList.remove(portId);
392                         builder.setPortList(portList);
393                     }
394
395                     subnetmap = builder.build();
396                     LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
397                     SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
398                             subnetmap);
399                 } else {
400                     LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
401                 }
402             }
403         } catch (ReadFailedException | TransactionCommitFailedException e) {
404             LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
405         }
406         return subnetmap;
407     }
408
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();
413         try {
414             synchronized (subnetId.getValue().intern()) {
415                 Optional<Subnetmap> sn =
416                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
417                                 id);
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());
426                     }
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());
433                     }
434                     subnetmap = builder.build();
435                     SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
436                             subnetmap);
437                 } else {
438                     LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
439                 }
440             }
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);
444         }
445         return subnetmap;
446     }
447
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());
454         try {
455             synchronized (subnetId.getValue().intern()) {
456                 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
457                         subnetMapIdentifier);
458             }
459         } catch (Exception e) {
460             LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
461         }
462     }
463
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();
467         try {
468             Optional<VpnInstance> vpnInstanceConfig =
469                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
470                             vpnIdentifier);
471             if (!vpnInstanceConfig.isPresent()) {
472                 LOG.debug("No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
473                 return;
474             }
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());
480             }
481             if (vpnInstance.getIpv6Family() != null) {
482                 Ipv6FamilyBuilder ipv6FamilyBuilder = new Ipv6FamilyBuilder(vpnInstance.getIpv6Family());
483                 updateVpnInstanceBuilder.setIpv6Family(ipv6FamilyBuilder.setRouteDistinguisher(rds).build());
484             }
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);
490         }
491     }
492
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();
502         try {
503             Optional<VpnInstance> optionalVpn =
504                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
505                             vpnIdentifier);
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");
510             } else {
511                 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
512                         .setType(type).setL3vni(l3vni);
513             }
514             if (irt != null && !irt.isEmpty()) {
515                 if (ert != null && !ert.isEmpty()) {
516                     List<String> commonRT = new ArrayList<>(irt);
517                     commonRT.retainAll(ert);
518
519                     for (String common : commonRT) {
520                         irt.remove(common);
521                         ert.remove(common);
522                         VpnTarget vpnTarget =
523                                 new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue(common)
524                                         .setVrfRTType(VpnTarget.VrfRTType.Both).build();
525                         vpnTargetList.add(vpnTarget);
526                     }
527                 }
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);
533                 }
534             }
535
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);
542                 }
543             }
544
545             VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
546
547             Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
548             Ipv6FamilyBuilder ipv6vpnBuilder = new Ipv6FamilyBuilder().setVpnTargets(vpnTargets);
549
550             if (rd != null && !rd.isEmpty()) {
551                 ipv4vpnBuilder.setRouteDistinguisher(rd);
552                 ipv6vpnBuilder.setRouteDistinguisher(rd);
553             }
554
555             VpnInstance newVpn = null;
556             if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
557                 newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
558             }
559             if (ipVersion != null && ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
560                 newVpn = builder.setIpv6Family(ipv6vpnBuilder.build()).build();
561             }
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();
565             }
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);
571         } finally {
572             if (isLockAcquired) {
573                 NeutronUtils.unlock(vpnName);
574             }
575         }
576     }
577
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))
584                 .build();
585         LOG.debug("removing vpnMaps node: {} ", vpnid.getValue());
586         try {
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());
591         } finally {
592             if (isLockAcquired) {
593                 NeutronUtils.unlock(vpnid.getValue());
594             }
595         }
596     }
597
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))
605                 .build();
606         try {
607             Optional<VpnMap> optionalVpnMap =
608                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
609                             vpnMapIdentifier);
610             if (optionalVpnMap.isPresent()) {
611                 builder = new VpnMapBuilder(optionalVpnMap.get());
612             } else {
613                 builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
614             }
615
616             if (name != null) {
617                 builder.setName(name);
618             }
619             if (tenantId != null) {
620                 builder.setTenantId(tenantId);
621             }
622             if (router != null) {
623                 builder.setRouterId(router);
624             }
625             if (networks != null) {
626                 List<Uuid> nwList = builder.getNetworkIds();
627                 if (nwList == null) {
628                     nwList = new ArrayList<>();
629                 }
630                 nwList.addAll(networks);
631                 builder.setNetworkIds(nwList);
632             }
633
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());
640         } finally {
641             if (isLockAcquired) {
642                 NeutronUtils.unlock(vpnId.getValue());
643             }
644         }
645     }
646
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))
653                 .build();
654         Optional<VpnMap> optionalVpnMap;
655         try {
656             optionalVpnMap =
657                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
658                             vpnMapIdentifier);
659         } catch (ReadFailedException e) {
660             LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
661             return;
662         }
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())) {
668                     try {
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());
675                     } finally {
676                         if (isLockAcquired) {
677                             NeutronUtils.unlock(vpnId.getValue());
678                         }
679                     }
680                     return;
681                 }
682                 vpnMapBuilder.setRouterId(null);
683             }
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);
690                 } else {
691                     vpnMapBuilder.setNetworkIds(vpnNw);
692                 }
693             }
694
695             try {
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());
702             } finally {
703                 if (isLockAcquired) {
704                     NeutronUtils.unlock(vpnId.getValue());
705                 }
706             }
707         } else {
708             LOG.error("VPN : {} not found", vpnId.getValue());
709         }
710         LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
711     }
712
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()))
720                 .build();
721         try {
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());
727         } finally {
728             if (isLockAcquired) {
729                 NeutronUtils.unlock(vpnId.getValue());
730             }
731         }
732     }
733
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);
740         }
741         LOG.trace("createVpnInterface - isRouterInterface:{}", isRouterInterface);
742         // create adjacency list
743         Uuid rtrId = null;
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();
750             adjList.add(vmAdj);
751
752             NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName,
753                     port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
754
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);
764                     }
765                 }
766                 rtrId = routerId;
767             }
768         }
769         // create vpn-interface on this neutron port
770         Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
771         writeVpnInterfaceToDs(vpnId, infName, adjs, isRouterInterface, wrtConfigTxn);
772     }
773
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();
781         }
782         String infName = port.getUuid().getValue();
783         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
784         try {
785             LOG.debug("Deleting vpn interface {}", infName);
786             wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
787
788             Uuid rtrId = null;
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);
797                     rtrId = routerId;
798                 }
799             }
800         } catch (Exception ex) {
801             LOG.error("Deletion of vpninterface {} failed", infName, ex);
802         }
803         if (!wrtConfigTxnPresent) {
804             wrtConfigTxn.submit();
805         }
806     }
807
808     protected void updateVpnInterface(Uuid vpnId, Uuid oldVpnId, Port port, boolean isBeingAssociated,
809                                       boolean isSubnetIp, WriteTransaction writeConfigTxn) {
810         if (vpnId == null || port == null) {
811             return;
812         }
813         boolean isLockAcquired = false;
814         String infName = port.getUuid().getValue();
815         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
816
817         try {
818             isLockAcquired = NeutronUtils.lock(infName);
819             Optional<VpnInterface> optionalVpnInterface =
820                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
821                             vpnIfIdentifier);
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());
845                         }
846                     }
847                     Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(adjacencyList).build();
848                     vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
849                 }
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);
856                     }
857                     NeutronvpnUtils.createVpnPortFixedIpToPort(dataBroker, vpnId.getValue(), ipValue, infName, port
858                             .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
859                 }
860                 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIfBuilder
861                         .build());
862             } else {
863                 LOG.error("VPN Interface {} not found", infName);
864             }
865         } catch (ReadFailedException ex) {
866             LOG.error("Updation of vpninterface {} failed", infName, ex);
867         } finally {
868             if (isLockAcquired) {
869                 NeutronUtils.unlock(infName);
870             }
871         }
872     }
873
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) {
876
877         IpVersionChoice ipVersChoices = NeutronvpnUtils.getIpVersionChoicesFromRouterUuid(dataBroker, router);
878
879         // Update VPN Instance node
880         updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, VpnInstance.Type.L3, 0 /*l3vni*/, ipVersChoices);
881
882         // Update local vpn-subnet DS
883         updateVpnMaps(vpn, name, router, tenant, networks);
884
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
889
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());
897                 return;
898             }
899             associateRouterToInternalVpn(vpn, router);
900         }
901     }
902
903     /**
904      * Performs the creation of a Neutron L3VPN, associating the new VPN to the
905      * specified Neutron Networks and Routers.
906      *
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
918      */
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)
921                                     throws Exception {
922
923         IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
924         IpVersionChoice vers = NeutronvpnUtils.getIpVersionChoicesFromRouterUuid(dataBroker, router);
925         ipVersChoices = ipVersChoices.addVersion(vers);
926
927         updateVpnInstanceNode(vpn.getValue(), rd, irt, ert, type, l3vni, ipVersChoices);
928
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);
933
934         if (router != null) {
935             associateRouterToVpn(vpn, router);
936         }
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());
943             }
944         }
945     }
946
947     /**
948      * It handles the invocations to the createVPN RPC method.
949      */
950     @Override
951     // TODO Clean up the exception handling
952     @SuppressWarnings("checkstyle:IllegalCatch")
953     public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
954
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;
960
961         List<L3vpn> vpns = input.getL3vpn();
962         for (L3vpn vpn : vpns) {
963             RpcError error = null;
964             String msg;
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());
968                 LOG.warn(msg);
969                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
970                 errorList.add(error);
971                 warningcount++;
972                 continue;
973             }
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());
977                 LOG.warn(msg);
978                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
979                 errorList.add(error);
980                 warningcount++;
981                 continue;
982             }
983             VpnInstance.Type vpnInstanceType = VpnInstance.Type.L3;
984             long l3vni = 0;
985             if (vpn.getL3vni() != null) {
986                 l3vni = vpn.getL3vni();
987             }
988
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));
994                 LOG.warn(msg);
995                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
996                 errorList.add(error);
997                 warningcount++;
998                 continue;
999             }
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());
1004                     LOG.warn(msg);
1005                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1006                     errorList.add(error);
1007                     warningcount++;
1008                     continue;
1009                 }
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(),
1014                                 vpnId.getValue());
1015                     LOG.warn(msg);
1016                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1017                     errorList.add(error);
1018                     warningcount++;
1019                     continue;
1020                 }
1021             }
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());
1029                         LOG.warn(msg);
1030                         error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1031                         errorList.add(error);
1032                         warningcount++;
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(),
1036                                 vpnId.getValue());
1037                         LOG.warn(msg);
1038                         error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
1039                         errorList.add(error);
1040                         warningcount++;
1041                     }
1042                 }
1043                 if (error != null) {
1044                     continue;
1045                 }
1046             }
1047             try {
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());
1053                 LOG.error(msg, ex);
1054                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1055                 errorList.add(error);
1056                 failurecount++;
1057             }
1058         }
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());
1063         } else {
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);
1070                 }
1071             } else {
1072                 errorResponseList.add("Operation successful with no errors");
1073             }
1074             opBuilder.setResponse(errorResponseList);
1075             result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1076         }
1077         return result;
1078     }
1079
1080     /**
1081      * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1082      */
1083     @Override
1084     public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1085
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<>();
1091
1092         try {
1093             if (inputVpnId == null) {
1094                 // get all vpns
1095                 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1096                         .build();
1097                 Optional<VpnInstances> optionalVpns =
1098                         SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1099                                 vpnsIdentifier);
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) {
1105                             vpns.add(vpn);
1106                         }
1107                     }
1108                 } else {
1109                     // No VPN present
1110                     opBuilder.setL3vpnInstances(l3vpnList);
1111                     result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1112                     return result;
1113                 }
1114             } else {
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,
1121                                 vpnIdentifier);
1122                 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1123                 // getL3VPN output
1124                 if (optionalVpn.isPresent() && optionalVpn.get().getIpv4Family().getRouteDistinguisher() != null) {
1125                     vpns.add(optionalVpn.get());
1126                 } else {
1127                     String message = String.format("GetL3VPN failed because VPN %s is not present", name);
1128                     LOG.error(message);
1129                     result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL,
1130                             "invalid-value", message).build());
1131                 }
1132             }
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<>();
1140
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());
1146                         }
1147                         if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1148                             irtList.add(vpnTarget.getVrfRTValue());
1149                         }
1150                         if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1151                             ertList.add(vpnTarget.getVrfRTValue());
1152                             irtList.add(vpnTarget.getVrfRTValue());
1153                         }
1154                     }
1155                 }
1156
1157                 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1158
1159                 if (vpnInstance.getL3vni() != null) {
1160                     l3vpn.setL3vni(vpnInstance.getL3vni());
1161                 }
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,
1166                                 vpnMapIdentifier);
1167                 if (optionalVpnMap.isPresent()) {
1168                     VpnMap vpnMap = optionalVpnMap.get();
1169                     l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
1170                         .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
1171                 }
1172                 l3vpnList.add(l3vpn.build());
1173             }
1174
1175             opBuilder.setL3vpnInstances(l3vpnList);
1176             result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1177
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());
1182         }
1183         return result;
1184     }
1185
1186     /**
1187      * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1188      */
1189     @Override
1190     public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1191
1192         DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1193         SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1194         List<RpcError> errorList = new ArrayList<>();
1195
1196         int failurecount = 0;
1197         int warningcount = 0;
1198         List<Uuid> vpns = input.getId();
1199         for (Uuid vpn : vpns) {
1200             RpcError error;
1201             String msg;
1202             try {
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,
1208                                 vpnIdentifier);
1209                 if (optionalVpn.isPresent()) {
1210                     removeVpn(vpn);
1211                 } else {
1212                     msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
1213                     LOG.warn(msg);
1214                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
1215                     errorList.add(error);
1216                     warningcount++;
1217                 }
1218             } catch (ReadFailedException ex) {
1219                 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
1220                 LOG.error(msg, ex);
1221                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
1222                 errorList.add(error);
1223                 failurecount++;
1224             }
1225         }
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());
1230         } else {
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);
1237                 }
1238             } else {
1239                 errorResponseList.add("Operation successful with no errors");
1240             }
1241             opBuilder.setResponse(errorResponseList);
1242             result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1243         }
1244         return result;
1245     }
1246
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);
1250     }
1251
1252     public void removeVpnInstanceForSubnet(Uuid subnetId) {
1253         LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1254         removeVpn(subnetId);
1255     }
1256
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);
1260         if (sn == null) {
1261             LOG.error("subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(), vpnId.getValue());
1262             return;
1263         }
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());
1267             return;
1268         }
1269
1270         final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1271         if (isVpnOfTypeL2(vpnInstance)) {
1272             neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1273                     NeutronEvpnUtils.Operation.ADD);
1274         }
1275         // Check if there are ports on this subnet and add corresponding
1276         // vpn-interfaces
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());
1287                     return futures;
1288                 });
1289             }
1290         }
1291     }
1292
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);
1297         if (sn == null) {
1298             LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1299             return;
1300         }
1301
1302         //Update Router Interface first synchronously.
1303         //CAUTION:  Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1304         try {
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);
1313             return;
1314         }
1315
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());
1330                     return futures;
1331                 });
1332             }
1333         }
1334     }
1335
1336     public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1337         return InstanceIdentifier.builder(RouterInterfacesMap.class)
1338                 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1339     }
1340
1341     protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1342         synchronized (routerId.getValue().intern()) {
1343             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1344             try {
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)),
1353                             routerInterface);
1354                 } else {
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)),
1361                             routerInterface);
1362                 }
1363             } catch (ReadFailedException e) {
1364                 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1365             }
1366         }
1367     }
1368
1369     protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1370         synchronized (routerId.getValue().intern()) {
1371             InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1372             try {
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);
1384                         } else {
1385                             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1386                                     routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1387                         }
1388                     }
1389                 }
1390             } catch (ReadFailedException e) {
1391                 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1392             }
1393         }
1394     }
1395
1396     /**
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.
1400      *
1401      * @param vpnName the VPN identifier
1402      * @param interVpnLinkRoutes The list of static routes
1403      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1404      */
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())
1415                                 .build();
1416                 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1417                 RpcResult<AddStaticRouteOutput> rpcResult;
1418                 try {
1419                     rpcResult = labelOuputFtr.get();
1420                     if (rpcResult.isSuccessful()) {
1421                         LOG.debug("Label generated for destination {} is: {}",
1422                                 destination, rpcResult.getResult().getLabel());
1423                     } else {
1424                         LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1425                                 destination, nexthop, rpcResult.getErrors());
1426                     }
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);
1430                 }
1431             } else {
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);
1435                 continue;
1436             }
1437         }
1438     }
1439
1440     /**
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.
1443      *
1444      * @param vpnName the VPN identifier
1445      * @param interVpnLinkRoutes The list of static routes
1446      * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1447      */
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())
1458                                 .build();
1459                 vpnRpcService.removeStaticRoute(rpcInput);
1460             } else {
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);
1464                 continue;
1465             }
1466         }
1467     }
1468
1469     /*
1470      * Returns true if the specified nexthop is the other endpoint in an
1471      * InterVpnLink, regarding one of the VPN's point of view.
1472      */
1473     private boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid, InterVpnLink interVpnLink) {
1474         return
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));
1480     }
1481
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);
1488             } else {
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);
1493                     continue;
1494                 }
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)) {
1499                     hops.add(nextHop);
1500                 }
1501             }
1502         }
1503
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();
1508             adjList.add(erAdj);
1509         }
1510         return  adjList;
1511     }
1512
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);
1519             } else {
1520                 String nextHop = String.valueOf(route.getNexthop().getValue());
1521                 String destination = String.valueOf(route.getDestination().getValue());
1522                 String infName = NeutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(dataBroker, vpnId.getValue(),
1523                         nextHop);
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;
1528                     try {
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);
1541                     } finally {
1542                         if (isLockAcquired) {
1543                             NeutronUtils.unlock(infName);
1544                         }
1545                     }
1546                 } else {
1547                     LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
1548                         + "with nexthop {}", destination, vpnId.getValue(), nextHop);
1549                 }
1550             }
1551         }
1552     }
1553
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(),
1563                         nextHop);
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
1568                     continue;
1569                 }
1570                 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
1571                         destination, vpnId.getValue(), nextHop, infName);
1572
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))
1578                                 .build();
1579
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;
1591                             } else {
1592                                 nextHopList.add(nextHopRead);
1593                             }
1594                         }
1595                     }
1596                 }
1597
1598                 try {
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))
1607                                 .build();
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);
1613                     } else {
1614                         // Remove the whole route
1615                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1616                         LOG.trace("extra route {} deleted successfully", route);
1617                     }
1618                 } catch (Exception e) {
1619                     LOG.error("exception in deleting extra route with destination {} for interface {}",
1620                             destination, infName, e);
1621                 } finally {
1622                     if (isLockAcquired) {
1623                         NeutronUtils.unlock(infName);
1624                     }
1625                 }
1626             } else {
1627                 LOG.error("Incorrect input received for extra route: {}", route);
1628             }
1629         }
1630     }
1631
1632     public void removeVpn(Uuid id) {
1633         // read VPNMaps
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);
1639         }
1640         // dissociate networks
1641         if (!id.equals(router)) {
1642             dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
1643         }
1644         // remove entire vpnMaps node
1645         deleteVpnMapsNode(id);
1646
1647         // remove vpn-instance
1648         deleteVpnInstance(id);
1649     }
1650
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());
1657             return;
1658         }
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);
1664         }
1665         if (sn != null) {
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);
1676
1677                         if (port != null) {
1678                             deleteVpnInterface(vpnId, port, wrtConfigTxn);
1679                         } else {
1680                             LOG.error("Cannot proceed with deleteVpnInterface for port {} in subnet {} since port is "
1681                                 + "absent in Neutron config DS", portId.getValue(), subnet.getValue());
1682                         }
1683                         futures.add(wrtConfigTxn.submit());
1684                         return futures;
1685                     });
1686                 }
1687             }
1688             // update subnet-vpn association
1689             removeFromSubnetNode(subnet, null, null, vpnId, null);
1690         } else {
1691             LOG.error("Subnetmap for subnet {} not found", subnet.getValue());
1692         }
1693     }
1694
1695     private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
1696         return vpnInstance != null && vpnInstance.getType() == VpnInstance.Type.L2;
1697     }
1698
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);
1708             }
1709         }
1710         try {
1711             checkAndPublishRouterAssociatedtoVpnNotification(routerId, vpnId);
1712             LOG.debug("notification upon association of router {} to VPN {} published", routerId.getValue(),
1713                     vpnId.getValue());
1714         } catch (Exception e) {
1715             LOG.error("publishing of notification upon association of router {} to VPN {} failed : ", routerId
1716                     .getValue(), vpnId.getValue(), e);
1717         }
1718     }
1719
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);
1725         }
1726     }
1727
1728     // TODO Clean up the exception handling
1729     @SuppressWarnings("checkstyle:IllegalCatch")
1730     protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
1731
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);
1737             }
1738         }
1739         clearFromVpnMaps(vpnId, routerId, null);
1740         try {
1741             checkAndPublishRouterDisassociatedFromVpnNotification(routerId, vpnId);
1742             LOG.debug("notification upon disassociation of router {} from VPN {} published", routerId.getValue(),
1743                     vpnId.getValue());
1744         } catch (Exception e) {
1745             LOG.error("publishing of notification upon disassociation of router {} from VPN {} failed : ", routerId
1746                     .getValue(), vpnId.getValue(), e);
1747         }
1748     }
1749
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",
1758                         vpn.getValue()));
1759                 return failedNwList;
1760             }
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()));
1770                     continue;
1771                 }
1772                 try {
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(),
1778                                 vpnId.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");
1783                     } else {
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);
1793                                 } else {
1794                                     failedNwList.add(
1795                                             String.format("subnet %s already added as router interface bound to "
1796                                                             + "internal/external VPN %s", subnet.getValue(),
1797                                                     subnetVpnId.getValue()));
1798                                 }
1799                             }
1800                         }
1801                         if (NeutronvpnUtils.getIsExternal(network)) {
1802                             nvpnNatManager.addExternalNetworkToVpn(network, vpn);
1803                         }
1804                     }
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");
1808                 }
1809             }
1810             updateVpnMaps(vpn, null, null, null, passedNwList);
1811         }
1812         return failedNwList;
1813     }
1814
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()));
1824                 } else {
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);
1833                             }
1834                         }
1835                     } else {
1836                         if (vpnId == null) {
1837                             failedNwList.add(String.format("input network %s not associated to any vpn yet", nw
1838                                     .getValue()));
1839                         } else {
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()));
1842                         }
1843                     }
1844                     if (NeutronvpnUtils.getIsExternal(network)) {
1845                         nvpnNatManager.removeExternalNetworkFromVpn(network);
1846                     }
1847                 }
1848             }
1849             clearFromVpnMaps(vpn, null, passedNwList);
1850         }
1851         return failedNwList;
1852     }
1853
1854     /**
1855      * It handles the invocations to the neutronvpn:associateNetworks RPC method.
1856      */
1857     @Override
1858     // TODO Clean up the exception handling
1859     @SuppressWarnings("checkstyle:IllegalCatch")
1860     public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1861
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();
1867
1868         try {
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);
1875                     }
1876                 }
1877             } else {
1878                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1879             }
1880             if (returnMsg.length() != 0) {
1881                 String message = String.format("associate Networks to vpn %s failed due to %s",
1882                         vpnId.getValue(), returnMsg);
1883                 LOG.error(message);
1884                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: %s",
1885                         message);
1886                 opBuilder.setResponse(errorResponse);
1887                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
1888             } else {
1889                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
1890             }
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)
1896                     .build());
1897         }
1898         LOG.debug("associateNetworks returns..");
1899         return result;
1900     }
1901
1902     /**
1903      * It handles the invocations to the neutronvpn:associateRouter RPC method.
1904      */
1905     @Override
1906     // TODO Clean up the exception handling
1907     @SuppressWarnings("checkstyle:IllegalCatch")
1908     public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1909
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();
1915         try {
1916             VpnMap vpnMap = NeutronvpnUtils.getVpnMap(dataBroker, vpnId);
1917             Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
1918             if (vpnMap != null) {
1919                 if (rtr != 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());
1927                     } else {
1928                         associateRouterToVpn(vpnId, routerId);
1929                     }
1930                 } else {
1931                     returnMsg.append("router not found : ").append(routerId.getValue());
1932                 }
1933             } else {
1934                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1935             }
1936             if (returnMsg.length() != 0) {
1937                 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1938                         returnMsg);
1939                 LOG.error(message);
1940                 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1941                         .build());
1942             } else {
1943                 result.set(RpcResultBuilder.<Void>success().build());
1944             }
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());
1950         }
1951         LOG.debug("associateRouter returns..");
1952         return result;
1953     }
1954
1955     /** It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
1956      */
1957     @Override
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();
1966         try {
1967             List<String> fixedIPList = new ArrayList<>();
1968             Port port = NeutronvpnUtils.getNeutronPort(dataBroker, portId);
1969             if (port != null) {
1970                 List<FixedIps> fixedIPs = port.getFixedIps();
1971                 for (FixedIps ip : fixedIPs) {
1972                     fixedIPList.add(String.valueOf(ip.getIpAddress().getValue()));
1973                 }
1974             } else {
1975                 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
1976             }
1977             if (returnMsg.length() != 0) {
1978                 String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
1979                 LOG.error(message);
1980                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed()
1981                         .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
1982             } else {
1983                 opBuilder.setFixedIPs(fixedIPList);
1984                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
1985                         .build());
1986                 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
1987             }
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());
1994         }
1995         return result;
1996     }
1997
1998     /**
1999      * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2000      */
2001     @Override
2002     // TODO Clean up the exception handling
2003     @SuppressWarnings("checkstyle:IllegalCatch")
2004     public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2005
2006         DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2007         SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2008
2009         LOG.debug("dissociateNetworks {}", input);
2010         StringBuilder returnMsg = new StringBuilder();
2011         Uuid vpnId = input.getVpnId();
2012
2013         try {
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);
2020                     }
2021                 }
2022             } else {
2023                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2024             }
2025             if (returnMsg.length() != 0) {
2026                 String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
2027                         returnMsg);
2028                 LOG.error(message);
2029                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
2030                         + message);
2031                 opBuilder.setResponse(errorResponse);
2032                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2033             } else {
2034                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2035             }
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)
2041                     .build());
2042         }
2043         LOG.debug("dissociateNetworks returns..");
2044         return result;
2045     }
2046
2047     /**
2048      * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2049      */
2050     @Override
2051     // TODO Clean up the exception handling
2052     @SuppressWarnings("checkstyle:IllegalCatch")
2053     public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
2054
2055         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
2056
2057         LOG.debug("dissociateRouter {}", input);
2058         StringBuilder returnMsg = new StringBuilder();
2059         Uuid vpnId = input.getVpnId();
2060         Uuid routerId = input.getRouterId();
2061         try {
2062             if (NeutronvpnUtils.getVpnMap(dataBroker, vpnId) != null) {
2063                 if (routerId != null) {
2064                     Router rtr = NeutronvpnUtils.getNeutronRouter(dataBroker, routerId);
2065                     if (rtr != null) {
2066                         Uuid routerVpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
2067                         if (vpnId.equals(routerVpnId)) {
2068                             dissociateRouterFromVpn(vpnId, routerId);
2069                         } else {
2070                             if (routerVpnId == null) {
2071                                 returnMsg.append("input router ").append(routerId.getValue())
2072                                     .append(" not associated to any vpn yet");
2073                             } else {
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");
2077                             }
2078                         }
2079                     } else {
2080                         returnMsg.append("router not found : ").append(routerId.getValue());
2081                     }
2082                 }
2083             } else {
2084                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2085             }
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);
2089                 LOG.error(message);
2090                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: "
2091                         + message);
2092                 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
2093                         .build());
2094             } else {
2095                 result.set(RpcResultBuilder.<Void>success().build());
2096             }
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());
2102         }
2103         LOG.debug("dissociateRouter returns..");
2104
2105         return result;
2106     }
2107
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);
2115             }
2116             clearFromVpnMaps(vpnId, routerId, null);
2117         } else {
2118             // remove existing internal vpn interfaces
2119             for (Uuid subnetId : routerSubnetIds) {
2120                 removeSubnetFromVpn(routerId, subnetId);
2121             }
2122         }
2123         // delete entire vpnMaps node for internal VPN
2124         deleteVpnMapsNode(routerId);
2125
2126         // delete vpn-instance for internal VPN
2127         deleteVpnInstance(routerId);
2128     }
2129
2130     protected Subnet getNeutronSubnet(Uuid subnetId) {
2131         return NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
2132     }
2133
2134     protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
2135         Subnet sn = NeutronvpnUtils.getNeutronSubnet(dataBroker, subnetId);
2136         if (null != sn) {
2137             return sn.getGatewayIp();
2138         }
2139         return null;
2140     }
2141
2142
2143     protected Network getNeutronNetwork(Uuid networkId) {
2144         return NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
2145     }
2146
2147     protected Port getNeutronPort(String name) {
2148         return NeutronvpnUtils.getNeutronPort(dataBroker, new Uuid(name));
2149     }
2150
2151     protected Port getNeutronPort(Uuid portId) {
2152         return NeutronvpnUtils.getNeutronPort(dataBroker, portId);
2153     }
2154
2155     protected Uuid getNetworkForSubnet(Uuid subnetId) {
2156         return NeutronvpnUtils.getNetworkForSubnet(dataBroker, subnetId);
2157     }
2158
2159     protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
2160         return NeutronvpnUtils.getNetworksforVpn(dataBroker, vpnId);
2161     }
2162
2163     /**
2164      * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
2165      *
2166      * @return a List of String to be printed on screen
2167      * @throws ReadFailedException if there was a problem reading from the data store
2168      */
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",
2172             "IP Address"));
2173         result.add("-------------------------------------------------------------------------------------------");
2174         InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
2175
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());
2186                         } else {
2187                             ipList.add(ipAddress.getIpv6Address().getValue());
2188                         }
2189                     }
2190                     result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
2191                             .getMacAddress().getValue(), NeutronvpnUtils.getIPPrefixFromPort(dataBroker, port),
2192                             ipList.toString()));
2193                 } else {
2194                     result.add(String.format(" %-36s  %-19s  %-13s  %-20s ", port.getUuid().getValue(), port
2195                             .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
2196                 }
2197             }
2198         }
2199
2200         return result;
2201     }
2202
2203     /**
2204      * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
2205      *
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
2210      */
2211     public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
2212         List<String> result = new ArrayList<>();
2213         if (vpnuuid == null) {
2214             result.add("");
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());
2218         }
2219         RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
2220         if (rpcResult.isSuccessful()) {
2221             result.add("");
2222             result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
2223             result.add("");
2224             result.add(String.format(" %-80s ", "Import-RTs"));
2225             result.add("");
2226             result.add(String.format(" %-80s ", "Export-RTs"));
2227             result.add("");
2228             result.add(String.format(" %-76s ", "Subnet IDs"));
2229             result.add("");
2230             result.add("------------------------------------------------------------------------------------");
2231             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()
2236                         : "\"                 " + "                  \"";
2237                 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
2238                         vpn.getRouteDistinguisher()));
2239                 result.add("");
2240                 result.add(String.format(" %-80s ", vpn.getImportRT()));
2241                 result.add("");
2242                 result.add(String.format(" %-80s ", vpn.getExportRT()));
2243                 result.add("");
2244
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()));
2250                     }
2251                 } else {
2252                     result.add(String.format(" %-76s ", "\"                                    \""));
2253                 }
2254                 result.add("");
2255                 result.add("----------------------------------------");
2256                 result.add("");
2257             }
2258         } else {
2259             String errortag = rpcResult.getErrors().iterator().next().getTag();
2260             if (Objects.equals(errortag, "")) {
2261                 result.add("");
2262                 result.add("No VPN has been configured yet");
2263             } else if (Objects.equals(errortag, "invalid-value")) {
2264                 result.add("");
2265                 result.add("VPN " + vpnuuid.getValue() + " is not present");
2266             } else {
2267                 result.add("error getting VPN info : " + rpcResult.getErrors());
2268                 result.add(getshowVpnConfigCLIHelp());
2269             }
2270         }
2271         return result;
2272     }
2273
2274     protected void createExternalVpnInterfaces(Uuid extNetId) {
2275         if (extNetId == null) {
2276             LOG.error("createExternalVpnInterfaces: external network is null");
2277             return;
2278         }
2279
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());
2283             return;
2284         }
2285
2286         WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2287         for (String elanInterface : extElanInterfaces) {
2288             createExternalVpnInterface(extNetId, elanInterface, wrtConfigTxn);
2289         }
2290         wrtConfigTxn.submit();
2291     }
2292
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());
2299             return;
2300         }
2301         try {
2302
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);
2309             }
2310             wrtConfigTxn.submit();
2311
2312         } catch (Exception ex) {
2313             LOG.error("Removal of vpninterfaces {} failed", extElanInterfaces, ex);
2314         }
2315     }
2316
2317     private void createExternalVpnInterface(Uuid vpnId, String infName, WriteTransaction wrtConfigTxn) {
2318         writeVpnInterfaceToDs(vpnId, infName, null, false /* not a router iface */, wrtConfigTxn);
2319     }
2320
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");
2327             return;
2328         }
2329
2330         Boolean wrtConfigTxnPresent = true;
2331         if (wrtConfigTxn == null) {
2332             wrtConfigTxnPresent = false;
2333             wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
2334         }
2335
2336         InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
2337         VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
2338                 .setName(infName)
2339                 .setVpnInstanceName(vpnId.getValue())
2340                 .setRouterInterface(isRouterInterface);
2341         if (adjacencies != null) {
2342             vpnb.addAugmentation(Adjacencies.class, adjacencies);
2343         }
2344         VpnInterface vpnIf = vpnb.build();
2345         try {
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);
2350         }
2351
2352         if (!wrtConfigTxnPresent) {
2353             wrtConfigTxn.submit();
2354         }
2355     }
2356
2357     private String getshowVpnConfigCLIHelp() {
2358         StringBuilder help = new StringBuilder("Usage:");
2359         help.append("display vpn-config [-vid/--vpnid <id>]");
2360         return help.toString();
2361     }
2362
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);
2369     }
2370
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);
2377     }
2378
2379     protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
2380         floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
2381     }
2382
2383     @Override
2384     public Future<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
2385         return neutronEvpnManager.createEVPN(input);
2386     }
2387
2388     @Override
2389     public Future<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
2390         return neutronEvpnManager.getEVPN(input);
2391     }
2392
2393     @Override
2394     public Future<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
2395         return neutronEvpnManager.deleteEVPN(input);
2396     }
2397 }