Add Select all checkbox to all datagrids, remove out port and out vlan columns from...
[controller.git] / opendaylight / web / troubleshoot / src / main / java / org / opendaylight / controller / troubleshoot / web / Troubleshoot.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. 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.controller.troubleshoot.web;
10
11 import java.net.InetAddress;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.Date;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19
20 import javax.servlet.http.HttpServletRequest;
21
22 import org.opendaylight.controller.sal.action.Action;
23 import org.opendaylight.controller.sal.action.Output;
24 import org.opendaylight.controller.sal.action.SetDlDst;
25 import org.opendaylight.controller.sal.action.SetDlSrc;
26 import org.opendaylight.controller.sal.action.SetNwDst;
27 import org.opendaylight.controller.sal.action.SetNwSrc;
28 import org.opendaylight.controller.sal.action.SetNwTos;
29 import org.opendaylight.controller.sal.action.SetTpDst;
30 import org.opendaylight.controller.sal.action.SetTpSrc;
31 import org.opendaylight.controller.sal.action.SetVlanId;
32 import org.opendaylight.controller.sal.action.SetVlanPcp;
33 import org.opendaylight.controller.sal.authorization.Privilege;
34 import org.opendaylight.controller.sal.authorization.UserLevel;
35 import org.opendaylight.controller.sal.core.Description;
36 import org.opendaylight.controller.sal.core.Node;
37 import org.opendaylight.controller.sal.core.NodeConnector;
38 import org.opendaylight.controller.sal.core.TimeStamp;
39 import org.opendaylight.controller.sal.flowprogrammer.Flow;
40 import org.opendaylight.controller.sal.match.Match;
41 import org.opendaylight.controller.sal.match.MatchType;
42 import org.opendaylight.controller.sal.reader.FlowOnNode;
43 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
44 import org.opendaylight.controller.sal.utils.EtherTypes;
45 import org.opendaylight.controller.sal.utils.GlobalConstants;
46 import org.opendaylight.controller.sal.utils.HexEncode;
47 import org.opendaylight.controller.sal.utils.IPProtocols;
48 import org.opendaylight.controller.sal.utils.NetUtils;
49 import org.opendaylight.controller.sal.utils.ServiceHelper;
50 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
51 import org.opendaylight.controller.switchmanager.ISwitchManager;
52 import org.opendaylight.controller.web.DaylightWebUtil;
53 import org.opendaylight.controller.web.IDaylightWeb;
54 import org.springframework.stereotype.Controller;
55 import org.springframework.web.bind.annotation.RequestMapping;
56 import org.springframework.web.bind.annotation.RequestMethod;
57 import org.springframework.web.bind.annotation.RequestParam;
58 import org.springframework.web.bind.annotation.ResponseBody;
59
60 @Controller
61 @RequestMapping("/")
62 public class Troubleshoot implements IDaylightWeb {
63     private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
64     private static final List<String> flowStatsColumnNames = Arrays.asList("Node", "In Port",
65             "DL Src", "DL Dst", "DL Type", "DL Vlan", "NW Src", "NW Dst",
66             "NW Proto", "TP Src", "TP Dst", "Actions", "Bytes", "Packets",
67             "Time (s)", "Timeout (s)",
68             "Priority");
69     private static final List<String> portStatsColumnNames = Arrays.asList("Node Connector",
70             "Rx Pkts", "Tx Pkts", "Rx Bytes", "Tx Bytes", "Rx Drops",
71             "Tx Drops", "Rx Errs", "Tx Errs", "Rx Frame Errs",
72             "Rx OverRun Errs", "Rx CRC Errs", "Collisions");
73     private static final List<String> nodesColumnNames = Arrays.asList("Node", "Node ID", "Statistics");
74     private static final List<String> nodeStatsColumnNames = Arrays.asList("Node", "Node ID", "Statistics");
75     private final String WEB_NAME = "Troubleshoot";
76     private final String WEB_ID = "troubleshoot";
77     private final short WEB_ORDER = 4;
78
79
80     public Troubleshoot() {
81         ServiceHelper.registerGlobalService(IDaylightWeb.class, this, null);
82     }
83
84     @Override
85     public String getWebName() {
86         return WEB_NAME;
87     }
88
89     @Override
90     public String getWebId() {
91         return WEB_ID;
92     }
93
94     @Override
95     public short getWebOrder() {
96         return WEB_ORDER;
97     }
98
99     @Override
100     public boolean isAuthorized(UserLevel userLevel) {
101         return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
102     }
103
104     @RequestMapping(value = "/existingNodes", method = RequestMethod.GET)
105     @ResponseBody
106     public TroubleshootingJsonBean getExistingNodes(HttpServletRequest request, @RequestParam(required = false) String container) {
107         List<Map<String, String>> lines = new ArrayList<Map<String, String>>();
108         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
109
110         // Derive the privilege this user has on the current container
111         String userName = request.getUserPrincipal().getName();
112         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
113
114         if (privilege != Privilege.NONE) {
115             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
116                     .getInstance(ISwitchManager.class, containerName, this);
117             Set<Node> nodeSet = (switchManager != null) ? switchManager.getNodes() : null;
118             if (nodeSet != null) {
119                 for (Node node : nodeSet) {
120                     Map<String, String> device = new HashMap<String, String>();
121                     device.put("nodeName", getNodeDesc(node, switchManager));
122                     device.put("nodeId", node.toString());
123                     lines.add(device);
124                 }
125             }
126         }
127
128         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
129         result.setColumnNames(nodesColumnNames);
130         result.setNodeData(lines);
131         return result;
132     }
133
134     @RequestMapping(value = "/uptime", method = RequestMethod.GET)
135     @ResponseBody
136     public TroubleshootingJsonBean getUptime(HttpServletRequest request, @RequestParam(required = false) String container) {
137         List<Map<String, String>> lines = new ArrayList<Map<String, String>>();
138         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
139
140         // Derive the privilege this user has on the current container
141         String userName = request.getUserPrincipal().getName();
142         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
143
144         if (privilege != Privilege.NONE) {
145             ISwitchManager switchManager = (ISwitchManager) ServiceHelper
146                     .getInstance(ISwitchManager.class, containerName, this);
147             Set<Node> nodeSet = (switchManager != null) ? switchManager.getNodes() : null;
148             if (nodeSet != null) {
149                 for (Node node : nodeSet) {
150                     Map<String, String> device = new HashMap<String, String>();
151                     device.put("nodeName", getNodeDesc(node, switchManager));
152                     device.put("nodeId", node.toString());
153                     TimeStamp timeStamp = (TimeStamp) switchManager.getNodeProp(
154                             node, TimeStamp.TimeStampPropName);
155                     Long time = (timeStamp == null) ? 0 : timeStamp.getValue();
156                     String date = (time == 0) ? "" : (new Date(time)).toString();
157                     device.put("connectedSince", date);
158                     lines.add(device);
159                 }
160             }
161         }
162
163         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
164         result.setColumnNames(nodeStatsColumnNames);
165         result.setNodeData(lines);
166         return result;
167     }
168
169     @RequestMapping(value = "/flowStats", method = RequestMethod.GET)
170     @ResponseBody
171     public TroubleshootingJsonBean getFlowStats(
172             @RequestParam("nodeId") String nodeId,
173             HttpServletRequest request, @RequestParam(required = false) String container) {
174         List<Map<String, String>> cells = new ArrayList<Map<String, String>>();
175         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
176
177         // Derive the privilege this user has on the current container
178         String userName = request.getUserPrincipal().getName();
179         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
180
181         if (privilege != Privilege.NONE) {
182             IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
183                     .getInstance(IStatisticsManager.class, containerName, this);
184             if (statisticsManager != null) {
185                 Node node = Node.fromString(nodeId);
186                 List<FlowOnNode> statistics = statisticsManager.getFlows(node);
187                 for (FlowOnNode stats : statistics) {
188                     cells.add(this.convertFlowStatistics(node, stats, containerName));
189                 }
190             }
191         }
192
193         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
194         result.setColumnNames(flowStatsColumnNames);
195         result.setNodeData(cells);
196         return result;
197     }
198
199     @RequestMapping(value = "/portStats", method = RequestMethod.GET)
200     @ResponseBody
201     public TroubleshootingJsonBean getPortStats(
202             @RequestParam("nodeId") String nodeId,
203             HttpServletRequest request, @RequestParam(required = false) String container) {
204         List<Map<String, String>> cells = new ArrayList<Map<String, String>>();
205         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
206
207         // Derive the privilege this user has on the current container
208         String userName = request.getUserPrincipal().getName();
209         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
210
211         if (privilege != Privilege.NONE) {
212             IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
213                     .getInstance(IStatisticsManager.class, containerName, this);
214             if (statisticsManager != null) {
215                 Node node = Node.fromString(nodeId);
216                 List<NodeConnectorStatistics> statistics = statisticsManager
217                         .getNodeConnectorStatistics(node);
218                 for (NodeConnectorStatistics stats : statistics) {
219                     cells.add(this.convertPortsStatistics(stats, containerName));
220                 }
221             }
222         }
223
224         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
225         result.setColumnNames(portStatsColumnNames);
226         result.setNodeData(cells);
227         return result;
228     }
229
230     private Map<String, String> convertPortsStatistics(
231             NodeConnectorStatistics ncStats, String containerName) {
232         Map<String, String> row = new HashMap<String, String>();
233
234         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
235                 .getInstance(ISwitchManager.class, containerName, this);
236         NodeConnector nodeConnector = ncStats.getNodeConnector();
237         Description description = (Description) switchManager.getNodeProp(nodeConnector.getNode(), Description.propertyName);
238         String desc = (description == null) ? "" : description.getValue();
239         String nodeName = desc.equalsIgnoreCase("none") ? nodeConnector.getNode().getNodeIDString() : desc;
240         String nodeConnectorDisplayName = nodeConnector.getType() + "|" + nodeConnector.getID() + "@" + nodeName;
241         row.put("nodeConnector",
242                 String.valueOf(nodeConnectorDisplayName));
243
244         row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
245         row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
246         row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));
247         row.put("txBytes", String.valueOf(ncStats.getTransmitByteCount()));
248         row.put("rxDrops", String.valueOf(ncStats.getReceiveDropCount()));
249         row.put("txDrops", String.valueOf(ncStats.getTransmitDropCount()));
250         row.put("rxErrors", String.valueOf(ncStats.getReceiveErrorCount()));
251         row.put("txErrors", String.valueOf(ncStats.getTransmitErrorCount()));
252         row.put("rxFrameErrors",
253                 String.valueOf(ncStats.getReceiveFrameErrorCount()));
254         row.put("rxOverRunErrors",
255                 String.valueOf(ncStats.getReceiveOverRunErrorCount()));
256         row.put("rxCRCErrors",
257                 String.valueOf(ncStats.getReceiveCRCErrorCount()));
258         row.put("collisions", String.valueOf(ncStats.getCollisionCount()));
259
260         return row;
261     }
262
263     private Map<String, String> convertFlowStatistics(Node node,
264             FlowOnNode flowOnNode,
265             String containerName) {
266         Map<String, String> row = new HashMap<String, String>();
267         Flow flow = flowOnNode.getFlow();
268         Match match = flow.getMatch();
269         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
270                 .getInstance(ISwitchManager.class, containerName, this);
271         String desc = getNodeDesc(node, switchManager);
272         desc = (desc == null || desc.isEmpty() || desc.equalsIgnoreCase("none"))?
273                         node.toString() : desc;
274         row.put("nodeName", desc);
275         if (match.isPresent(MatchType.IN_PORT)) {
276             row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch()
277                     .getField(MatchType.IN_PORT).getValue())
278                     .getNodeConnectorIdAsString());
279         } else {
280             row.put(MatchType.IN_PORT.id(), "*");
281         }
282         if (match.isPresent(MatchType.DL_SRC)) {
283             row.put(MatchType.DL_SRC.id(),
284                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
285                             .getField(MatchType.DL_SRC).getValue()))));
286         } else {
287             row.put(MatchType.DL_SRC.id(), "*");
288         }
289         if (match.isPresent(MatchType.DL_DST)) {
290             row.put(MatchType.DL_DST.id(),
291                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
292                             .getField(MatchType.DL_DST).getValue()))));
293         } else {
294             row.put(MatchType.DL_DST.id(), "*");
295         }
296         if (match.isPresent(MatchType.DL_TYPE)) {
297             row.put(MatchType.DL_TYPE.id(),
298                     EtherTypes.getEtherTypeName(((Short) flow.getMatch()
299                             .getField(MatchType.DL_TYPE).getValue())));
300         } else {
301             row.put(MatchType.DL_TYPE.id(), "*");
302         }
303
304         // Some physical switch has vlan as ffff to show "any" vlan
305         if (match.isPresent(MatchType.DL_VLAN)) {
306             if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
307                     .shortValue() < 0) {
308                 row.put(MatchType.DL_VLAN.id(), "0");
309             } else {
310                 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
311                         .getField(MatchType.DL_VLAN).getValue()).toString());
312             }
313         } else {
314             row.put(MatchType.DL_VLAN.id(), "*");
315         }
316         if (match.isPresent(MatchType.NW_SRC)) {
317             row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
318                     .getField(MatchType.NW_SRC).getValue()).getHostAddress());
319         } else {
320             row.put(MatchType.NW_SRC.id(), "*");
321         }
322         if (match.isPresent(MatchType.NW_DST)) {
323             row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
324                     .getField(MatchType.NW_DST).getValue()).getHostAddress());
325         } else {
326             row.put(MatchType.NW_DST.id(), "*");
327         }
328         if (match.isPresent(MatchType.NW_PROTO)) {
329             row.put(MatchType.NW_PROTO.id(),
330                     IPProtocols.getProtocolName(((Byte) flow.getMatch()
331                             .getField(MatchType.NW_PROTO).getValue())));
332         } else {
333             row.put(MatchType.NW_PROTO.id(), "*");
334         }
335         if (match.isPresent(MatchType.TP_SRC)) {
336             Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
337                     .getValue());
338             row.put(MatchType.TP_SRC.id(),
339                         String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
340         } else {
341             row.put(MatchType.TP_SRC.id(), "*");
342         }
343         if (match.isPresent(MatchType.TP_DST)) {
344             Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
345                     .getValue());
346             row.put(MatchType.TP_DST.id(),
347                         String.valueOf(NetUtils.getUnsignedShort(tpDst)));
348         } else {
349             row.put(MatchType.TP_DST.id(), "*");
350         }
351
352         row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
353         row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
354
355         StringBuffer actions = new StringBuffer();
356         StringBuffer outPorts = new StringBuffer();
357         for (Action action : flow.getActions()) {
358
359             if (action instanceof Output) {
360                 Output ao = (Output) action;
361                 if (outPorts.length() > 0) {
362                     outPorts.append(" ");
363                 }
364                 actions.append(action.getType().toString() + " = "
365                         + ao.getPort().getNodeConnectorIdAsString() + "<br>");
366             } else if (action instanceof SetVlanId) {
367                 SetVlanId av = (SetVlanId) action;
368                 String outVlanId = String.valueOf(av.getVlanId());
369                 actions.append(action.getType().toString() + " = " + outVlanId
370                         + "<br>");
371             } else if (action instanceof SetDlSrc) {
372                 SetDlSrc ads = (SetDlSrc) action;
373                 actions.append(action.getType().toString() + " = "
374                         + HexEncode.bytesToHexStringFormat(ads.getDlAddress()) + "<br>");
375             } else if (action instanceof SetDlDst) {
376                 SetDlDst add = (SetDlDst) action;
377                 actions.append(action.getType().toString() + " = "
378                         + HexEncode.bytesToHexStringFormat(add.getDlAddress())
379                         + "<br>");
380             } else if (action instanceof SetNwSrc) {
381                 SetNwSrc ans = (SetNwSrc) action;
382                 actions.append(action.getType().toString() + " = "
383                         + ans.getAddressAsString() + "<br>");
384             } else if (action instanceof SetNwDst) {
385                 SetNwDst and = (SetNwDst) action;
386                 actions.append(action.getType().toString() + " = "
387                         + and.getAddressAsString() + "<br>");
388             } else if (action instanceof SetNwTos) {
389                 SetNwTos ant = (SetNwTos) action;
390                 actions.append(action.getType().toString() + " = "
391                         + ant.getNwTos() + "<br>");
392             } else if (action instanceof SetTpSrc) {
393                 SetTpSrc ads = (SetTpSrc) action;
394                 actions.append(action.getType().toString() + " = "
395                         + ads.getPort() + "<br>");
396             } else if (action instanceof SetTpDst) {
397                 SetTpDst atd = (SetTpDst) action;
398                 actions.append(action.getType().toString() + " = "
399                         + atd.getPort() + "<br>");
400             } else if (action instanceof SetVlanPcp) {
401                 SetVlanPcp avp = (SetVlanPcp) action;
402                 actions.append(action.getType().toString() + " = "
403                         + avp.getPcp() + "<br>");
404                 // } else if (action instanceof SetDlSrc) {
405                 // SetDlSrc ads = (SetDlSrc) action;
406             } else {
407                 actions.append(action.getType().toString() + "<br>");
408             }
409         }
410         row.put("actions", actions.toString());
411         row.put("durationSeconds",
412                 ((Integer) flowOnNode.getDurationSeconds()).toString());
413         row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
414         row.put("priority", String.valueOf(flow.getPriority()));
415         return row;
416     }
417
418     private String getNodeDesc(Node node, ISwitchManager switchManager) {
419         if (switchManager == null) {
420             return null;
421         }
422         Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
423         return (desc == null) ? "" : desc.getValue();
424     }
425 }