NETVIRT-1563: karaf cmd display in proper format
[netvirt.git] / aclservice / shell / src / main / java / org / opendaylight / netvirt / aclservice / shell / DisplayAclDataCaches.java
1 /*
2  * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.aclservice.shell;
10
11 import static java.util.stream.Collectors.joining;
12
13 import java.util.Collection;
14 import java.util.Formatter;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Map.Entry;
19 import java.util.SortedSet;
20 import java.util.stream.Collectors;
21 import org.apache.karaf.shell.commands.Command;
22 import org.apache.karaf.shell.commands.Option;
23 import org.apache.karaf.shell.console.OsgiCommandSupport;
24 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
25 import org.opendaylight.netvirt.aclservice.api.utils.AclDataCache;
26 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.AceIpVersion;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
44 import org.opendaylight.yangtools.yang.common.Uint8;
45
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 @Command(scope = "aclservice", name = "display-acl-data-cache", description = " ")
50 public class DisplayAclDataCaches extends OsgiCommandSupport {
51     private static final Logger LOG = LoggerFactory.getLogger(DisplayAclDataCaches.class);
52     private AclDataCache aclDataCache;
53     private AclInterfaceCache aclInterfaceCache;
54
55     private static final String UUID_TAB = "%-40s";
56     private static final String DELIMITER = String.format("%-40s", "");
57     private  static final String ACL_TAG_HEADER_LINE = "-----------------------------------------------";
58     private static final String ACL_TAG_HEADERS = String.format("%-40s%-40s", "ACL Id", "ACL Tag");
59     private static final String ACL_TAG_DATA_FORMAT_STRING = "%-40s%-40s";
60     private static final String HEADER_LINE =
61             "----------------------------------------------------------------------------------";
62     private static final String REMOTE_ACL_ID_HEADERS = String.format("%-40s%-40s", "Remote ACL Id", "ACL Id");
63     private static final String ACL_INTERFACE_MAP_HEADERS = String.format("%-40s%-40s", "ACL Id", "Interface Id");
64     private static final String ACL_HEADER = String.format("%-8s", "ACL Id: ");
65     private static final String ACE_DATA_FOR = "%-37s%-10s%-6s%-7s%-25s";
66     private static final String ACL_ENTRIES_HEADERS = String.format(ACE_DATA_FOR, "ACE ID", "Direction", "Proto",
67             "IP Ver", "IP Prefix/RemoteGroupId");
68     private static final String ACL_INTERFACE_FORMAT_STRING = "%-37s %-12s %-10s %-15s %-7s %-6s %-6s";
69     private static final String ACL_ENTRIES_HEADER_LINE =
70             "--------------------------------------------------------------------------------------";
71     private static final String ACE_ENTRIES_FORMAT_STRING = "%-37s%-10s%-6s%-7s%-40s";
72
73     private final String exeCmdStr = "display-acl-data-cache -op ";
74     private final String opSelections =
75             "[ aclInterface | ingressRemoteAclId | egressRemoteAclId | aclTag | aclInterfaceCache | acl ]";
76     private final String opSelStr = exeCmdStr + opSelections;
77
78     @Option(name = "-op", aliases = {"--option",
79             "--op"}, description = opSelections, required = false, multiValued = false)
80     private String op;
81
82     @Option(name = "--all", description = "display the complete selected map", required = false, multiValued = false)
83     private String all;
84
85     @Option(name = "--key", description = "key for aclTag/aclInterfaceCache/acl", required = false,
86             multiValued = false)
87     private String key;
88
89     public void setAclDataCache(AclDataCache aclDataCache) {
90         this.aclDataCache = aclDataCache;
91     }
92
93     public void setAclInterfaceCache(AclInterfaceCache aclInterfaceCache) {
94         this.aclInterfaceCache = aclInterfaceCache;
95     }
96
97     private Map<String, String> protoMap = new HashMap<String, String>() {
98         {
99             put("1", "ICMP");
100             put("6", "TCP");
101             put("17", "UDP");
102         }
103     };
104
105     private Map<String, String> opToKeyIdMap = new HashMap<String, String>() {
106         {
107             put("aclInterface", "aclInterfaceUuid");
108             put("ingressRemoteAclId", "remoteAclUuid");
109             put("egressRemoteAclId", "remoteAclUuid");
110             put("aclTag", "aclUuid");
111             put("aclInterfaceCache", "aclInterfaceUuid");
112             put("acl", "aclUuid");
113         }
114     };
115
116     @Override
117     protected Object doExecute() {
118         if (aclDataCache == null) {
119             session.getConsole().println("Failed to handle the command, AclData reference is null at this point");
120             return null;
121         }
122
123         if (op == null) {
124             session.getConsole().println("Please provide valid option");
125             session.getConsole().println();
126             session.getConsole().println("Usage: " + opSelStr);
127             return null;
128         }
129         switch (op) {
130             case "aclInterface":
131                 getAclInterfaceMap();
132                 break;
133             case "ingressRemoteAclId":
134                 getRemoteAclIdMap(DirectionIngress.class);
135                 break;
136             case "egressRemoteAclId":
137                 getRemoteAclIdMap(DirectionEgress.class);
138                 break;
139             case "aclTag":
140                 getAclTagMap();
141                 break;
142             case "aclInterfaceCache":
143                 getAclInterfaceCache();
144                 break;
145             case "acl":
146                 getAclMap();
147                 break;
148             default:
149                 session.getConsole().println("Invalid operation");
150                 session.getConsole().println();
151                 session.getConsole().println("Usage: " + opSelStr);
152         }
153         return null;
154     }
155
156     private void printHelp() {
157         session.getConsole().println("Invalid input");
158         session.getConsole().println();
159         session.getConsole().println("Usage: " + exeCmdStr + op + " --all show | --key <"
160                                             + opToKeyIdMap.get(op) + ">");
161     }
162
163     private boolean validateAll() {
164         return "show".equalsIgnoreCase(all);
165     }
166
167     private void printHeader(String headerString, String headerLine) {
168         session.getConsole().println();
169         session.getConsole().println(headerString);
170         session.getConsole().println(headerLine);
171     }
172
173     protected void getAclInterfaceMap() {
174         if (all == null && key == null) {
175             printHelp();
176         } else if (all == null) {
177             Uuid uuid;
178             try {
179                 uuid = Uuid.getDefaultInstance(key);
180             } catch (IllegalArgumentException e) {
181                 session.getConsole().println("Invalid uuid. " + e.getMessage());
182                 LOG.error("Invalid uuid", e);
183                 return;
184             }
185             Collection<AclInterface> aclInterfaceList = aclDataCache.getInterfaceList(uuid);
186             printHeader(ACL_INTERFACE_MAP_HEADERS, HEADER_LINE);
187             session.getConsole().print(String.format(UUID_TAB, uuid.getValue()));
188             printAclInterfaceMap(aclInterfaceList);
189         } else if (key == null) {
190             if (!validateAll()) {
191                 printHelp();
192                 return;
193             }
194             Map<Uuid, Collection<AclInterface>> aclInterfaceMap = aclDataCache.getAclInterfaceMap();
195             if (aclInterfaceMap.isEmpty()) {
196                 session.getConsole().println("No data found");
197             } else {
198                 printHeader(ACL_INTERFACE_MAP_HEADERS, HEADER_LINE);
199                 aclInterfaceMap.forEach((uuid, aclInterfaceList) -> {
200                     session.getConsole().print(String.format(UUID_TAB, uuid.getValue()));
201                     printAclInterfaceMap(aclInterfaceList);
202                 });
203             }
204         }
205     }
206
207     protected void getRemoteAclIdMap(Class<? extends DirectionBase> direction) {
208         if (all == null && key == null) {
209             printHelp();
210         } else if (all == null) {
211             Uuid uuidRef;
212             try {
213                 uuidRef = Uuid.getDefaultInstance(key);
214             } catch (IllegalArgumentException e) {
215                 session.getConsole().println("Invalid uuid" + e.getMessage());
216                 LOG.error("Invalid uuid", e);
217                 return;
218             }
219             Collection<Uuid> remoteUuidLst = aclDataCache.getRemoteAcl(uuidRef, direction);
220             printHeader(REMOTE_ACL_ID_HEADERS, HEADER_LINE);
221             session.getConsole().print(String.format(UUID_TAB, uuidRef.getValue()));
222             printRemoteAcl(remoteUuidLst);
223         } else if (key == null) {
224             if (!validateAll()) {
225                 printHelp();
226                 return;
227             }
228
229             Map<Uuid, Collection<Uuid>> map = DirectionEgress.class.equals(direction)
230                     ? aclDataCache.getEgressRemoteAclIdMap() : aclDataCache.getIngressRemoteAclIdMap();
231             if (map.isEmpty()) {
232                 session.getConsole().println("No data found");
233             } else {
234                 printHeader(REMOTE_ACL_ID_HEADERS, HEADER_LINE);
235                 map.forEach((uuid, remoteUuidList) -> {
236                     session.getConsole().print(String.format(UUID_TAB, uuid.getValue()));
237                     printRemoteAcl(remoteUuidList);
238                     session.getConsole().println();
239                 });
240             }
241         }
242     }
243
244     private void printRemoteAcl(Collection<Uuid> remoteUuidLst) {
245         if (remoteUuidLst == null || remoteUuidLst.isEmpty()) {
246             session.getConsole().println("No data found ");
247         } else {
248             List<String> uuids = remoteUuidLst.stream().map(Uuid::getValue).collect(Collectors.toList());
249             String joined = uuids.stream().collect(joining("\n" + DELIMITER, "", ""));
250             session.getConsole().println(joined);
251         }
252     }
253
254     protected void getAclTagMap() {
255         if (all == null && key == null) {
256             printHelp();
257         } else if (all == null) {
258             Integer val = aclDataCache.getAclTag(key);
259             if (val == null) {
260                 session.getConsole().println("No data found");
261                 return;
262             }
263             printHeader(ACL_TAG_HEADERS, ACL_TAG_HEADER_LINE);
264             session.getConsole().println(String.format(ACL_TAG_DATA_FORMAT_STRING, key, val));
265         } else if (key == null) {
266             if (!validateAll()) {
267                 printHelp();
268                 return;
269             }
270             Map<String, Integer> map = aclDataCache.getAclTagMap();
271             if (map.isEmpty()) {
272                 session.getConsole().println("No data found");
273             } else {
274                 printHeader(ACL_TAG_HEADERS, ACL_TAG_HEADER_LINE);
275                 map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(entry -> session.getConsole()
276                         .println(String.format(ACL_TAG_DATA_FORMAT_STRING, entry.getKey(), entry.getValue())));
277             }
278         }
279     }
280
281
282     protected void getAclInterfaceCache() {
283         if (all == null && key == null) {
284             printHelp();
285             return;
286         }
287         if (all == null && key != null) {
288             AclInterface aclInterface = aclInterfaceCache.get(key);
289             if (aclInterface == null) {
290                 session.getConsole().println("No data found");
291                 return;
292             }
293             printAclInterfaceHeader();
294             printAclInterface(aclInterface);
295         } else if (key == null) {
296             if (!validateAll()) {
297                 printHelp();
298                 return;
299             }
300             Collection<Entry<String, AclInterface>> entries = aclInterfaceCache.entries();
301             if (entries.isEmpty()) {
302                 session.getConsole().println("No data found");
303                 return;
304             }
305             printAclInterfaceCache(entries);
306         }
307     }
308
309     private void printAclInterfaceMap(Collection<AclInterface> aclInterfaceList) {
310         if (aclInterfaceList == null || aclInterfaceList.isEmpty()) {
311             session.getConsole().println("No data found");
312         } else {
313             List<String> uuids = aclInterfaceList.stream().map(AclInterface::getInterfaceId)
314                     .collect(Collectors.toList());
315             String joined = uuids.stream().collect(joining("\n" + DELIMITER, "", ""));
316             session.getConsole().println(joined);
317             session.getConsole().println();
318         }
319     }
320
321     @SuppressWarnings("checkstyle:RegexpSinglelineJava")
322     private void printAclInterfaceCache(Collection<Entry<String, AclInterface>> entries) {
323         printAclInterfaceHeader();
324
325         for (Map.Entry<String, AclInterface> entry : entries) {
326             AclInterface aclInterface = entry.getValue();
327             printAclInterface(aclInterface);
328         }
329     }
330
331     private void printAclInterface(AclInterface aclInterface) {
332         session.getConsole().println(String.format(ACL_INTERFACE_FORMAT_STRING, aclInterface.getInterfaceId(),
333                 aclInterface.getInterfaceType(), aclInterface.isPortSecurityEnabled(), aclInterface.getDpId(),
334                 aclInterface.getLPortTag(), aclInterface.getElanId(), aclInterface.isMarkedForDelete()));
335         List<AllowedAddressPairs> aaps = aclInterface.getAllowedAddressPairs();
336         if (aaps == null || aaps.isEmpty()) {
337             session.getConsole().println("--");
338         } else {
339             for (AllowedAddressPairs aap : aaps) {
340                 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
341                 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
342                 String ipAddrStr = "";
343                 if (ipPrefix != null) {
344                     if (ipPrefix.getIpv4Prefix() != null) {
345                         ipAddrStr = ipPrefix.getIpv4Prefix().getValue();
346                     } else {
347                         ipAddrStr = ipPrefix.getIpv6Prefix().getValue();
348                     }
349                 } else {
350                     IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
351                     if (ipAddress != null) {
352                         if (ipAddress.getIpv4Address() != null) {
353                             ipAddrStr = ipAddress.getIpv4Address().getValue();
354                         } else {
355                             ipAddrStr = ipAddress.getIpv6Address().getValue();
356                         }
357                     }
358                 }
359                 String macAddrStr = aap.getMacAddress().getValue();
360                 session.getConsole().println(ipAddrStr + ", " + macAddrStr);
361             }
362         }
363
364         List<Uuid> sgsUuid = aclInterface.getSecurityGroups();
365         if (sgsUuid == null || sgsUuid.isEmpty()) {
366             session.getConsole().println("--");
367         } else {
368             for (Uuid sgUuid : sgsUuid) {
369                 session.getConsole().println(sgUuid.getValue());
370             }
371         }
372         SortedSet<Integer> ingressRemoteAclTags = aclInterface.getIngressRemoteAclTags();
373         if (ingressRemoteAclTags == null || ingressRemoteAclTags.isEmpty()) {
374             session.getConsole().println("--");
375         } else {
376             session.getConsole().println(ingressRemoteAclTags);
377         }
378         SortedSet<Integer> egressRemoteAclTags = aclInterface.getEgressRemoteAclTags();
379         if (egressRemoteAclTags == null || egressRemoteAclTags.isEmpty()) {
380             session.getConsole().println("--");
381         } else {
382             session.getConsole().println(egressRemoteAclTags);
383         }
384         session.getConsole().println();
385     }
386
387     private void printAclInterfaceHeader() {
388         session.getConsole().println();
389         StringBuilder sb = new StringBuilder();
390         Formatter fmt = new Formatter(sb);
391         session.getConsole().println(fmt.format(ACL_INTERFACE_FORMAT_STRING, "InterfaceId", "Type",
392                 "SGEnabled", "DpId", "LPort", "ElanId", "Marked"));
393         sb.setLength(0);
394         session.getConsole().println(fmt.format("%-55s", "AllowedAddressPairs"));
395         sb.setLength(0);
396         session.getConsole().println(fmt.format("%-55s", "SecurityGroups"));
397         sb.setLength(0);
398         session.getConsole().println(fmt.format("%-55s", "IngressRemoteAclTags"));
399         sb.setLength(0);
400         session.getConsole().println(fmt.format("%-55s", "EgressRemoteAclTags"));
401         sb.setLength(0);
402         session.getConsole().println(fmt
403             .format("----------------------------------------------------------------------------------------------"));
404         sb.setLength(0);
405         fmt.close();
406     }
407
408     protected void getAclMap() {
409         if (all == null && key == null) {
410             printHelp();
411         } else if (all == null) {
412             Acl acl = aclDataCache.getAcl(key);
413             if (acl == null) {
414                 session.getConsole().println("No data found");
415                 return;
416             }
417             printAcl(key, acl);
418         } else if (key == null) {
419             if (!validateAll()) {
420                 printHelp();
421                 return;
422             }
423             Map<String, Acl> map = aclDataCache.getAclMap();
424             if (map.isEmpty()) {
425                 session.getConsole().println("No data found");
426             } else {
427                 map.forEach(this::printAcl);
428             }
429         }
430     }
431
432     private void printAcl(String aclId, Acl acl) {
433         session.getConsole().println();
434         session.getConsole().println(ACL_HEADER + String.format("%-32s  ", aclId));
435         if (null != acl.getAccessListEntries() && null != acl.getAccessListEntries().getAce()) {
436             printHeader(ACL_ENTRIES_HEADERS, ACL_ENTRIES_HEADER_LINE);
437             List<Ace> aceList = acl.getAccessListEntries().getAce();
438             for (Ace ace : aceList) {
439                 LOG.info("ace data: {}", ace);
440                 SecurityRuleAttr aceAttr = getAccessListAttributes(ace);
441                 Class<? extends DirectionBase> aceAttrDirection = aceAttr.getDirection();
442                 AceIp aceIp = (AceIp) ace.getMatches().getAceType();
443                 AceIpVersion ipVersion = aceIp.getAceIpVersion();
444                 Uint8 protoNum = aceIp.getProtocol();
445                 String protocol = "Any";
446                 if (null != protoNum) {
447                     protocol = protoMap.get(protoNum.toString());
448                     protocol = (protocol == null) ? protoNum.toString() : protocol;
449                 }
450                 String ipVer = "";
451                 String direction = DirectionEgress.class.equals(aceAttrDirection) ? "Egress" : "Ingress";
452                 String ipPrefix = " -- ";
453                 if (null != ipVersion && ipVersion instanceof AceIpv4) {
454                     ipVer = "IPv4";
455                     Ipv4Prefix srcNetwork = ((AceIpv4) ipVersion).getSourceIpv4Network();
456                     if (null != srcNetwork) {
457                         ipPrefix = srcNetwork.getValue();
458                     }
459                 } else if (null != ipVersion && ipVersion instanceof AceIpv6) {
460                     ipVer = "IPv6";
461                     Ipv6Prefix srcNetwork = ((AceIpv6) ipVersion).getSourceIpv6Network();
462                     if (null != srcNetwork) {
463                         ipPrefix = srcNetwork.getValue();
464                     }
465                 }
466                 String remoteGroupId = "-";
467                 if (aceAttr.getRemoteGroupId() != null) {
468                     remoteGroupId = aceAttr.getRemoteGroupId().getValue();
469                     ipPrefix = "-";
470                 }
471                 String prefixAndRemoteId = ipPrefix + " / " + remoteGroupId;
472                 session.getConsole().print(String.format(ACE_ENTRIES_FORMAT_STRING, ace.key().getRuleName(),
473                         direction, protocol, ipVer, prefixAndRemoteId));
474             }
475         }
476         session.getConsole().println();
477     }
478
479     public SecurityRuleAttr getAccessListAttributes(Ace ace) {
480         if (ace == null) {
481             LOG.error("Ace is Null");
482             return null;
483         }
484         SecurityRuleAttr aceAttributes = ace.augmentation(SecurityRuleAttr.class);
485         if (aceAttributes == null) {
486             LOG.error("Ace is null");
487             return null;
488         }
489         return aceAttributes;
490     }
491 }