Merge "Checkstyle enforcement - idmanager-shell"
[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                         System.out.println(p);
471                     }
472                 } else {
473                     System.out.println("No teps to display");
474                 }
475             }
476         } else if(session != null){
477             System.out.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         System.out.println(String.format(displayFormat, "Tunnel Name", "Source-DPN",
669                         "Destination-DPN", "Source-IP", "Destination-IP", "Trunk-State", "Transport Type"));
670         System.out.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                 System.out.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     // deletes from ADD-cache if it exists.
698     public boolean isInCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
699                              String gatewayIp, String transportZone, CommandSession session) {
700         boolean exists = false;
701         VtepsKey vtepkey = new VtepsKey(dpnId, portName);
702         IpAddress ipAddressObj = new IpAddress(ipAddress.toCharArray());
703         IpPrefix subnetMaskObj = new IpPrefix(subnetMask.toCharArray());
704         IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
705         if (gatewayIp != null) {
706             gatewayIpObj = new IpAddress(gatewayIp.toCharArray());
707         } else {
708             LOG.debug("gateway is null");
709         }
710         SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj);
711         Vteps vtepCli =
712                 new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey)
713                         .setPortname(portName).build();
714         SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId);
715
716         if (tZones.containsKey(transportZone)) {
717             Map<SubnetObject, List<Vteps>> subVtepMapTemp = tZones.get(transportZone);
718             if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists
719                 List<Vteps> vtepListTemp = subVtepMapTemp.get(subObCli);
720                 if (vtepListTemp.contains(vtepCli)) {
721                     exists = true; // return true if tzones has vtep
722                     vtepListTemp.remove(vtepCli);
723                     if (vtepListTemp.size() == 0) {
724                         subVtepMapTemp.remove(subObCli);
725                         if (subVtepMapTemp.size() == 0) {
726                             tZones.remove(transportZone);
727                         }
728                     }
729                 } else if(session != null) {
730                         session.getConsole().println("Vtep " + "has not been configured");
731                 }
732             }
733         }
734         return exists;
735     }
736
737     public void configureTunnelType(String tZoneName, String tunnelType) {
738         LOG.debug("configureTunnelType {} for transportZone {}", tunnelType, tZoneName);
739
740         TransportZone tZoneFromConfigDS = ItmUtils.getTransportZoneFromConfigDS(tZoneName, dataBroker);
741         Class<? extends TunnelTypeBase> tunType;
742
743         validateTunnelType(tZoneName, tunnelType, tZoneFromConfigDS);
744         if (tZoneFromConfigDS != null) {
745             if (!tZoneName.equals(ITMConstants.DEFAULT_TRANSPORT_ZONE)) {
746                 LOG.debug(
747                     "Transport zone {} with tunnel type {} already exists. No action required.",
748                     tZoneName, tunnelType);
749                 return;
750             } else {
751                 tunnelType = StringUtils.upperCase(tunnelType);
752                 tunType = ItmUtils.TUNNEL_TYPE_MAP.get(tunnelType);
753                 if(tZoneFromConfigDS.getTunnelType().equals(tunType)) {
754                     // default-TZ already exists and tunnel-type is not changed during
755                     // controller restart, then nothing to do now. Just return.
756                     return;
757                 }
758             }
759         }
760
761         // get tunnel-type
762         tunnelType = StringUtils.upperCase(tunnelType);
763         tunType = ItmUtils.TUNNEL_TYPE_MAP.get(tunnelType);
764
765         TransportZones transportZones = null;
766         List<TransportZone> tZoneList = null;
767         InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
768         Optional<TransportZones> tZones = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
769
770         TransportZone tZone = new TransportZoneBuilder().setKey(new TransportZoneKey(tZoneName))
771                 .setTunnelType(tunType).build();
772         if (tZones.isPresent()) {
773             tZoneList = tZones.get().getTransportZone();
774             if(tZoneList == null || tZoneList.isEmpty()) {
775                 tZoneList = new ArrayList<>();
776             }
777         } else {
778             tZoneList = new ArrayList<>();
779         }
780         tZoneList.add(tZone);
781         transportZones = new TransportZonesBuilder().setTransportZone(tZoneList).build();
782         ItmUtils.syncWrite(LogicalDatastoreType.CONFIGURATION, path, transportZones, dataBroker);
783
784     }
785
786     /**
787      * Validate tunnel type.
788      *
789      * @param tZoneName
790      *            the t zone name
791      * @param tunnelType
792      *            the tunnel type
793      */
794     private void validateTunnelType(String tZoneName, String tunnelType,TransportZone tZoneFromConfigDS) {
795         /*
796         String strTunnelType = ItmUtils.validateTunnelType(tunnelType);
797
798         TransportZone tZone = getTransportZone(tZoneName);
799         if (tZone != null) {
800             if (!StringUtils.equalsIgnoreCase(strTunnelType, tZone.getTunnelType())
801                     && ItmUtils.isNotEmpty(tZone.getSubnets())) {
802                 String errorMsg = new StringBuilder("Changing the tunnel type from ").append(tZone.getTunnelType())
803                         .append(" to ").append(strTunnelType)
804                         .append(" is not allowed for already configured transport zone [").append(tZoneName)
805                         .append("].").toString();
806                 Preconditions.checkArgument(false, errorMsg);
807             }
808         }
809         */
810         String strTunnelType = ItmUtils.validateTunnelType(tunnelType);
811         Class<? extends TunnelTypeBase> tunType ;
812         if( strTunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN))
813             tunType = TunnelTypeVxlan.class ;
814         else
815             tunType = TunnelTypeGre.class ;
816         //TransportZone tZone = getTransportZone(tZoneName);
817         // if (tZone != null) {
818         if (tZoneFromConfigDS != null) {
819             if( (!tZoneFromConfigDS.getTunnelType().equals(tunType))  && ItmUtils.isNotEmpty(tZoneFromConfigDS.getSubnets())) {
820                 // for default-TZ, such error message is not needed to be thrown.
821                 // it needs to be handled in different way, by deleting default-TZ
822                 // with old tunnel-type and then add default-TZ with new tunnel-type
823                 if (!tZoneName.equals(ITMConstants.DEFAULT_TRANSPORT_ZONE)) {
824                     String errorMsg = "Changing the tunnel type from " + tZoneFromConfigDS.getTunnelType()
825                         + " to " + strTunnelType
826                         + " is not allowed for already configured transport zone [" + tZoneName
827                         + "].";
828                     Preconditions.checkArgument(false, errorMsg);
829                 } else {
830                     // delete already existing default TZ
831                     ItmUtils.deleteTransportZoneFromConfigDS(ITMConstants.DEFAULT_TRANSPORT_ZONE, dataBroker);
832                 }
833             }
834         }
835     }
836
837     public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
838         InstanceIdentifier<TunnelMonitorParams> path = InstanceIdentifier.builder(TunnelMonitorParams.class).build();
839         Optional<TunnelMonitorParams> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
840         Class<? extends TunnelMonitoringTypeBase> monitorType ;
841         if(storedTunnelMonitor.isPresent() && storedTunnelMonitor.get().getMonitorProtocol()!=null )
842             monitorType = storedTunnelMonitor.get().getMonitorProtocol();
843         else
844         {
845             if(monitorProtocol!=null && monitorProtocol.equalsIgnoreCase(ITMConstants.MONITOR_TYPE_LLDP))
846                 monitorType = TunnelMonitoringTypeLldp.class ;
847             else
848                 monitorType = TunnelMonitoringTypeBfd.class ;
849         }
850         if (!storedTunnelMonitor.isPresent()|| storedTunnelMonitor.get().isEnabled() != monitorEnabled)  {
851             TunnelMonitorParams tunnelMonitor = new TunnelMonitorParamsBuilder().setEnabled(monitorEnabled).setMonitorProtocol(monitorType).build();
852             ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker,
853                     ItmUtils.DEFAULT_CALLBACK);
854
855         }
856     }
857
858     public void configureTunnelMonitorInterval(int interval) {
859         InstanceIdentifier<TunnelMonitorInterval> path = InstanceIdentifier.builder(TunnelMonitorInterval.class).build();
860         Optional<TunnelMonitorInterval> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
861         if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().getInterval() != interval) {
862             TunnelMonitorInterval tunnelMonitor = new TunnelMonitorIntervalBuilder().setInterval(interval).build();
863             ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker,
864                     ItmUtils.DEFAULT_CALLBACK);
865         }
866     }
867
868     public void handleError(String errorMessage, CommandSession session) throws TepException {
869         if(session != null) {
870             session.getConsole().println(errorMessage);
871         } else {
872             throw new TepException(errorMessage);
873         }
874
875     }
876 }