Initial commit for NeutronVpn
[vpnservice.git] / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / vpnservice / neutronvpn / NeutronvpnManager.java
1 /*
2  * Copyright (c) 2015 - 2016 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.vpnservice.neutronvpn;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.SettableFuture;
12
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
17 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
18 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
19 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
20 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
21 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
22 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
23 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets
24         .VpnTargetBuilder;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance
30         .Ipv4FamilyBuilder;
31 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
32 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateNetworksInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateNetworksOutput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.AssociateRouterInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNInput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNOutput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNOutput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateNetworksInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateNetworksOutput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DissociateRouterInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetL3VPNOutputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.L3vpnInstance;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetmapsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMaps;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMapsBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.createl3vpn.input.L3vpn;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.getl3vpn.output
81         .L3vpnInstancesBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
83         .PortFixedipToPortNameBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
85         .PortNameToPortUuidBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapKey;
92 import org.opendaylight.yangtools.yang.binding.DataObject;
93 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
94 import org.opendaylight.yangtools.yang.common.RpcError;
95 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
96 import org.opendaylight.yangtools.yang.common.RpcResult;
97 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
98 import org.slf4j.Logger;
99 import org.slf4j.LoggerFactory;
100
101 import java.util.ArrayList;
102 import java.util.Arrays;
103 import java.util.List;
104 import java.util.concurrent.ExecutionException;
105 import java.util.concurrent.Future;
106
107 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable {
108
109     private static final Logger logger = LoggerFactory.getLogger(NeutronvpnManager.class);
110     private final DataBroker broker;
111     private LockManagerService lockManager;
112     IMdsalApiManager mdsalUtil;
113
114     /**
115      * @param db           - dataBroker reference
116      * @param mdsalManager - MDSAL Util API access
117      */
118     public NeutronvpnManager(final DataBroker db, IMdsalApiManager mdsalManager) {
119         broker = db;
120         mdsalUtil = mdsalManager;
121     }
122
123     public void setLockManager(LockManagerService lockManager) {
124         this.lockManager = lockManager;
125     }
126
127     @Override
128     public void close() throws Exception {
129         logger.info("Neutron VPN Manager Closed");
130     }
131
132     protected Subnetmap updateSubnetNode(Uuid subnetId, Uuid tenantId, Uuid networkId, Uuid routerId, Uuid vpnId,
133                                          Uuid portId) {
134
135         try {
136             SubnetmapBuilder builder = null;
137
138             InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
139                     child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
140             Optional<Subnetmap> sn = read(LogicalDatastoreType.CONFIGURATION, id);
141             logger.debug("updating Subnet :read: ");
142             if (sn.isPresent()) {
143                 builder = new SubnetmapBuilder(sn.get());
144                 logger.debug("updating Subnet :existing: ");
145             } else {
146                 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
147                 logger.debug("updating Subnet :new: ");
148             }
149
150             if (routerId != null) {
151                 builder.setRouterId(routerId);
152             }
153             if (networkId != null) {
154                 builder.setNetworkId(networkId);
155             }
156             if (vpnId != null) {
157                 builder.setVpnId(vpnId);
158             }
159             if (tenantId != null) {
160                 builder.setTenantId(tenantId);
161             }
162
163             if (portId != null) {
164                 List<Uuid> portList = builder.getPortList();
165                 if (portList == null) {
166                     portList = new ArrayList<Uuid>();
167                 }
168                 portList.add(portId);
169                 builder.setPortList(portList);
170             }
171
172             Subnetmap subnetmap = builder.build();
173             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
174             logger.debug("Created/Updated subnetmap node: {} ", subnetId.getValue());
175
176             return subnetmap;
177         } catch (Exception e) {
178             logger.error("Update local subnetmap failed for node: {} {} {} {} {} {} ",
179                     subnetId.getValue(), tenantId.getValue(), networkId.getValue(), routerId.getValue(), vpnId
180                             .getValue(), portId.getValue());
181             throw new RuntimeException(e);
182         }
183
184     }
185
186     protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
187         Subnetmap subnetmap = null;
188         try {
189             InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
190                     child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
191             Optional<Subnetmap> sn = read(LogicalDatastoreType.CONFIGURATION, id);
192
193             if (sn.isPresent()) {
194                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
195
196                 if (routerId != null) {
197                     builder.setRouterId(null);
198                 }
199                 if (networkId != null) {
200                     builder.setNetworkId(null);
201                 }
202                 if (vpnId != null) {
203                     builder.setVpnId(null);
204                 }
205                 if (portId != null && builder.getPortList() != null) {
206                     List<Uuid> portList = builder.getPortList();
207                     portList.remove(portId);
208                     builder.setPortList(portList);
209                 }
210
211                 subnetmap = builder.build();
212                 logger.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
213                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
214             } else {
215                 logger.warn("remove from non-existing subnetmap node: {} ", subnetId.getValue());
216             }
217         } catch (Exception e) {
218             logger.error("Remove from subnetmap failed for node: {} {} {} {} {} {} ", subnetId.getValue(), networkId
219                     .getValue(), routerId.getValue(), vpnId.getValue(), portId.getValue());
220             throw new RuntimeException(e);
221         }
222
223         return subnetmap;
224     }
225
226     private void updateVpnInstanceNode(String name, List<String> rd, List<String> irt, List<String> ert) {
227
228         try {
229             VpnInstanceBuilder builder = null;
230             List<VpnTarget> vpnTargetList = new ArrayList<VpnTarget>();
231             InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class).
232                     child(VpnInstance.class, new VpnInstanceKey(name)).build();
233             Optional<VpnInstance> optionalVpn = read(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
234             logger.debug("Creating/Updating a new vpn-instance node: {} ", name);
235             if (optionalVpn.isPresent()) {
236                 builder = new VpnInstanceBuilder(optionalVpn.get());
237                 logger.debug("updating existing vpninstance node");
238             } else {
239                 builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(name)).setVpnInstanceName(name);
240             }
241
242             if (irt != null && !irt.isEmpty()) {
243                 if (ert != null && !ert.isEmpty()) {
244                     List<String> commonRT = new ArrayList<String>(irt);
245                     commonRT.retainAll(ert);
246
247                     for (String common : commonRT) {
248                         irt.remove(common);
249                         ert.remove(common);
250                         VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue
251                                 (common).setVrfRTType(VpnTarget.VrfRTType.Both).build();
252                         vpnTargetList.add(vpnTarget);
253                     }
254                 }
255                 for (String importRT : irt) {
256                     VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue
257                             (importRT).setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
258                     vpnTargetList.add(vpnTarget);
259                 }
260             }
261
262             if (ert != null && !ert.isEmpty()) {
263                 for (String exportRT : ert) {
264                     VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue
265                             (exportRT).setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
266                     vpnTargetList.add(vpnTarget);
267                 }
268             }
269
270             VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
271
272             Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
273
274             if (rd != null && !rd.isEmpty()) {
275                 ipv4vpnBuilder.setRouteDistinguisher(rd.get(0));
276             }
277
278             VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
279             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
280             logger.debug("Created/Updated vpn-instance for {} ", name);
281         } catch (Exception e) {
282             logger.error("Update VPN Instance node failed for node: {} {} {} {}", name, rd, irt, ert);
283             throw new RuntimeException(e);
284         }
285     }
286
287     private void createVpnMapsNode() {
288         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
289         VpnMapsBuilder vpnMaps = new VpnMapsBuilder();
290         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier, vpnMaps.build());
291         InstanceIdentifier<Subnetmaps> subnetmapsId = InstanceIdentifier.builder(Subnetmaps.class).build();
292         SubnetmapsBuilder subnetmaps = new SubnetmapsBuilder();
293         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, subnetmapsId, subnetmaps.build());
294     }
295
296     private void deleteVpnMapsNode(Uuid vpnid) {
297         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
298                 .child(VpnMap.class, new VpnMapKey(vpnid)).build();
299         logger.debug("removing vpnMaps node: {} ", vpnid.getValue());
300         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
301     }
302
303     private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
304         VpnMapBuilder builder;
305         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
306                 .child(VpnMap.class, new VpnMapKey(vpnId)).build();
307         Optional<VpnMap> optionalVpnMap = read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
308         if (optionalVpnMap.isPresent()) {
309             builder = new VpnMapBuilder(optionalVpnMap.get());
310         } else {
311             builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
312         }
313
314         if (name != null) {
315             builder.setName(name);
316         }
317         if (tenantId != null) {
318             builder.setTenantId(tenantId);
319         }
320         if (router != null) {
321             builder.setRouterId(router);
322         }
323         if (networks != null) {
324             List<Uuid> nwList = builder.getNetworkIds();
325             if (nwList == null) {
326                 nwList = new ArrayList<Uuid>();
327             }
328             nwList.addAll(networks);
329             builder.setNetworkIds(nwList);
330         }
331
332         logger.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
333         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
334         logger.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
335     }
336
337     private void clearFromVpnMaps(Uuid id, Uuid router, List<Uuid> networks) {
338         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
339                 .child(VpnMap.class, new VpnMapKey(id)).build();
340         Optional<VpnMap> optionalVpnMap = read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
341         if (optionalVpnMap.isPresent()) {
342             VpnMap vpnMap = optionalVpnMap.get();
343             VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
344             if (router != null) {
345                 if (vpnMap.getNetworkIds() == null && router.equals(vpnMap.getVpnId())) {
346                     // remove entire node in case of internal VPN
347                     logger.debug("removing vpnMaps node: {} ", id);
348                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
349                     return;
350                 }
351                 vpnMapBuilder.setRouterId(null);
352             }
353             if (networks != null) {
354                 List<Uuid> vpnNw = vpnMap.getNetworkIds();
355                 for (Uuid nw : networks) {
356                     vpnNw.remove(nw);
357                 }
358                 if (vpnNw.isEmpty()) {
359                     logger.debug("setting networks null in vpnMaps node: {} ", id.getValue());
360                     vpnMapBuilder.setNetworkIds(null);
361                 } else {
362                     vpnMapBuilder.setNetworkIds(vpnNw);
363                 }
364             }
365
366             logger.debug("clearing from vpnMaps node: {} ", id.getValue());
367             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, vpnMapBuilder.build());
368         } else {
369             logger.error("VPN : {} not found", id.getValue());
370         }
371         logger.debug("VPNMaps DS clear success for VPN {} ", id.getValue());
372     }
373
374     private void createOfPortInterface(Port port, int portVlanId) {
375         String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
376         //String ifname = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
377         //Network network = NeutronvpnUtils.getNeutronNetwork(broker, port.getNetworkId());
378         //Boolean isVlanTransparent = network.isVlanTransparent();
379
380         logger.debug("Creating OFPort Interface {}", name);
381         InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
382         try {
383             Optional<Interface> optionalInf = read(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
384             if (!optionalInf.isPresent()) {
385                 // handle these for trunkport extensions : portVlanId, isVlanTransparent
386                 Interface inf = new InterfaceBuilder().setEnabled(true).setName(name).setType(L2vlan.class).build();
387                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
388             } else {
389                 logger.error("Interface {} is already present", name);
390             }
391         } catch (Exception e) {
392             logger.error("failed to create interface {} due to the exception {} ", name, e.getMessage());
393         }
394
395         InstanceIdentifier portIdentifier = NeutronvpnUtils.buildPortNameToPortUuidIdentifier(name);
396         PortNameToPortUuidBuilder builder = new PortNameToPortUuidBuilder().setPortName(name).setPortId(port.getUuid());
397         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, portIdentifier, builder.build());
398         logger.debug("name-uuid map for port with name: {}, uuid: {} added to NeutronPortData DS", name, port.getUuid
399                 ());
400     }
401
402     private void deleteOfPortInterface(Port port, int portVlanId) {
403         String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
404         //String ifname = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
405         logger.debug("Removing OFPort Interface {}", name);
406         InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
407         try {
408             Optional<Interface> optionalInf = read(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
409             if (optionalInf.isPresent()) {
410                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
411             } else {
412                 logger.error("Interface {} is not present", name);
413             }
414         } catch (Exception e) {
415             logger.error("Failed to delete interface {} due to the exception {}", name, e.getMessage());
416         }
417
418         InstanceIdentifier id = NeutronvpnUtils.buildPortNameToPortUuidIdentifier(name);
419         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
420         logger.debug("name-uuid map for port with name: {}, uuid: {} deleted from NeutronPortData DS", name, port
421                 .getUuid());
422     }
423
424     private void deleteVpnInstance(Uuid vpnId) {
425
426         InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class).
427                 child(VpnInstance.class, new VpnInstanceKey(vpnId.getValue())).build();
428         logger.debug("removing vpn Instance {}", vpnId.getValue());
429         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
430     }
431
432
433     private void createVpnInterface(Uuid vpnId, Port port) {
434
435         if (vpnId == null || port == null) {
436             return;
437         }
438         String portname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
439         String name = new StringBuilder(portname).append(":0").toString();
440         List<Adjacency> adjList = new ArrayList<Adjacency>();
441         InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
442                 child(VpnInterface.class, new VpnInterfaceKey(name)).build();
443         // find router associated to vpn
444         Uuid routerId = NeutronvpnUtils.getRouterforVpn(broker, vpnId);
445         Router rtr = null;
446         if (routerId != null) {
447             rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
448         }
449         // find all Subnets to which this port is associated
450         List<FixedIps> ips = port.getFixedIps();
451         // create adjacency list
452         for (FixedIps ip : ips) {
453             // create vm adjacency
454             StringBuilder IpPrefixBuild = new StringBuilder(ip.getIpAddress().getIpv4Address().getValue());
455             String IpPrefix = IpPrefixBuild.append("/32").toString();
456             Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(IpPrefix)).setIpAddress(IpPrefix)
457                     .setMacAddress(port.getMacAddress()).build();
458             adjList.add(vmAdj);
459             // create extra route adjacency
460             if (rtr != null && rtr.getRoutes() != null) {
461                 List<String> routeList = rtr.getRoutes();
462                 List<Adjacency> erAdjList = addAdjacencyforExtraRoute(routeList, false, name);
463                 if (erAdjList != null) {
464                     adjList.addAll(erAdjList);
465                 }
466             }
467         }
468         // create vpn-interface on this neutron port
469         Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
470         VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(name)).
471                 setName(name).setVpnInstanceName(vpnId.getValue()).addAugmentation(Adjacencies.class, adjs);
472         VpnInterface vpnIf = vpnb.build();
473
474         NeutronvpnUtils.lockVpnInterface(lockManager, name);
475         try {
476             logger.debug("Creating vpn interface {}", vpnIf);
477             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
478         } catch (Exception ex) {
479             logger.error("Creation of vpninterface {} failed due to {}", name, ex);
480         } finally {
481             NeutronvpnUtils.unlockVpnInterface(lockManager, name);
482         }
483     }
484
485     private void deleteVpnInterface(Port port) {
486
487         if (port != null) {
488             String pname = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
489             String name = new StringBuilder(pname).append(":0").toString();
490             InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
491                     child(VpnInterface.class, new VpnInterfaceKey(name)).build();
492
493             NeutronvpnUtils.lockVpnInterface(lockManager, name);
494             try {
495                 logger.debug("Deleting vpn interface {}", name);
496                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
497             } catch (Exception ex) {
498                 logger.error("Deletion of vpninterface {} failed due to {}", name, ex);
499             } finally {
500                 NeutronvpnUtils.unlockVpnInterface(lockManager, name);
501             }
502         }
503     }
504
505     // adds port to subnet list and creates vpnInterface
506     private Uuid addPortToSubnets(Port port) {
507         Uuid subnetId = null;
508         Uuid vpnId = null;
509         String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
510
511         // find all Subnets to which this port is associated,
512         List<FixedIps> ips = port.getFixedIps();
513         for (FixedIps ip : ips) {
514             String ipValue = ip.getIpAddress().getIpv4Address().getValue();
515
516             InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
517             PortFixedipToPortNameBuilder builder = new PortFixedipToPortNameBuilder().setPortFixedip(ipValue)
518                     .setPortName(name);
519             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
520             logger.debug("fixedIp-name map for neutron port with fixedIp: {}, name: {} added to NeutronPortData DS",
521                     ipValue, name);
522
523             subnetId = ip.getSubnetId();
524             Subnetmap subnetmap = updateSubnetNode(subnetId, null, null, null, null, port.getUuid());
525             if (vpnId == null && subnetmap != null) {
526                 vpnId = subnetmap.getVpnId();
527             }
528         }
529         return vpnId;
530     }
531
532     private Uuid removePortFromSubnets(Port port) {
533         Uuid subnetId = null;
534         Uuid vpnId = null;
535
536         // find all Subnets to which this port is associated,
537         List<FixedIps> ips = port.getFixedIps();
538         for (FixedIps ip : ips) {
539             String ipValue = ip.getIpAddress().getIpv4Address().getValue();
540
541             InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
542             MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
543             logger.debug("fixedIp-name map for neutron port with fixedIp: {} deleted from NeutronPortData DS",
544                     ipValue);
545
546             subnetId = ip.getSubnetId();
547             Subnetmap subnetmap = removeFromSubnetNode(subnetId, null, null, null, port.getUuid());
548             if (vpnId == null && subnetmap != null) {
549                 vpnId = subnetmap.getVpnId();
550             }
551         }
552         return vpnId;
553     }
554
555     protected void handleNeutronPortCreated(Port port) {
556         logger.info("Of-port-interface creation");
557         int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
558         // Create of-port interface for this neutron port
559         createOfPortInterface(port, portVlanId);
560         logger.debug("Add port to subnet");
561         // add port to local Subnets DS
562         Uuid vpnId = addPortToSubnets(port);
563
564         if (vpnId != null) {
565             // create vpn-interface on this neutron port
566             logger.debug("Adding VPN Interface");
567             createVpnInterface(vpnId, port);
568         }
569     }
570
571     protected void handleNeutronPortDeleted(Port port) {
572         logger.debug("Of-port-interface removal");
573         logger.debug("Remove port from subnet");
574         // remove port from local Subnets DS
575         Uuid vpnId = removePortFromSubnets(port);
576
577         if (vpnId != null) {
578             // remove vpn-interface for this neutron port
579             logger.debug("removing VPN Interface");
580             deleteVpnInterface(port);
581         }
582         int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
583         // Remove of-port interface for this neutron port
584         deleteOfPortInterface(port, portVlanId);
585
586     }
587
588     protected void handleNeutronPortUpdated(Port portoriginal, Port portupdate) {
589         logger.debug("Add port to subnet");
590         // add port FixedIPs to local Subnets DS
591         Uuid vpnIdup = addPortToSubnets(portupdate);
592
593         if (vpnIdup != null) {
594             createVpnInterface(vpnIdup, portupdate);
595         }
596
597         // remove port FixedIPs from local Subnets DS
598         Uuid vpnIdor = removePortFromSubnets(portoriginal);
599
600         if (vpnIdor != null) {
601             deleteVpnInterface(portoriginal);
602         }
603     }
604
605     public void createL3Vpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
606                             Uuid router, List<Uuid> networks) {
607
608         // Update VPN Instance node
609         updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
610
611         // Update local vpn-subnet DS
612         updateVpnMaps(vpn, name, router, tenant, networks);
613
614         if (router != null) {
615             associateRouterToVpn(vpn, router);
616         }
617         if (networks != null) {
618             associateNetworksToVpn(vpn, networks);
619         }
620     }
621
622     @Override
623     public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
624
625         CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
626         SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
627         List<RpcError> errorList = new ArrayList<RpcError>();
628         int failurecount = 0;
629         int warningcount = 0;
630
631         List<L3vpn> vpns = input.getL3vpn();
632         for (L3vpn vpn : vpns) {
633             RpcError error;
634             String msg;
635             if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
636                 msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
637                         vpn.getId().getValue());
638                 logger.warn(msg);
639                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
640                 errorList.add(error);
641                 warningcount++;
642                 continue;
643             }
644             if (vpn.getRouteDistinguisher().size() > 1) {
645                 msg = String.format("Creation of L3VPN failed for VPN %s due to multiple RD input %s",
646                         vpn.getId().getValue(), vpn.getRouteDistinguisher());
647                 logger.warn(msg);
648                 error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
649                 errorList.add(error);
650                 warningcount++;
651                 continue;
652             }
653             try {
654                 createL3Vpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
655                         vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds());
656             } catch (Exception ex) {
657                 msg = String.format("Creation of L3VPN failed for VPN %s", vpn.getId().getValue());
658                 logger.error(msg, ex.getMessage());
659                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
660                 errorList.add(error);
661                 failurecount++;
662             }
663         }
664         // if at least one succeeds; result is success
665         // if none succeeds; result is failure
666         if (failurecount + warningcount == vpns.size()) {
667             result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
668         } else {
669             List<String> errorResponseList = new ArrayList<>();
670             if (!errorList.isEmpty()) {
671                 for (RpcError rpcError : errorList) {
672                     String errorResponse = String.format("ErrorType: " + rpcError.getErrorType() + ", " + "ErrorTag: " +
673                             rpcError.getTag() + ", " + "ErrorMessage: " + rpcError.getMessage());
674                     errorResponseList.add(errorResponse);
675                 }
676             } else {
677                 errorResponseList.add("Operation successful with no errors");
678             }
679             opBuilder.setResponse(errorResponseList);
680             result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
681         }
682         return result;
683     }
684
685     @Override
686     public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
687
688         GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
689         SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
690         Uuid inputVpnId = input.getId();
691         List<VpnInstance> vpns = new ArrayList<VpnInstance>();
692
693         try {
694             if (inputVpnId == null) {
695                 // get all vpns
696                 InstanceIdentifier<VpnInstances> vpnsIdentifier =
697                         InstanceIdentifier.builder(VpnInstances.class).build();
698                 Optional<VpnInstances> optionalVpns = read(LogicalDatastoreType.CONFIGURATION, vpnsIdentifier);
699                 if (optionalVpns.isPresent()) {
700                     for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
701                         vpns.add(vpn);
702                     }
703                 } else {
704                     // No VPN present
705                     result.set(RpcResultBuilder.<GetL3VPNOutput>failed()
706                             .withWarning(ErrorType.PROTOCOL, "", "No VPN is present").build());
707                     return result;
708                 }
709             } else {
710                 String name = inputVpnId.getValue();
711                 InstanceIdentifier<VpnInstance> vpnIdentifier =
712                         InstanceIdentifier.builder(VpnInstances.class)
713                                 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
714                 // read VpnInstance Info
715                 Optional<VpnInstance> optionalVpn = read(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
716                 if (optionalVpn.isPresent()) {
717                     vpns.add(optionalVpn.get());
718                 } else {
719                     String message = String.format("GetL3VPN failed because VPN %s is not present", name);
720                     logger.error(message);
721                     result.set(RpcResultBuilder.<GetL3VPNOutput>failed()
722                             .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
723                 }
724             }
725             List<L3vpnInstances> l3vpnList = new ArrayList<L3vpnInstances>();
726             for (VpnInstance vpnInstance : vpns) {
727                 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
728                 // create VpnMaps id
729                 InstanceIdentifier<VpnMap> vpnMapIdentifier =
730                         InstanceIdentifier.builder(VpnMaps.class)
731                                 .child(VpnMap.class, new VpnMapKey(vpnId)).build();
732                 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
733
734                 List<String> rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(","));
735                 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
736
737                 List<String> ertList = new ArrayList<String>();
738                 List<String> irtList = new ArrayList<String>();
739
740                 for (VpnTarget vpnTarget : vpnTargetList) {
741                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
742                         ertList.add(vpnTarget.getVrfRTValue());
743                     }
744                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
745                         irtList.add(vpnTarget.getVrfRTValue());
746                     }
747                     if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
748                         ertList.add(vpnTarget.getVrfRTValue());
749                         irtList.add(vpnTarget.getVrfRTValue());
750                     }
751                 }
752
753                 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
754                 Optional<VpnMap> optionalVpnMap =
755                         read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
756                 if (optionalVpnMap.isPresent()) {
757                     VpnMap vpnMap = optionalVpnMap.get();
758                     l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
759                             .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
760                 }
761                 l3vpnList.add(l3vpn.build());
762             }
763
764             opBuilder.setL3vpnInstances(l3vpnList);
765             result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
766
767         } catch (Exception ex) {
768             String message = String.format("GetL3VPN failed due to %s", ex.getMessage());
769             logger.error(message);
770             result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
771         }
772
773         return result;
774     }
775
776     @Override
777     public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
778
779         DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
780         SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
781         List<RpcError> errorList = new ArrayList<RpcError>();
782
783         int failurecount = 0;
784         int warningcount = 0;
785         List<Uuid> vpns = input.getId();
786         for (Uuid vpn : vpns) {
787             RpcError error;
788             String msg;
789             try {
790                 InstanceIdentifier<VpnInstance> vpnIdentifier =
791                         InstanceIdentifier.builder(VpnInstances.class)
792                                 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
793                 Optional<VpnInstance> optionalVpn = read(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
794                 if (optionalVpn.isPresent()) {
795                     removeL3Vpn(vpn);
796                 } else {
797                     msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
798                     logger.warn(msg);
799                     error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
800                     errorList.add(error);
801                     warningcount++;
802                 }
803             } catch (Exception ex) {
804                 msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
805                 logger.error(msg, ex.getMessage());
806                 error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
807                 errorList.add(error);
808                 failurecount++;
809             }
810         }
811         // if at least one succeeds; result is success
812         // if none succeeds; result is failure
813         if (failurecount + warningcount == vpns.size()) {
814             result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
815         } else {
816             List<String> errorResponseList = new ArrayList<>();
817             if (!errorList.isEmpty()) {
818                 for (RpcError rpcError : errorList) {
819                     String errorResponse = String.format("ErrorType: " + rpcError.getErrorType() + ", " + "ErrorTag: " +
820                             rpcError.getTag() + ", " + "ErrorMessage: " + rpcError.getMessage());
821                     errorResponseList.add(errorResponse);
822                 }
823             } else {
824                 errorResponseList.add("Operation successful with no errors");
825             }
826             opBuilder.setResponse(errorResponseList);
827             result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
828         }
829         return result;
830     }
831
832     protected void addSubnetToVpn(Uuid vpnId, Uuid subnet) {
833         logger.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
834         Subnetmap sn = updateSubnetNode(subnet, null, null, null, vpnId, null);
835         // Check if there are ports on this subnet and add corresponding vpn-interfaces
836         List<Uuid> portList = sn.getPortList();
837         if (portList != null) {
838             for (Uuid port : sn.getPortList()) {
839                 logger.debug("adding vpn-interface for port {}", port.getValue());
840                 createVpnInterface(vpnId, getNeutronPort(port));
841             }
842         }
843     }
844
845     protected List<Adjacency> addAdjacencyforExtraRoute(List<String> routeList, boolean rtrUp, String vpnifname) {
846         try {
847             List<Adjacency> adjList = new ArrayList<Adjacency>();
848             for (String route : routeList) {
849                 // assuming extra route is strictly in the format "nexthop destination" > "10.1.1.10 40.0.1.0/24"
850                 String[] parts = route.split(" ");
851                 if (parts.length == 2) {
852                     String nextHop = parts[0];
853                     String destination = parts[1];
854
855                     String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
856                     String ifname = new StringBuilder(tapPortName).append(":0").toString();
857                     logger.trace("Adding extra route with nexthop {}, destination {}, ifName {}", nextHop,
858                             destination, ifname);
859                     Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination).setNextHopIp(nextHop).setKey
860                             (new AdjacencyKey(destination)).build();
861                     if (rtrUp == false) {
862                         if (ifname.equals(vpnifname)) {
863                             adjList.add(erAdj);
864                         }
865                         continue;
866                     }
867                     InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
868                             child(VpnInterface.class, new VpnInterfaceKey(ifname)).build();
869                     Optional<VpnInterface> optionalVpnInterface = read(LogicalDatastoreType.CONFIGURATION,
870                             vpnIfIdentifier);
871                     if (optionalVpnInterface.isPresent()) {
872                         Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(erAdj)).build();
873                         VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(ifname))
874                                 .addAugmentation(Adjacencies.class, erAdjs).build();
875                         MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
876                         logger.trace("extra route {} added successfully", route);
877                     } else {
878                         logger.error("VM adjacency for interface {} not present ; cannot add extra route adjacency",
879                                 ifname);
880                     }
881                 } else {
882                     logger.error("Incorrect input received for extra route. {}", parts);
883                 }
884             }
885             return adjList;
886         } catch (Exception e) {
887             logger.error("exception in adding extra route: {}" + e);
888         }
889         return null;
890     }
891
892     protected void removeAdjacencyforExtraRoute(List<String> routeList) {
893         try {
894             for (String route : routeList) {
895                 // assuming extra route is strictly in the format "nexthop destination" > "10.1.1.10 40.0.1.0/24"
896                 String[] parts = route.split(" ");
897                 if (parts.length == 2) {
898                     String nextHop = parts[0];
899                     String destination = parts[1];
900
901                     String tapPortName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
902                     String ifname = new StringBuilder(tapPortName).append(":0").toString();
903                     logger.trace("Removing extra route with nexthop {}, destination {}, ifName {}", nextHop,
904                             destination, ifname);
905                     InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
906                             child(VpnInterface.class, new VpnInterfaceKey(ifname)).augmentation(Adjacencies.class)
907                             .child(Adjacency.class, new AdjacencyKey(destination)).build();
908                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
909                     logger.trace("extra route {} deleted successfully", route);
910                 } else {
911                     logger.error("Incorrect input received for extra route. {}", parts);
912                 }
913             }
914         } catch (Exception e) {
915             logger.error("exception in deleting extra route: {}" + e);
916         }
917     }
918
919     protected void addPortToVpn(Uuid vpnId, Uuid port) {
920         logger.debug("Adding Port to vpn node...");
921         createVpnInterface(vpnId, getNeutronPort(port));
922     }
923
924     protected void removeL3Vpn(Uuid id) {
925         // read VPN networks
926         VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, id);
927         Uuid router = vpnMap.getRouterId();
928         // dissociate router
929         if (router != null) {
930             dissociateRouterFromVpn(id, router);
931         }
932         // dissociate networks
933         if (!id.equals(router)) {
934             dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
935         }
936         // remove entire vpnMaps node
937         deleteVpnMapsNode(id);
938
939         // remove vpn-instance
940         deleteVpnInstance(id);
941     }
942
943     protected void removePortFromVpn(Uuid vpnId, Uuid port) {
944         logger.debug("Removing Port from vpn node...");
945         deleteVpnInterface(getNeutronPort(port));
946     }
947
948     protected void removeSubnetFromVpn(Uuid vpnId, Uuid subnet) {
949         logger.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
950         Subnetmap sn = NeutronvpnUtils.getSubnetmap(broker, subnet);
951         if (sn != null) {
952             // Check if there are ports on this subnet; remove corresponding vpn-interfaces
953             List<Uuid> portList = sn.getPortList();
954             if (portList != null) {
955                 for (Uuid port : sn.getPortList()) {
956                     logger.debug("removing vpn-interface for port {}", port.getValue());
957                     deleteVpnInterface(getNeutronPort(port));
958                 }
959             }
960             // update subnet-vpn association
961             removeFromSubnetNode(subnet, null, null, vpnId, null);
962         } else {
963             logger.warn("Subnetmap for subnet {} not found", subnet.getValue());
964         }
965     }
966
967     protected void associateRouterToVpn(Uuid vpn, Uuid router) {
968
969         // remove existing Router-VPN
970         if (!vpn.equals(router)) {
971             removeL3Vpn(router);
972         }
973         updateVpnMaps(vpn, null, router, null, null);
974
975         List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
976         logger.debug("Adding subnets...");
977         for (Uuid subnet : routerSubnets) {
978             addSubnetToVpn(vpn, subnet);
979         }
980     }
981
982     protected void dissociateRouterFromVpn(Uuid vpn, Uuid router) {
983         clearFromVpnMaps(vpn, router, null);
984
985         // fetching sn from SubnetmapDS for internal VPN because sn already deleted from RouterIf DS on router deletion
986         List<Uuid> routerSubnets = (vpn.equals(router)) ? getSubnetsforVpn(vpn) :
987                 NeutronvpnUtils.getNeutronRouterSubnetIds(broker, router);
988
989         logger.debug("dissociateRouter vpn {} router {} Removing subnets...", vpn.getValue(), router.getValue());
990         if (routerSubnets != null) {
991             for (Uuid subnet : routerSubnets) {
992                 removeSubnetFromVpn(vpn, subnet);
993             }
994         }
995         // create Router-VPN for this router
996         if (!vpn.equals(router)) {
997             logger.debug("Re-creating vpn-router...");
998             createL3Vpn(router, null, null, null, null, null, router, null);
999         }
1000     }
1001
1002     protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
1003         List<String> failed = new ArrayList<String>();
1004         if (!networks.isEmpty()) {
1005             // store in Data Base
1006             updateVpnMaps(vpn, null, null, null, networks);
1007             // process corresponding subnets for VPN
1008             for (Uuid nw : networks) {
1009                 if (NeutronvpnUtils.getNeutronNetwork(broker, nw) == null) {
1010                     failed.add(nw.getValue());
1011                 } else {
1012                     List<Uuid> networkSubnets = NeutronvpnUtils.getNeutronNetworkSubnetIds(broker, nw);
1013                     logger.debug("Adding network subnets...");
1014                     if (networkSubnets != null) {
1015                         for (Uuid subnet : networkSubnets) {
1016                             addSubnetToVpn(vpn, subnet);
1017                         }
1018                     }
1019                 }
1020             }
1021         }
1022         return failed;
1023     }
1024
1025     protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
1026         List<String> failed = new ArrayList<String>();
1027         if (networks != null && !networks.isEmpty()) {
1028             // store in Data Base
1029             clearFromVpnMaps(vpn, null, networks);
1030             // process corresponding subnets for VPN
1031             for (Uuid nw : networks) {
1032                 if (NeutronvpnUtils.getNeutronNetwork(broker, nw) == null) {
1033                     failed.add(nw.getValue());
1034                 } else {
1035                     List<Uuid> networkSubnets = NeutronvpnUtils.getNeutronNetworkSubnetIds(broker, nw);
1036                     logger.debug("Removing network subnets...");
1037                     for (Uuid subnet : networkSubnets) {
1038                         removeSubnetFromVpn(vpn, subnet);
1039                     }
1040                 }
1041             }
1042         }
1043         return failed;
1044     }
1045
1046     @Override
1047     public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
1048
1049         AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
1050         SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
1051         logger.debug("associateNetworks {}", input);
1052         StringBuilder returnMsg = new StringBuilder();
1053         Uuid vpnId = input.getVpnId();
1054
1055         try {
1056             if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
1057                 List<Uuid> netIds = input.getNetworkId();
1058                 if (netIds != null && !netIds.isEmpty()) {
1059                     List<String> failed = associateNetworksToVpn(vpnId, netIds);
1060                     if (!failed.isEmpty()) {
1061                         returnMsg.append("network(s) not found : ").append(failed);
1062                     }
1063                 }
1064             } else {
1065                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1066             }
1067             if (returnMsg.length() != 0) {
1068                 String message = String.format("associate Networks to vpn %s failed due to %s", vpnId.getValue(),
1069                         returnMsg);
1070                 logger.error(message);
1071                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
1072                         message);
1073                 opBuilder.setResponse(errorResponse);
1074                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
1075             } else {
1076                 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
1077             }
1078         } catch (Exception ex) {
1079             String message = String.format("associate Networks to vpn %s failed due to %s", input.getVpnId().getValue(),
1080                     ex.getMessage());
1081             logger.error(message);
1082             result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1083                     .build());
1084         }
1085         logger.debug("associateNetworks returns..");
1086         return result;
1087     }
1088
1089     @Override
1090     public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
1091
1092         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1093         logger.debug("associateRouter {}", input);
1094         StringBuilder returnMsg = new StringBuilder();
1095         Uuid vpnId = input.getVpnId();
1096         Uuid routerId = input.getRouterId();
1097         try {
1098             if (routerId != null && vpnId != null) {
1099                 Router rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
1100                 VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, vpnId);
1101                 if (rtr != null && vpnMap != null) {
1102                     if (vpnMap.getRouterId() != null) {
1103                         returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
1104                                 .append(vpnMap.getRouterId().getValue());
1105                     } else {
1106                         associateRouterToVpn(vpnId, routerId);
1107                     }
1108                 } else {
1109                     returnMsg.append("router not found : ").append(routerId.getValue());
1110                 }
1111             } else {
1112                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1113             }
1114             if (returnMsg.length() != 0) {
1115                 String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
1116                         returnMsg);
1117                 logger.error(message);
1118                 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1119                         .build());
1120             } else {
1121                 result.set(RpcResultBuilder.<Void>success().build());
1122             }
1123         } catch (Exception ex) {
1124             String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
1125                     vpnId.getValue(), ex.getMessage());
1126             logger.error(message);
1127             result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1128         }
1129         logger.debug("associateRouter returns..");
1130         return result;
1131     }
1132
1133     @Override
1134     public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
1135
1136         DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
1137         SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
1138
1139         logger.debug("dissociateNetworks {}", input);
1140         StringBuilder returnMsg = new StringBuilder();
1141         Uuid vpnId = input.getVpnId();
1142
1143         try {
1144             if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
1145                 List<Uuid> netIds = input.getNetworkId();
1146                 if (netIds != null && !netIds.isEmpty()) {
1147                     List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
1148                     if (!failed.isEmpty()) {
1149                         returnMsg.append("netowrk(s) not found : ").append(failed);
1150                     }
1151                 }
1152             } else {
1153                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1154             }
1155             if (returnMsg.length() != 0) {
1156                 String message = String.format("disssociate Networks to vpn %s failed due to %s", vpnId.getValue(),
1157                         returnMsg);
1158                 logger.error(message);
1159                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
1160                         message);
1161                 opBuilder.setResponse(errorResponse);
1162                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
1163             } else {
1164                 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
1165             }
1166         } catch (Exception ex) {
1167             String message = String.format("dissociate Networks to vpn %s failed due to %s", input.getVpnId().
1168                     getValue(), ex.getMessage());
1169             logger.error(message);
1170             result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
1171                     .build());
1172         }
1173         logger.debug("dissociateNetworks returns..");
1174         return result;
1175     }
1176
1177     @Override
1178     public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
1179
1180         SettableFuture<RpcResult<Void>> result = SettableFuture.create();
1181
1182         logger.debug("dissociateRouter {}", input);
1183         StringBuilder returnMsg = new StringBuilder();
1184         Uuid vpnId = input.getVpnId();
1185         Uuid routerId = input.getRouterId();
1186         try {
1187             if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
1188                 if (routerId != null) {
1189                     Router rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
1190                     if (rtr != null) {
1191                         dissociateRouterFromVpn(vpnId, routerId);
1192                     } else {
1193                         returnMsg.append("router not found : ").append(routerId.getValue());
1194                     }
1195                 }
1196             } else {
1197                 returnMsg.append("VPN not found : ").append(vpnId.getValue());
1198             }
1199             if (returnMsg.length() != 0) {
1200                 String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
1201                         vpnId.getValue(), returnMsg);
1202                 logger.error(message);
1203                 String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
1204                         message);
1205                 result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
1206                         .build());
1207             } else {
1208                 result.set(RpcResultBuilder.<Void>success().build());
1209             }
1210         } catch (Exception ex) {
1211             String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
1212                     vpnId.getValue(), ex.getMessage());
1213             logger.error(message);
1214             result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
1215         }
1216         logger.debug("dissociateRouter returns..");
1217
1218         return result;
1219     }
1220
1221     private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
1222
1223         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
1224
1225         Optional<T> result = Optional.absent();
1226         try {
1227             result = tx.read(datastoreType, path).get();
1228         } catch (Exception e) {
1229             throw new RuntimeException(e);
1230         }
1231
1232         return result;
1233     }
1234
1235     protected Subnet getNeutronSubnet(Uuid subnetId) {
1236         InstanceIdentifier<Subnet> inst = InstanceIdentifier.create(Neutron.class).
1237                 child(Subnets.class).child(Subnet.class, new SubnetKey(subnetId));
1238         Optional<Subnet> sn = read(LogicalDatastoreType.CONFIGURATION, inst);
1239
1240         if (sn.isPresent()) {
1241             return sn.get();
1242         }
1243         return null;
1244     }
1245
1246     protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
1247         Subnet sn = getNeutronSubnet(subnetId);
1248         if (null != sn) {
1249             return sn.getGatewayIp();
1250         }
1251         return null;
1252     }
1253
1254     protected Port getNeutronPort(String name) {
1255         Uuid portId = NeutronvpnUtils.getNeutronPortIdfromPortName(broker, name);
1256         if (portId != null) {
1257             InstanceIdentifier<Port> pid = InstanceIdentifier.create(Neutron.class).
1258                     child(Ports.class).child(Port.class, new PortKey(portId));
1259             Optional<Port> optPort = read(LogicalDatastoreType.CONFIGURATION, pid);
1260             if (optPort.isPresent()) {
1261                 return optPort.get();
1262             }
1263         } else {
1264             logger.error("Port {} not Found!!", name);
1265         }
1266         return null;
1267     }
1268
1269     protected Port getNeutronPort(Uuid portId) {
1270         InstanceIdentifier<Port> pid = InstanceIdentifier.create(Neutron.class).
1271                 child(Ports.class).child(Port.class, new PortKey(portId));
1272         Optional<Port> optPort = read(LogicalDatastoreType.CONFIGURATION, pid);
1273         if (optPort.isPresent()) {
1274             return optPort.get();
1275         }
1276         return null;
1277     }
1278
1279     protected List<Uuid> getSubnetsforVpn(Uuid vpnid) {
1280         List<Uuid> subnets = new ArrayList<Uuid>();
1281         //read subnetmaps
1282         InstanceIdentifier<Subnetmaps> subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build();
1283         Optional<Subnetmaps> subnetmaps = read(LogicalDatastoreType.CONFIGURATION, subnetmapsid);
1284         if (subnetmaps.isPresent()) {
1285             Subnetmaps smaps = subnetmaps.get();
1286             List<Subnetmap> subnetMapList = smaps.getSubnetmap();
1287             for (Subnetmap subnetMap : subnetMapList) {
1288                 if (subnetMap.getVpnId() != null && subnetMap.getVpnId().equals(vpnid)) {
1289                     subnets.add(subnetMap.getId());
1290                 }
1291             }
1292         }
1293         return subnets;
1294     }
1295
1296     public List<String> showNeutronPortsCLI() {
1297         List<String> result = new ArrayList<String>();
1298         result.add(String.format(" %-22s  %-22s  %-22s  %-6s ", "PortName", "Mac Address", "IP Address",
1299                 "Prefix Length"));
1300         result.add("---------------------------------------------------------------------------------------");
1301         InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
1302         try {
1303             Optional<Ports> ports = read(LogicalDatastoreType.CONFIGURATION, portidentifier);
1304             if (ports.isPresent()) {
1305                 List<Port> portList = ports.get().getPort();
1306                 for (Port port : portList) {
1307                     result.add(String.format(" %-22s  %-22s  %-22s  %-6s ", NeutronvpnUtils.uuidToTapPortName(port
1308                             .getUuid()), port.getMacAddress(), port.getFixedIps().get(0).getIpAddress().getIpv4Address()
1309                             .getValue(), getIPPrefixFromPort(port)));
1310                 }
1311             }
1312         } catch (Exception e) {
1313             logger.trace("Failed to retrieve neutronPorts info : ", e);
1314             System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
1315         }
1316         return result;
1317     }
1318
1319     private Short getIPPrefixFromPort(Port port) {
1320         Short prefix = new Short((short) 0);
1321         String cidr = "";
1322         try {
1323             Uuid subnetUUID = port.getFixedIps().get(0).getSubnetId();
1324
1325             org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets
1326                     .SubnetKey subnetkey = new org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets
1327                     .rev150712.subnets.attributes.subnets.SubnetKey(subnetUUID);
1328             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
1329                     .attributes.subnets.Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class).child(org
1330                     .opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets
1331                     .class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets
1332                     .attributes.subnets.Subnet.class, subnetkey);
1333             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes
1334                     .subnets.Subnet> subnet = read(LogicalDatastoreType.CONFIGURATION, subnetidentifier);
1335
1336             if (subnet.isPresent()) {
1337                 cidr = subnet.get().getCidr();
1338                 // Extract the prefix length from cidr
1339                 String[] parts = cidr.split("/");
1340                 if ((parts.length == 2)) {
1341                     prefix = Short.valueOf(parts[1]);
1342                     return prefix;
1343                 } else {
1344                     logger.trace("Could not retrieve prefix from subnet CIDR");
1345                     System.out.println("Could not retrieve prefix from subnet CIDR");
1346                 }
1347             } else {
1348                 logger.trace("Unable to read on subnet datastore");
1349             }
1350         } catch (Exception e) {
1351             logger.trace("Failed to retrieve IP prefix from port : ", e);
1352             System.out.println("Failed to retrieve IP prefix from port : " + e.getMessage());
1353         }
1354         return null;
1355     }
1356
1357     public List<String> showVpnConfigCLI(Uuid vpnuuid) {
1358         List<String> result = new ArrayList<String>();
1359         if (vpnuuid == null) {
1360             System.out.println("");
1361             System.out.println("Displaying VPN config for all VPNs");
1362             System.out.println("To display VPN config for a particular VPN, use the following syntax");
1363             System.out.println(getshowVpnConfigCLIHelp());
1364         }
1365         try {
1366             RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
1367             if (rpcResult.isSuccessful()) {
1368                 result.add("");
1369                 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
1370                 result.add("");
1371                 result.add(String.format(" %-80s ", "Import-RTs"));
1372                 result.add("");
1373                 result.add(String.format(" %-80s ", "Export-RTs"));
1374                 result.add("");
1375                 result.add(String.format(" %-76s ", "Subnet IDs"));
1376                 result.add("");
1377                 result.add("------------------------------------------------------------------------------------");
1378                 result.add("");
1379                 List<L3vpnInstances> VpnList = rpcResult.getResult().getL3vpnInstances();
1380                 for (L3vpnInstance Vpn : VpnList) {
1381                     String tenantId = Vpn.getTenantId() != null ? Vpn.getTenantId().getValue() : "\"                 " +
1382                             "                  \"";
1383                     result.add(String.format(" %-37s %-37s %-7s ", Vpn.getId().getValue(), tenantId, Vpn
1384                             .getRouteDistinguisher()));
1385                     result.add("");
1386                     result.add(String.format(" %-80s ", Vpn.getImportRT()));
1387                     result.add("");
1388                     result.add(String.format(" %-80s ", Vpn.getExportRT()));
1389                     result.add("");
1390
1391                     Uuid vpnid = Vpn.getId();
1392                     List<Uuid> subnetList = getSubnetsforVpn(vpnid);
1393                     if (!subnetList.isEmpty()) {
1394                         for (Uuid subnetuuid : subnetList) {
1395                             result.add(String.format(" %-76s ", subnetuuid.getValue()));
1396                         }
1397                     } else {
1398                         result.add(String.format(" %-76s ", "\"                                    \""));
1399                     }
1400                     result.add("");
1401                     result.add("----------------------------------------");
1402                     result.add("");
1403                 }
1404             } else {
1405                 String errortag = rpcResult.getErrors().iterator().next().getTag();
1406                 if (errortag == "") {
1407                     System.out.println("");
1408                     System.out.println("No VPN has been configured yet");
1409                 } else if (errortag == "invalid-value") {
1410                     System.out.println("");
1411                     System.out.println("VPN " + vpnuuid.getValue() + " is not present");
1412                 } else {
1413                     System.out.println("error getting VPN info : " + rpcResult.getErrors());
1414                     System.out.println(getshowVpnConfigCLIHelp());
1415                 }
1416             }
1417         } catch (InterruptedException | ExecutionException e) {
1418             logger.trace("error getting VPN info : ", e);
1419             System.out.println("error getting VPN info : " + e.getMessage());
1420         }
1421         return result;
1422     }
1423
1424     private String getshowVpnConfigCLIHelp() {
1425         StringBuilder help = new StringBuilder("Usage:");
1426         help.append("display vpn-config [-vid/--vpnid <id>]");
1427         return help.toString();
1428     }
1429
1430 }