OpenDaylight Controller functional modules.
[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.ServiceHelper;
36 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
37 import org.opendaylight.controller.switchmanager.ISwitchManager;
38 import org.opendaylight.controller.switchmanager.SwitchConfig;
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         } else {
89             // TODO: Change to use logger instead.
90             System.out.println("SwitchManager reference is NULL");
91         }
92         if (nodeSet != null) {
93             for (Node node : nodeSet) {
94                 HashMap<String, String> device = new HashMap<String, String>();
95                 SwitchConfig switchConfig = switchManager.getSwitchConfig(node.getNodeIDString());
96                 device.put("nodeName", switchConfig == null ? "" : switchConfig.getNodeName());
97                 device.put("nodeId", node.toString());
98                 lines.add(device);
99             }
100         }
101         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
102
103         List<String> guiFieldNames = new ArrayList<String>();
104         guiFieldNames.add("Node Names");
105         guiFieldNames.add("Node ID");
106         guiFieldNames.add("Statistics");
107
108         result.setColumnNames(guiFieldNames);
109         result.setNodeData(lines);
110         return result;
111     }
112
113     @RequestMapping(value = "/uptime", method = RequestMethod.GET)
114     @ResponseBody
115     public TroubleshootingJsonBean getUptime() {
116         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
117                 .getInstance(ISwitchManager.class, containerName, this);
118         List<HashMap<String, String>> lines = new ArrayList<HashMap<String, String>>();
119         Set<Node> nodeSet = null;
120         if (switchManager != null) {
121             nodeSet = switchManager.getNodes();
122         } else {
123             // TODO: Change to use logger instead.
124             System.out.println("SwitchManager reference is NULL");
125         }
126         if (nodeSet != null) {
127             for (Node node : nodeSet) {
128                 HashMap<String, String> device = new HashMap<String, String>();
129                 SwitchConfig switchConfig = switchManager.getSwitchConfig(node.getNodeIDString());
130                 device.put("nodeName", switchConfig == null ? "" : switchConfig.getNodeName());
131                 device.put("nodeId", node.toString());
132                 TimeStamp timeStamp = (TimeStamp) switchManager.getNodeProp(
133                         node, TimeStamp.TimeStampPropName);
134                 Long time = (timeStamp == null) ? 0 : timeStamp.getValue();
135                 String date = (time == 0) ? "" : (new Date(time)).toString();
136                 device.put("connectedSince", date);
137                 lines.add(device);
138             }
139         }
140         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
141
142         List<String> guiFieldNames = new ArrayList<String>();
143         guiFieldNames.add("Node Names");
144         guiFieldNames.add("Node ID");
145         guiFieldNames.add("Connected");
146
147         result.setColumnNames(guiFieldNames);
148         result.setNodeData(lines);
149         return result;
150     }
151
152     @RequestMapping(value = "/flowStats", method = RequestMethod.GET)
153     @ResponseBody
154     public TroubleshootingJsonBean getFlowStats(
155             @RequestParam("nodeId") String nodeId) {
156         Node node = Node.fromString(nodeId);
157         List<HashMap<String, String>> cells = new ArrayList<HashMap<String, String>>();
158         IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
159                 .getInstance(IStatisticsManager.class, containerName, this);
160
161         List<FlowOnNode> statistics = statisticsManager.getFlows(node);
162         for (FlowOnNode stats : statistics) {
163             cells.add(this.convertFlowStatistics(node, stats));
164         }
165         List<String> columnNames = new ArrayList<String>();
166         columnNames.addAll(Arrays.asList(new String[] { "Node", "In Port",
167                 "DL Src", "DL Dst", "DL Type", "DL Vlan", "NW Src", "NW Dst",
168                 "NW Proto", "TP Src", "TP Dst", "Actions", "Bytes", "Packets",
169                 "Time (s)", "Timeout (s)", "Out Port(s)", "Out Vlan",
170                 "Priority" }));
171         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
172         result.setColumnNames(columnNames);
173         result.setNodeData(cells);
174         return result;
175     }
176
177     @RequestMapping(value = "/portStats", method = RequestMethod.GET)
178     @ResponseBody
179     public TroubleshootingJsonBean getPortStats(
180             @RequestParam("nodeId") String nodeId) {
181         Node node = Node.fromString(nodeId);
182         List<HashMap<String, String>> cells = new ArrayList<HashMap<String, String>>();
183         IStatisticsManager statisticsManager = (IStatisticsManager) ServiceHelper
184                 .getInstance(IStatisticsManager.class, containerName, this);
185         List<NodeConnectorStatistics> statistics = statisticsManager
186                 .getNodeConnectorStatistics(node);
187         for (NodeConnectorStatistics stats : statistics) {
188             cells.add(this.convertPortsStatistics(stats));
189         }
190         TroubleshootingJsonBean result = new TroubleshootingJsonBean();
191         List<String> columnNames = new ArrayList<String>();
192         columnNames.addAll(Arrays.asList(new String[] { "Node Connector",
193                 "Rx Pkts", "Tx Pkts", "Rx Bytes", "Tx Bytes", "Rx Drops",
194                 "Tx Drops", "Rx Errs", "Tx Errs", "Rx Frame Errs",
195                 "Rx OverRun Errs", "Rx CRC Errs", "Collisions" }));
196         result.setColumnNames(columnNames);
197         result.setNodeData(cells);
198         return result;
199     }
200
201     private HashMap<String, String> convertPortsStatistics(
202             NodeConnectorStatistics ncStats) {
203         HashMap<String, String> row = new HashMap<String, String>();
204
205         row.put("nodeConnector",
206                 String.valueOf(ncStats.getNodeConnector().toString()));
207         row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
208         row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
209         row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));
210         row.put("txBytes", String.valueOf(ncStats.getTransmitByteCount()));
211         row.put("rxDrops", String.valueOf(ncStats.getReceiveDropCount()));
212         row.put("txDrops", String.valueOf(ncStats.getTransmitDropCount()));
213         row.put("rxErrors", String.valueOf(ncStats.getReceiveErrorCount()));
214         row.put("txErrors", String.valueOf(ncStats.getTransmitErrorCount()));
215         row.put("rxFrameErrors",
216                 String.valueOf(ncStats.getReceiveFrameErrorCount()));
217         row.put("rxOverRunErrors",
218                 String.valueOf(ncStats.getReceiveOverRunErrorCount()));
219         row.put("rxCRCErrors",
220                 String.valueOf(ncStats.getReceiveCRCErrorCount()));
221         row.put("collisions", String.valueOf(ncStats.getCollisionCount()));
222
223         return row;
224     }
225
226     private HashMap<String, String> convertFlowStatistics(Node node,
227             FlowOnNode flowOnNode) {
228         HashMap<String, String> row = new HashMap<String, String>();
229         Flow flow = flowOnNode.getFlow();
230         Match match = flow.getMatch();
231         row.put("nodeName", getNodeName(node));
232         if (match.isPresent(MatchType.IN_PORT)) {
233             row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch()
234                     .getField(MatchType.IN_PORT).getValue()).getID().toString());
235         } else {
236             row.put(MatchType.IN_PORT.id(), "*");
237         }
238         if (match.isPresent(MatchType.DL_SRC)) {
239             row.put(MatchType.DL_SRC.id(),
240                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
241                             .getField(MatchType.DL_SRC).getValue()))));
242         } else {
243             row.put(MatchType.DL_SRC.id(), "*");
244         }
245         if (match.isPresent(MatchType.DL_DST)) {
246             row.put(MatchType.DL_DST.id(),
247                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
248                             .getField(MatchType.DL_DST).getValue()))));
249         } else {
250             row.put(MatchType.DL_DST.id(), "*");
251         }
252         if (match.isPresent(MatchType.DL_TYPE)) {
253             row.put(MatchType.DL_TYPE.id(),
254                     EtherTypes.getEtherTypeName(((Short) flow.getMatch()
255                             .getField(MatchType.DL_TYPE).getValue())));
256         } else {
257             row.put(MatchType.DL_TYPE.id(), "*");
258         }
259
260         // Some physical switch has vlan as ffff to show "any" vlan
261         if (match.isPresent(MatchType.DL_VLAN)) {
262             if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
263                     .shortValue() < 0) {
264                 row.put(MatchType.DL_VLAN.id(), "0");
265             } else {
266                 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
267                         .getField(MatchType.DL_VLAN).getValue()).toString());
268             }
269         } else {
270             row.put(MatchType.DL_VLAN.id(), "*");
271         }
272         if (match.isPresent(MatchType.NW_SRC)) {
273             row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
274                     .getField(MatchType.NW_SRC).getValue()).getHostAddress());
275         } else {
276             row.put(MatchType.NW_SRC.id(), "*");
277         }
278         if (match.isPresent(MatchType.NW_DST)) {
279             row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
280                     .getField(MatchType.NW_DST).getValue()).getHostAddress());
281         } else {
282             row.put(MatchType.NW_DST.id(), "*");
283         }
284         if (match.isPresent(MatchType.NW_PROTO)) {
285             row.put(MatchType.NW_PROTO.id(),
286                     IPProtocols.getProtocolName(((Byte) flow.getMatch()
287                             .getField(MatchType.NW_PROTO).getValue())));
288         } else {
289             row.put(MatchType.NW_PROTO.id(), "*");
290         }
291         if (match.isPresent(MatchType.TP_SRC)) {
292             Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
293                     .getValue());
294             if (tpSrc < 0) {
295                 row.put(MatchType.TP_SRC.id(),
296                         ((Integer) (tpSrc.intValue() & 0x7FFF | 0x8000))
297                                 .toString());
298             } else {
299                 row.put(MatchType.TP_SRC.id(), tpSrc.toString());
300             }
301         } else {
302             row.put(MatchType.TP_SRC.id(), "*");
303         }
304         if (match.isPresent(MatchType.TP_DST)) {
305             Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
306                     .getValue());
307             if (tpDst < 0) {
308                 row.put(MatchType.TP_DST.id(),
309                         ((Integer) (tpDst.intValue() & 0x7FFF | 0x8000))
310                                 .toString());
311             } else {
312                 row.put(MatchType.TP_DST.id(), tpDst.toString());
313             }
314         } else {
315             row.put(MatchType.TP_DST.id(), "*");
316         }
317
318         row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
319         row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
320
321         StringBuffer actions = new StringBuffer();
322         StringBuffer outPorts = new StringBuffer();
323         String outVlanId = null;
324         for (Action action : flow.getActions()) {
325             actions.append(action.getType().toString() + "\n");
326             if (action instanceof Output) {
327                 Output ao = (Output) action;
328                 if (outPorts.length() > 0) {
329                     outPorts.append(" ");
330                 }
331                 outPorts.append(ao.getPort().getNodeConnectorIdAsString());
332             } else if (action instanceof SetVlanId) {
333                 SetVlanId av = (SetVlanId) action;
334                 outVlanId = String.valueOf(av.getVlanId());
335             }
336         }
337         if (outPorts.length() == 0) {
338             outPorts.append("*");
339         }
340         if (outVlanId == null) {
341             outVlanId = "*";
342         }
343         row.put("actions", actions.toString());
344         row.put("outPorts", outPorts.toString());
345         row.put("outVlanId", outVlanId);
346         row.put("durationSeconds",
347                 ((Integer) flowOnNode.getDurationSeconds()).toString());
348         row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
349         row.put("priority", String.valueOf(flow.getPriority()));
350         return row;
351     }
352
353     private String getNodeName(Node node) {
354         String nodeName = "";
355         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
356                 .getInstance(ISwitchManager.class, containerName, this);
357         if (switchManager != null) {
358             SwitchConfig config = switchManager.getSwitchConfig(node
359                     .getNodeIDString());
360             if (config != null) {
361                 nodeName = config.getNodeName();
362             }
363         }
364         return nodeName;
365     }
366 }