dfa21075ea845eaf3140a701cf99d706553c41dc
[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.IDaylightWeb;
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 IDaylightWeb {
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(IDaylightWeb.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())
233                     .getNodeConnectorIdAsString());
234         } else {
235             row.put(MatchType.IN_PORT.id(), "*");
236         }
237         if (match.isPresent(MatchType.DL_SRC)) {
238             row.put(MatchType.DL_SRC.id(),
239                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
240                             .getField(MatchType.DL_SRC).getValue()))));
241         } else {
242             row.put(MatchType.DL_SRC.id(), "*");
243         }
244         if (match.isPresent(MatchType.DL_DST)) {
245             row.put(MatchType.DL_DST.id(),
246                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
247                             .getField(MatchType.DL_DST).getValue()))));
248         } else {
249             row.put(MatchType.DL_DST.id(), "*");
250         }
251         if (match.isPresent(MatchType.DL_TYPE)) {
252             row.put(MatchType.DL_TYPE.id(),
253                     EtherTypes.getEtherTypeName(((Short) flow.getMatch()
254                             .getField(MatchType.DL_TYPE).getValue())));
255         } else {
256             row.put(MatchType.DL_TYPE.id(), "*");
257         }
258
259         // Some physical switch has vlan as ffff to show "any" vlan
260         if (match.isPresent(MatchType.DL_VLAN)) {
261             if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
262                     .shortValue() < 0) {
263                 row.put(MatchType.DL_VLAN.id(), "0");
264             } else {
265                 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
266                         .getField(MatchType.DL_VLAN).getValue()).toString());
267             }
268         } else {
269             row.put(MatchType.DL_VLAN.id(), "*");
270         }
271         if (match.isPresent(MatchType.NW_SRC)) {
272             row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
273                     .getField(MatchType.NW_SRC).getValue()).getHostAddress());
274         } else {
275             row.put(MatchType.NW_SRC.id(), "*");
276         }
277         if (match.isPresent(MatchType.NW_DST)) {
278             row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
279                     .getField(MatchType.NW_DST).getValue()).getHostAddress());
280         } else {
281             row.put(MatchType.NW_DST.id(), "*");
282         }
283         if (match.isPresent(MatchType.NW_PROTO)) {
284             row.put(MatchType.NW_PROTO.id(),
285                     IPProtocols.getProtocolName(((Byte) flow.getMatch()
286                             .getField(MatchType.NW_PROTO).getValue())));
287         } else {
288             row.put(MatchType.NW_PROTO.id(), "*");
289         }
290         if (match.isPresent(MatchType.TP_SRC)) {
291             Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
292                     .getValue());
293             row.put(MatchType.TP_SRC.id(),
294                         String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
295         } else {
296             row.put(MatchType.TP_SRC.id(), "*");
297         }
298         if (match.isPresent(MatchType.TP_DST)) {
299             Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
300                     .getValue());
301             row.put(MatchType.TP_DST.id(),
302                         String.valueOf(NetUtils.getUnsignedShort(tpDst)));
303         } else {
304             row.put(MatchType.TP_DST.id(), "*");
305         }
306
307         row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
308         row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
309
310         StringBuffer actions = new StringBuffer();
311         StringBuffer outPorts = new StringBuffer();
312         String outVlanId = null;
313         for (Action action : flow.getActions()) {
314             actions.append(action.getType().toString() + "\n");
315             if (action instanceof Output) {
316                 Output ao = (Output) action;
317                 if (outPorts.length() > 0) {
318                     outPorts.append(" ");
319                 }
320                 outPorts.append(ao.getPort().getNodeConnectorIdAsString());
321             } else if (action instanceof SetVlanId) {
322                 SetVlanId av = (SetVlanId) action;
323                 outVlanId = String.valueOf(av.getVlanId());
324             }
325         }
326         if (outPorts.length() == 0) {
327             outPorts.append("*");
328         }
329         if (outVlanId == null) {
330             outVlanId = "*";
331         }
332         row.put("actions", actions.toString());
333         row.put("outPorts", outPorts.toString());
334         row.put("outVlanId", outVlanId);
335         row.put("durationSeconds",
336                 ((Integer) flowOnNode.getDurationSeconds()).toString());
337         row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
338         row.put("priority", String.valueOf(flow.getPriority()));
339         return row;
340     }
341
342 }