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