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