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