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