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