478dda2229d19bd5e991181be174804931ef8812
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / cli / TepCommandHelper.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.genius.itm.cli;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import org.apache.commons.lang3.StringUtils;
18 import org.apache.commons.net.util.SubnetUtils;
19 import org.apache.felix.service.command.CommandSession;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
23 import org.opendaylight.genius.itm.globals.ITMConstants;
24 import org.opendaylight.genius.utils.cache.DataStoreCache;
25 import org.opendaylight.genius.itm.impl.ItmUtils;
26 import org.opendaylight.genius.mdsalutil.MDSALDataStoreUtils;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBfd;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorInterval;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorIntervalBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorParams;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorParamsBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZonesBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
61 import org.opendaylight.yangtools.yang.binding.DataObject;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 //import org.opendaylight.genius.interfacemgr.util.OperationalIfmUtil;
67
68
69 public class TepCommandHelper {
70
71     private static final Logger LOG = LoggerFactory.getLogger(TepCommandHelper.class);
72     private DataBroker dataBroker;
73     static int check = 0;
74     static short flag = 0;
75     /*
76      * boolean flag add_or_delete --- can be set to true if the last called tep
77      * command is Tep-add else set to false when Tep-delete is called
78      * tepCommandHelper object is created only once in session initiated
79      */
80     final Map<String, Map<SubnetObject, List<Vteps>>> tZones = new HashMap<>();
81     private List<Subnets> subnetList = new ArrayList<>();
82     private List<TransportZone> tZoneList = new ArrayList<>();
83     private List<Vteps> vtepDelCommitList = new ArrayList<>();
84     private IInterfaceManager interfaceManager;
85
86     // private List<InstanceIdentifier<? extends DataObject>> vtepPaths = new
87     // ArrayList<>();
88
89
90     public TepCommandHelper(final DataBroker broker) {
91         this.dataBroker = broker;
92     }
93
94
95     public void setInterfaceManager(IInterfaceManager interfaceManager) {
96         this.interfaceManager = interfaceManager;
97     }
98
99     public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress,
100                                  String subnetMask, String gatewayIp, String transportZone, CommandSession session) throws TepException{
101
102         check++;
103         IpAddress ipAddressObj = null;
104         IpAddress gatewayIpObj = null;
105         IpPrefix subnetMaskObj = null;
106         VtepsKey vtepkey = new VtepsKey(dpnId, portName);
107         try {
108             ipAddressObj = new IpAddress(ipAddress.toCharArray());
109             gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
110             if (gatewayIp != null) {
111                 gatewayIpObj = new IpAddress(gatewayIp.toCharArray());
112             } else {
113                 LOG.debug("gateway is null");
114             }
115         } catch (Exception e) {
116             handleError("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255", session);
117             return;
118         }
119         try {
120             subnetMaskObj = new IpPrefix(subnetMask.toCharArray());
121         } catch (Exception e) {
122             handleError("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32", session);
123             return;
124         }
125
126         if (!validateIPs(ipAddress, subnetMask, gatewayIp)) {
127             handleError("IpAddress and gateWayIp should belong to the subnet provided", session);
128             return;
129         }
130
131         if (checkTepPerTzPerDpn(transportZone, dpnId)) {
132             if(session  != null) {
133                 session.getConsole().println("Only one end point per transport Zone per Dpn is allowed");
134             }
135             return;
136         }
137         Vteps vtepCli = new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey)
138                 .setPortname(portName).build();
139         validateForDuplicates(vtepCli, transportZone);
140
141         SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj);
142         SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId);
143         if (tZones.containsKey(transportZone)) {
144             Map<SubnetObject, List<Vteps>> subVtepMapTemp = tZones.get(transportZone);
145             if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists
146                 List<Vteps> vtepListTemp = subVtepMapTemp.get(subObCli);
147                 if (vtepListTemp.contains(vtepCli)) {
148                     // do nothing
149                 } else {
150                     vtepListTemp.add(vtepCli);
151                 }
152             } else { // subnet doesnt exist
153                 if (checkExistingSubnet(subVtepMapTemp, subObCli)) {
154                     if(session != null) {
155                         session.getConsole().println("subnet with subnet mask " + subObCli.get_key() + "already exists");
156                     }
157                     return;
158                 }
159                 List<Vteps> vtepListTemp = new ArrayList<>();
160                 vtepListTemp.add(vtepCli);
161                 subVtepMapTemp.put(subObCli, vtepListTemp);
162             }
163         } else {
164             List<Vteps> vtepListTemp = new ArrayList<>();
165             vtepListTemp.add(vtepCli);
166             Map<SubnetObject, List<Vteps>> subVtepMapTemp = new HashMap<>();
167             subVtepMapTemp.put(subObCli, vtepListTemp);
168             tZones.put(transportZone, subVtepMapTemp);
169         }
170     }
171
172     private boolean validateIPs(String ipAddress, String subnetMask, String gatewayIp) {
173         SubnetUtils utils = new SubnetUtils(subnetMask);
174         if ((utils.getInfo().isInRange(ipAddress)) && ((gatewayIp == null) || (utils.getInfo().isInRange(gatewayIp)))) {
175             return true;
176         } else {
177             LOG.trace("InValid IP");
178             return false;
179         }
180     }
181
182     /**
183      * Validate for duplicates.
184      *
185      * @param inputVtep
186      *            the input vtep
187      * @param transportZone
188      *            the transport zone
189      */
190     public void validateForDuplicates(Vteps inputVtep, String transportZone) {
191         Map<String, TransportZone> tZoneMap = getAllTransportZonesAsMap();
192
193         boolean isConfiguredTepGreType = isGreTunnelType(transportZone, tZoneMap);
194         // Checking for duplicates in local cache
195         for (String tZ : tZones.keySet()) {
196             boolean isGreType = isGreTunnelType(tZ, tZoneMap);
197             Map<SubnetObject, List<Vteps>> subVtepMapTemp = tZones.get(tZ);
198             for (SubnetObject subOb : subVtepMapTemp.keySet()) {
199                 List<Vteps> vtepList = subVtepMapTemp.get(subOb);
200                 validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList);
201             }
202         }
203         // Checking for duplicates in config DS
204         for (TransportZone tZ : tZoneMap.values()) {
205             boolean isGreType = false;
206             if (tZ.getTunnelType().equals(TunnelTypeGre.class)) {
207                 isGreType = true;
208             }
209             for (Subnets sub : ItmUtils.emptyIfNull(tZ.getSubnets())) {
210                 List<Vteps> vtepList = sub.getVteps();
211                 validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList);
212             }
213         }
214     }
215
216     private void validateForDuplicateAndSingleGreTep(Vteps inputVtep, boolean isConfiguredTepGreType, boolean isGreType,
217                                                      List<Vteps> vtepList) {
218         if (ItmUtils.isEmpty(vtepList)) {
219             return;
220         }
221         if (vtepList.contains(inputVtep)) {
222             Preconditions.checkArgument(false, "VTEP already exists");
223         }
224         BigInteger dpnId = inputVtep.getDpnId();
225         if (isConfiguredTepGreType && isGreType) {
226             for (Vteps vtep : vtepList) {
227                 if (vtep.getDpnId().equals(dpnId)) {
228                     String errMsg = "DPN [" + dpnId +
229                             "] already configured with GRE TEP. Mutiple GRE TEP's on a single DPN are not allowed.";
230                     Preconditions.checkArgument(false, errMsg);
231                 }
232             }
233         }
234     }
235
236     /**
237      * Gets all transport zones as map.
238      *
239      * @return all transport zones as map
240      */
241     private Map<String, TransportZone> getAllTransportZonesAsMap() {
242         TransportZones tZones = getAllTransportZones();
243         Map<String, TransportZone> tZoneMap = new HashMap<>();
244         if( null != tZones) {
245             for (TransportZone tzone : ItmUtils.emptyIfNull(tZones.getTransportZone())) {
246                 tZoneMap.put(tzone.getZoneName(), tzone);
247             }
248         }
249         return tZoneMap;
250     }
251
252     /**
253      * Checks if is gre tunnel type.
254      *
255      * @param tZoneName
256      *            the zone name
257      * @param tZoneMap
258      *            the zone map
259      * @return true, if is gre tunnel type
260      */
261     private boolean isGreTunnelType(String tZoneName, Map<String, TransportZone> tZoneMap) {
262         TransportZone tzone = tZoneMap.get(tZoneName);
263         /*
264         if (tzone != null && StringUtils.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_GRE, tzone.getTunnelType())) {
265             return true;
266         }
267         */
268         return (tzone != null) && (tzone.getTunnelType()).equals(TunnelTypeGre.class);
269     }
270
271     /**
272      * Gets the transport zone.
273      *
274      * @param tzone
275      *            the tzone
276      * @return the transport zone
277      */
278     public TransportZone getTransportZone(String tzone) {
279         InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
280                 .child(TransportZone.class, new TransportZoneKey(tzone)).build();
281         Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath,
282                 dataBroker);
283         if (tZoneOptional.isPresent()) {
284             return tZoneOptional.get();
285         }
286         return null;
287     }
288
289     /**
290      * Gets the transport zone from config ds.
291      *
292      * @param tzone
293      *            the tzone
294      * @return the transport zone
295      */
296     public TransportZone getTransportZoneFromConfigDS(String tzone) {
297         InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
298                 .child(TransportZone.class, new TransportZoneKey(tzone)).build();
299         Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath,
300                 dataBroker);
301         if (tZoneOptional.isPresent()) {
302             return tZoneOptional.get();
303         }
304         return null;
305     }
306
307     /**
308      * Gets all transport zones.
309      *
310      * @return all transport zones
311      */
312     public TransportZones getAllTransportZones() {
313         InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
314         Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
315         if (tZonesOptional.isPresent()) {
316             return tZonesOptional.get();
317         }
318         return null;
319     }
320
321     public boolean checkExistingSubnet(Map<SubnetObject, List<Vteps>> subVtepMapTemp, SubnetObject subObCli) {
322         for (SubnetObject subOb : subVtepMapTemp.keySet()) {
323             if (subOb.get_key().equals(subObCli.get_key())) {
324                 if (!(subOb.get_vlanId().equals(subObCli.get_vlanId())))
325                     return true;
326                 if (!(subOb.get_gatewayIp().equals(subObCli.get_gatewayIp())))
327                     return true;
328             }
329         }
330         return false;
331     }
332
333     public boolean checkTepPerTzPerDpn(String tzone, BigInteger dpnId) {
334         // check in local cache
335         if (tZones.containsKey(tzone)) {
336             Map<SubnetObject, List<Vteps>> subVtepMapTemp = tZones.get(tzone);
337             for (SubnetObject subOb : subVtepMapTemp.keySet()) {
338                 List<Vteps> vtepList = subVtepMapTemp.get(subOb);
339                 for (Vteps vtep : vtepList)
340                     if (vtep.getDpnId().equals(dpnId))
341                         return true;
342             }
343         }
344
345         // check in DS
346         InstanceIdentifier<TransportZone> tzonePath =
347                 InstanceIdentifier.builder(TransportZones.class)
348                         .child(TransportZone.class, new TransportZoneKey(tzone)).build();
349         Optional<TransportZone> tZoneOptional =
350                 ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
351         if (tZoneOptional.isPresent()) {
352             TransportZone tz = tZoneOptional.get();
353             if (tz.getSubnets() == null || tz.getSubnets().isEmpty())
354                 return false;
355             for (Subnets sub : tz.getSubnets()) {
356                 if (sub.getVteps() == null || sub.getVteps().isEmpty())
357                     continue;
358                 for (Vteps vtep : sub.getVteps()) {
359                     if (vtep.getDpnId().equals(dpnId)) {
360                         return true;
361                     }
362                 }
363             }
364         }
365         return false;
366     }
367
368     public void buildTeps() {
369         TransportZones tZonesBuilt = null;
370         TransportZone tZone = null;
371         try {
372             LOG.debug("no of teps added" + check);
373             if (tZones != null || !tZones.isEmpty()) {
374                 tZoneList = new ArrayList<>();
375                 for (String tZ : tZones.keySet()) {
376                     LOG.debug("tZones" + tZ);
377                     subnetList = new ArrayList<>();
378                     Map<SubnetObject, List<Vteps>> subVtepMapTemp = tZones.get(tZ);
379                     for (SubnetObject subOb : subVtepMapTemp.keySet()) {
380                         LOG.debug("subnets" + subOb.get_prefix());
381                         List<Vteps> vtepList = subVtepMapTemp.get(subOb);
382                         Subnets subnet =
383                                 new SubnetsBuilder().setGatewayIp(subOb.get_gatewayIp())
384                                         .setKey(subOb.get_key()).setPrefix(subOb.get_prefix())
385                                         .setVlanId(subOb.get_vlanId()).setVteps(vtepList).build();
386                         subnetList.add(subnet);
387                         LOG.debug("vteps" + vtepList);
388                     }
389                     InstanceIdentifier<TransportZone> tZonepath =
390                             InstanceIdentifier.builder(TransportZones.class)
391                                     .child(TransportZone.class, new TransportZoneKey(tZ)).build();
392                     Optional<TransportZone> tZoneOptional =
393                             ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tZonepath, dataBroker);
394                     LOG.debug("read container from DS");
395                     if (tZoneOptional.isPresent()) {
396                         TransportZone tzoneFromDs = tZoneOptional.get();
397                         LOG.debug("read tzone container" + tzoneFromDs.toString());
398                         if (tzoneFromDs.getTunnelType() == null
399                                 || (tzoneFromDs.getTunnelType()).equals(TunnelTypeVxlan.class)) {
400                             tZone =
401                                     new TransportZoneBuilder().setKey(new TransportZoneKey(tZ))
402                                             .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList)
403                                             .setZoneName(tZ).build();
404                         } else if ((tzoneFromDs.getTunnelType()).equals(TunnelTypeGre.class)) {
405                             tZone =
406                                     new TransportZoneBuilder().setKey(new TransportZoneKey(tZ))
407                                             .setTunnelType(TunnelTypeGre.class).setSubnets(subnetList)
408                                             .setZoneName(tZ).build();
409                         }
410                     } else {
411                         tZone =
412                                 new TransportZoneBuilder().setKey(new TransportZoneKey(tZ))
413                                         .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList).setZoneName(tZ)
414                                         .build();
415                     }
416                     LOG.debug("tzone object" + tZone);
417                     tZoneList.add(tZone);
418                 }
419                 tZonesBuilt = new TransportZonesBuilder().setTransportZone(tZoneList).build();
420                 InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
421                 LOG.debug("InstanceIdentifier" + path);
422                 ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tZonesBuilt, dataBroker,
423                         ItmUtils.DEFAULT_CALLBACK);
424                 LOG.debug("wrote to Config DS" + tZonesBuilt);
425                 tZones.clear();
426                 tZoneList.clear();
427                 subnetList.clear();
428                 LOG.debug("Everything cleared");
429             } else {
430                 LOG.debug("NO vteps were configured");
431             }
432         } catch (Exception e) {
433             LOG.error(e.getMessage());
434         }
435     }
436
437     public void showTeps(boolean monitorEnabled, int monitorInterval, CommandSession session) throws TepException {
438         boolean flag = false;
439         InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
440         Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
441         if (tZonesOptional.isPresent()) {
442             TransportZones tZones = tZonesOptional.get();
443             if(tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty())
444             {
445                 handleError("No teps configured", session);
446                 return;
447             }
448             List<String> result = new ArrayList<>();
449             result.add(String.format("Tunnel Monitoring (for VXLAN tunnels): %s", (monitorEnabled ? "On" : "Off")));
450             result.add(String.format("Tunnel Monitoring Interval (for VXLAN tunnels): %d", monitorInterval));
451             result.add(System.lineSeparator());
452             result.add(String.format("%-16s  %-16s  %-16s  %-12s  %-12s %-12s %-16s %-12s", "TransportZone", "TunnelType", "SubnetMask",
453                     "GatewayIP", "VlanID", "DpnID", "IPAddress", "PortName"));
454             result.add("------------------------------------------------------------------------------------------------------------------------------");
455             for (TransportZone tZ : tZones.getTransportZone()) {
456                 if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty()) {
457                     LOG.error("Transport Zone " + tZ.getZoneName() + "has no subnets");
458                     continue;
459                 }
460                 for (Subnets sub : tZ.getSubnets()) {
461                     if (sub.getVteps() == null || sub.getVteps().isEmpty()) {
462                         LOG.error("Transport Zone " + tZ.getZoneName() + "subnet " + sub.getPrefix() + "has no vteps");
463                         continue;
464                     }
465                     for (Vteps vtep : sub.getVteps()) {
466                         flag = true;
467                         String strTunnelType ;
468                         if( (tZ.getTunnelType()).equals(TunnelTypeGre.class) )
469                             strTunnelType = ITMConstants.TUNNEL_TYPE_GRE ;
470                         else
471                             strTunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
472                         result.add(String.format("%-16s  %-16s  %-16s  %-12s  %-12s %-12s %-16s %-12s", tZ.getZoneName(), strTunnelType, sub
473                                 .getPrefix().getIpv4Prefix().getValue(), sub.getGatewayIp().getIpv4Address()
474                                 .getValue(), sub.getVlanId().toString(), vtep.getDpnId().toString(), vtep
475                                 .getIpAddress().getIpv4Address().getValue(), vtep.getPortname()));
476                     }
477                 }
478             }
479             if (session != null) {
480                 if (flag) {
481                     for (String p : result) {
482                         session.getConsole().println(p);
483                     }
484                 } else {
485                     session.getConsole().println("No teps to display");
486                 }
487             }
488         } else if(session != null){
489             session.getConsole().println("No teps configured");
490         }
491     }
492
493 public void showCache(String cacheName) {
494
495         if( !DataStoreCache.isCacheValid(cacheName)) {
496             System.out.println( " " + cacheName + " is not a valid Cache Name ") ;
497             return ;
498         }
499         List<Object> keys = null ;
500         keys = DataStoreCache.getKeys(cacheName);
501         if( keys != null && !keys.isEmpty()) {
502             System.out.println( "Dumping the data in cache for " + cacheName ) ;
503             for( Object key : keys ) {
504                 System.out.println( " KEY:  " + key + " Value: " + DataStoreCache.get(cacheName, key) ) ;
505                 System.out.println() ;
506             }
507
508         }else
509             System.out.println( "No data in cache for " + cacheName ) ;
510         }
511
512     public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
513                            String gatewayIp, String transportZone,CommandSession session) throws TepException {
514
515         IpAddress ipAddressObj = null;
516         IpAddress gatewayIpObj = null;
517         IpPrefix subnetMaskObj = null;
518         VtepsKey vtepkey = new VtepsKey(dpnId, portName);
519         try {
520             ipAddressObj = new IpAddress(ipAddress.toCharArray());
521             gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
522             if (gatewayIp != null) {
523                 gatewayIpObj = new IpAddress(gatewayIp.toCharArray());
524             } else {
525                 LOG.debug("gateway is null");
526             }
527         } catch (Exception e) {
528             handleError("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255", session);
529             return;
530         }
531         try {
532             subnetMaskObj = new IpPrefix(subnetMask.toCharArray());
533         } catch (Exception e) {
534             handleError("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32", session);
535             return;
536         }
537
538         if (!validateIPs(ipAddress, subnetMask, gatewayIp)) {
539             handleError("IpAddress and gateWayIp should belong to the subnet provided", session);
540             return;
541         }
542         SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj);
543         Vteps vtepCli = null;
544         Subnets subCli = null;
545
546         InstanceIdentifier<Vteps> vpath =
547                 InstanceIdentifier.builder(TransportZones.class)
548                         .child(TransportZone.class, new TransportZoneKey(transportZone))
549                         .child(Subnets.class, subnetsKey).child(Vteps.class, vtepkey).build();
550
551         // check if present in tzones and delete from cache
552         boolean existsInCache = isInCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone, session);
553         if (!existsInCache) {
554             Optional<Vteps> vtepOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, vpath, dataBroker);
555             if (vtepOptional.isPresent()) {
556                 vtepCli = vtepOptional.get();
557                 if(vtepCli.getIpAddress().equals(ipAddressObj)){
558                     InstanceIdentifier<Subnets> spath =
559                             InstanceIdentifier
560                                     .builder(TransportZones.class)
561                                     .child(TransportZone.class, new TransportZoneKey(transportZone))
562                                     .child(Subnets.class, subnetsKey).build();
563                     Optional<Subnets> subOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, spath, dataBroker);
564                     if (subOptional.isPresent()) {
565                         subCli = subOptional.get();
566                         if(subCli.getGatewayIp().equals(gatewayIpObj) && subCli.getVlanId().equals(vlanId)){
567                             vtepDelCommitList.add(vtepCli);
568                         }
569                         else if(session != null) {
570                                 session.getConsole().println("vtep with this vlan or gateway doesnt exist");
571                         }
572                     }
573                 }
574                 else if(session != null) {
575                         session.getConsole().println("Vtep with this ipaddress doesnt exist");
576                 }
577             } else if(session != null) {
578                     session.getConsole().println("Vtep Doesnt exist");
579             }
580         }
581     }
582
583     public <T extends DataObject> void deleteOnCommit() {
584         List<InstanceIdentifier<T>> vtepPaths = new ArrayList<>();
585         List<InstanceIdentifier<T>> subnetPaths = new ArrayList<>();
586         List<InstanceIdentifier<T>> tzPaths = new ArrayList<>();
587         List<Subnets> subDelList = new ArrayList<>();
588         List<TransportZone> tzDelList = new ArrayList<>();
589         List<Vteps> vtepDelList = new ArrayList<>();
590         List<InstanceIdentifier<T>> allPaths = new ArrayList<>();
591         try {
592             if (vtepDelCommitList != null && !vtepDelCommitList.isEmpty()) {
593                 InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
594                 Optional<TransportZones> tZonesOptional =
595                         ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
596                 if (tZonesOptional.isPresent()) {
597                     TransportZones tZones = tZonesOptional.get();
598                     for (TransportZone tZ : tZones.getTransportZone()) {
599                         if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty())
600                             continue;
601                         for (Subnets sub : tZ.getSubnets()) {
602                             vtepDelList.addAll(vtepDelCommitList);
603                             for (Vteps vtep : vtepDelList) {
604                                 InstanceIdentifier<T> vpath =
605                                         (InstanceIdentifier<T>) InstanceIdentifier
606                                                 .builder(TransportZones.class)
607                                                 .child(TransportZone.class, tZ.getKey())
608                                                 .child(Subnets.class, sub.getKey())
609                                                 .child(Vteps.class, vtep.getKey()).build();
610                                 if (sub.getVteps().remove(vtep)) {
611                                     vtepPaths.add(vpath);
612                                     if (sub.getVteps().size() == 0 || sub.getVteps() == null) {
613                                         subDelList.add(sub);
614                                     }
615
616                                 }
617                             }
618                         }
619                     }
620
621                     for (TransportZone tZ : tZones.getTransportZone()) {
622                         if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty())
623                             continue;
624                         for (Subnets sub : subDelList) {
625                             if (tZ.getSubnets().remove(sub)) {
626                                 InstanceIdentifier<T> spath =
627                                         (InstanceIdentifier<T>) InstanceIdentifier
628                                                 .builder(TransportZones.class)
629                                                 .child(TransportZone.class, tZ.getKey())
630                                                 .child(Subnets.class, sub.getKey()).build();
631                                 subnetPaths.add(spath);
632                                 if (tZ.getSubnets() == null || tZ.getSubnets().size() == 0) {
633                                     tzDelList.add(tZ);
634                                 }
635                             }
636                         }
637                     }
638
639                     for (TransportZone tZ : tzDelList) {
640                         if (tZones.getTransportZone().remove(tZ)) {
641                             InstanceIdentifier<T> tpath =
642                                     (InstanceIdentifier<T>) InstanceIdentifier.builder(TransportZones.class)
643                                             .child(TransportZone.class, tZ.getKey()).build();
644                             tzPaths.add(tpath);
645                             if (tZones.getTransportZone() == null || tZones.getTransportZone().size() == 0) {
646                                 MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, path,
647                                         ItmUtils.DEFAULT_CALLBACK);
648                                 return;
649                             }
650                         }
651                     }
652                     allPaths.addAll(vtepPaths);
653                     allPaths.addAll(subnetPaths);
654                     allPaths.addAll(tzPaths);
655                     ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, allPaths,
656                             ItmUtils.DEFAULT_CALLBACK);
657                 }
658                 vtepPaths.clear();
659                 subnetPaths.clear();
660                 tzPaths.clear();
661                 allPaths.clear();
662                 vtepDelCommitList.clear();
663             }
664         } catch (Exception e) {
665             LOG.error(e.getMessage());
666         }
667     }
668
669     public void showState(List<StateTunnelList> tunnelLists, boolean tunnelMonitorEnabled,CommandSession session) throws TepException{
670         if (tunnelLists == null || tunnelLists.isEmpty()) {
671             handleError("No Internal Tunnels Exist", session);
672             return;
673         }
674         if (!tunnelMonitorEnabled) {
675             if(session != null) {
676                 session.getConsole().println("Tunnel Monitoring is Off");
677             }
678         }
679         String displayFormat = "%-16s  %-16s  %-16s  %-16s  %-16s  %-10s  %-10s";
680         session.getConsole().println(String.format(displayFormat, "Tunnel Name", "Source-DPN",
681                         "Destination-DPN", "Source-IP", "Destination-IP", "Trunk-State", "Transport Type"));
682         session.getConsole().println("-------------------------------------------------------------------------------------------------------------------------------------");
683
684         for (StateTunnelList tunnelInst : tunnelLists) {
685            // Display only the internal tunnels
686             if(  tunnelInst.getDstInfo().getTepDeviceType().equals(TepTypeInternal.class)) {
687                 String tunnelInterfaceName = tunnelInst.getTunnelInterfaceName();
688                 LOG.trace("tunnelInterfaceName::: {}", tunnelInterfaceName);
689                 String tunnelState = ITMConstants.TUNNEL_STATE_UNKNOWN;
690                 if (tunnelInst.getOperState() == TunnelOperStatus.Up)
691                     tunnelState = ITMConstants.TUNNEL_STATE_UP;
692                 else if (tunnelInst.getOperState() == TunnelOperStatus.Down )
693                     tunnelState = ITMConstants.TUNNEL_STATE_DOWN;
694                 Class<? extends TunnelTypeBase> tunType = tunnelInst.getTransportType();
695                 String tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
696                 if( tunType.equals(TunnelTypeVxlan.class))
697                    tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
698                 else if( tunType.equals(TunnelTypeGre.class) )
699                    tunnelType = ITMConstants.TUNNEL_TYPE_GRE ;
700                 else if (tunType.equals(TunnelTypeMplsOverGre.class))
701                     tunnelType = ITMConstants.TUNNEL_TYPE_MPLSoGRE;
702                 session.getConsole().println(String.format(displayFormat, tunnelInst.getTunnelInterfaceName(), tunnelInst.getSrcInfo().getTepDeviceId(),
703                         tunnelInst.getDstInfo().getTepDeviceId(), tunnelInst.getSrcInfo().getTepIp().getIpv4Address().getValue(), tunnelInst.getDstInfo().getTepIp().getIpv4Address().getValue(), tunnelState,
704                         tunnelType));
705                 
706             }
707         }
708     }
709
710     // deletes from ADD-cache if it exists.
711     public boolean isInCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
712                              String gatewayIp, String transportZone, CommandSession session) {
713         boolean exists = false;
714         VtepsKey vtepkey = new VtepsKey(dpnId, portName);
715         IpAddress ipAddressObj = new IpAddress(ipAddress.toCharArray());
716         IpPrefix subnetMaskObj = new IpPrefix(subnetMask.toCharArray());
717         IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
718         if (gatewayIp != null) {
719             gatewayIpObj = new IpAddress(gatewayIp.toCharArray());
720         } else {
721             LOG.debug("gateway is null");
722         }
723         SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj);
724         Vteps vtepCli =
725                 new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey)
726                         .setPortname(portName).build();
727         SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId);
728
729         if (tZones.containsKey(transportZone)) {
730             Map<SubnetObject, List<Vteps>> subVtepMapTemp = tZones.get(transportZone);
731             if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists
732                 List<Vteps> vtepListTemp = subVtepMapTemp.get(subObCli);
733                 if (vtepListTemp.contains(vtepCli)) {
734                     exists = true; // return true if tzones has vtep
735                     vtepListTemp.remove(vtepCli);
736                     if (vtepListTemp.size() == 0) {
737                         subVtepMapTemp.remove(subObCli);
738                         if (subVtepMapTemp.size() == 0) {
739                             tZones.remove(transportZone);
740                         }
741                     }
742                 } else if(session != null) {
743                         session.getConsole().println("Vtep " + "has not been configured");
744                 }
745             }
746         }
747         return exists;
748     }
749
750     public void configureTunnelType(String tZoneName, String tunnelType) {
751         LOG.debug("configureTunnelType {} for transportZone {}", tunnelType, tZoneName);
752
753         TransportZone tZoneFromConfigDS = getTransportZoneFromConfigDS(tZoneName);
754         validateTunnelType(tZoneName, tunnelType,tZoneFromConfigDS);
755
756         if (tZoneFromConfigDS != null) {
757             LOG.debug("Transport zone {} with tunnel type {} already exists. No action required.", tZoneName,
758                     tunnelType);
759             return;
760         }
761         TransportZones transportZones = null;
762         List<TransportZone> tZoneList = null;
763         InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
764         Optional<TransportZones> tZones = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
765         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
766         if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN))
767             tunType = TunnelTypeVxlan.class ;
768         else if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_GRE) )
769             tunType = TunnelTypeGre.class ;
770
771         TransportZone tZone = new TransportZoneBuilder().setKey(new TransportZoneKey(tZoneName))
772                 .setTunnelType(tunType).build();
773         if (tZones.isPresent()) {
774             tZoneList = tZones.get().getTransportZone();
775             if(tZoneList == null || tZoneList.isEmpty()) {
776                 tZoneList = new ArrayList<>();
777             }
778         } else {
779             tZoneList = new ArrayList<>();
780         }
781         tZoneList.add(tZone);
782         transportZones = new TransportZonesBuilder().setTransportZone(tZoneList).build();
783         ItmUtils.syncWrite(LogicalDatastoreType.CONFIGURATION, path, transportZones, dataBroker);
784
785     }
786
787     /**
788      * Validate tunnel type.
789      *
790      * @param tZoneName
791      *            the t zone name
792      * @param tunnelType
793      *            the tunnel type
794      */
795     private void validateTunnelType(String tZoneName, String tunnelType,TransportZone tZoneFromConfigDS) {
796         /*
797         String strTunnelType = ItmUtils.validateTunnelType(tunnelType);
798
799         TransportZone tZone = getTransportZone(tZoneName);
800         if (tZone != null) {
801             if (!StringUtils.equalsIgnoreCase(strTunnelType, tZone.getTunnelType())
802                     && ItmUtils.isNotEmpty(tZone.getSubnets())) {
803                 String errorMsg = new StringBuilder("Changing the tunnel type from ").append(tZone.getTunnelType())
804                         .append(" to ").append(strTunnelType)
805                         .append(" is not allowed for already configured transport zone [").append(tZoneName)
806                         .append("].").toString();
807                 Preconditions.checkArgument(false, errorMsg);
808             }
809         }
810         */
811         String strTunnelType = ItmUtils.validateTunnelType(tunnelType);
812         Class<? extends TunnelTypeBase> tunType ;
813         if( strTunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN))
814             tunType = TunnelTypeVxlan.class ;
815         else
816             tunType = TunnelTypeGre.class ;
817         //TransportZone tZone = getTransportZone(tZoneName);
818         // if (tZone != null) {
819         if (tZoneFromConfigDS != null) {
820             if( (!tZoneFromConfigDS.getTunnelType().equals(tunType))  && ItmUtils.isNotEmpty(tZoneFromConfigDS.getSubnets())) {
821                 String errorMsg = "Changing the tunnel type from " + tZoneFromConfigDS.getTunnelType() +
822                         " to " + strTunnelType +
823                         " is not allowed for already configured transport zone [" + tZoneName +
824                         "].";
825                 Preconditions.checkArgument(false, errorMsg);
826             }
827         }
828     }
829
830     public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
831         InstanceIdentifier<TunnelMonitorParams> path = InstanceIdentifier.builder(TunnelMonitorParams.class).build();
832         Optional<TunnelMonitorParams> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
833         Class<? extends TunnelMonitoringTypeBase> monitorType ;
834         if(storedTunnelMonitor.isPresent() && storedTunnelMonitor.get().getMonitorProtocol()!=null )
835             monitorType = storedTunnelMonitor.get().getMonitorProtocol();
836         else
837         {
838             if(monitorProtocol!=null && monitorProtocol.equalsIgnoreCase(ITMConstants.MONITOR_TYPE_LLDP))
839                 monitorType = TunnelMonitoringTypeLldp.class ;
840             else
841                 monitorType = TunnelMonitoringTypeBfd.class ;
842         }
843         if (!storedTunnelMonitor.isPresent()|| storedTunnelMonitor.get().isEnabled() != monitorEnabled)  {
844             TunnelMonitorParams tunnelMonitor = new TunnelMonitorParamsBuilder().setEnabled(monitorEnabled).setMonitorProtocol(monitorType).build();
845             ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker,
846                     ItmUtils.DEFAULT_CALLBACK);
847
848         }
849     }
850
851     public void configureTunnelMonitorInterval(int interval) {
852         InstanceIdentifier<TunnelMonitorInterval> path = InstanceIdentifier.builder(TunnelMonitorInterval.class).build();
853         Optional<TunnelMonitorInterval> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
854         if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().getInterval() != interval) {
855             TunnelMonitorInterval tunnelMonitor = new TunnelMonitorIntervalBuilder().setInterval(interval).build();
856             ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker,
857                     ItmUtils.DEFAULT_CALLBACK);
858         }
859     }
860
861     public void handleError(String errorMessage, CommandSession session) throws TepException {
862         if(session != null) {
863             session.getConsole().println(errorMessage);
864         } else {
865             throw new TepException(errorMessage);
866         }
867
868     }
869 }