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