Merge "Increase timeout for waiting for broker service in sal-binding-it."
[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","Vlan Priority", "NW Src", "NW Dst","ToS Bits",
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
233         Map<String, String> row = new HashMap<String, String>();
234
235         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
236                 .getInstance(ISwitchManager.class, containerName, this);
237         NodeConnector nodeConnector = ncStats.getNodeConnector();
238         Description description = (Description) switchManager.getNodeProp(nodeConnector.getNode(), Description.propertyName);
239         String desc = (description == null) ? "" : description.getValue();
240         String nodeName = desc.equalsIgnoreCase("none") ? nodeConnector.getNode().getNodeIDString() : desc;
241         String nodeConnectorDisplayName = nodeConnector.getType() + "|" + nodeConnector.getID() + "@" + nodeName;
242         row.put("nodeConnector",
243                 String.valueOf(nodeConnectorDisplayName));
244
245         row.put("rxPkts", String.valueOf(ncStats.getReceivePacketCount()));
246         row.put("txPkts", String.valueOf(ncStats.getTransmitPacketCount()));
247         row.put("rxBytes", String.valueOf(ncStats.getReceiveByteCount()));
248         row.put("txBytes", String.valueOf(ncStats.getTransmitByteCount()));
249         row.put("rxDrops", String.valueOf(ncStats.getReceiveDropCount()));
250         row.put("txDrops", String.valueOf(ncStats.getTransmitDropCount()));
251         row.put("rxErrors", String.valueOf(ncStats.getReceiveErrorCount()));
252         row.put("txErrors", String.valueOf(ncStats.getTransmitErrorCount()));
253         row.put("rxFrameErrors",
254                 String.valueOf(ncStats.getReceiveFrameErrorCount()));
255         row.put("rxOverRunErrors",
256                 String.valueOf(ncStats.getReceiveOverRunErrorCount()));
257         row.put("rxCRCErrors",
258                 String.valueOf(ncStats.getReceiveCRCErrorCount()));
259         row.put("collisions", String.valueOf(ncStats.getCollisionCount()));
260
261         return row;
262     }
263
264     private Map<String, String> convertFlowStatistics(Node node,
265             FlowOnNode flowOnNode,
266             String containerName) {
267         Map<String, String> row = new HashMap<String, String>();
268         Flow flow = flowOnNode.getFlow();
269         Match match = flow.getMatch();
270         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
271                 .getInstance(ISwitchManager.class, containerName, this);
272         String desc = getNodeDesc(node, switchManager);
273         desc = (desc == null || desc.isEmpty() || desc.equalsIgnoreCase("none"))?
274                         node.toString() : desc;
275         row.put("nodeName", desc);
276         if (match.isPresent(MatchType.IN_PORT)) {
277             row.put(MatchType.IN_PORT.id(), ((NodeConnector) flow.getMatch()
278                     .getField(MatchType.IN_PORT).getValue())
279                     .getNodeConnectorIdAsString());
280         } else {
281             row.put(MatchType.IN_PORT.id(), "*");
282         }
283         if (match.isPresent(MatchType.DL_SRC)) {
284             row.put(MatchType.DL_SRC.id(),
285                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
286                             .getField(MatchType.DL_SRC).getValue()))));
287         } else {
288             row.put(MatchType.DL_SRC.id(), "*");
289         }
290         if (match.isPresent(MatchType.DL_DST)) {
291             row.put(MatchType.DL_DST.id(),
292                     (HexEncode.bytesToHexString(((byte[]) flow.getMatch()
293                             .getField(MatchType.DL_DST).getValue()))));
294         } else {
295             row.put(MatchType.DL_DST.id(), "*");
296         }
297         if (match.isPresent(MatchType.DL_TYPE)) {
298             row.put(MatchType.DL_TYPE.id(),
299                     EtherTypes.getEtherTypeName(((Short) flow.getMatch()
300                             .getField(MatchType.DL_TYPE).getValue())));
301         } else {
302             row.put(MatchType.DL_TYPE.id(), "*");
303         }
304
305         // Some physical switch has vlan as ffff to show "any" vlan
306         if (match.isPresent(MatchType.DL_VLAN)) {
307             if (((Short) flow.getMatch().getField(MatchType.DL_VLAN).getValue())
308                     .shortValue() < 0) {
309                 row.put(MatchType.DL_VLAN.id(), "0");
310             } else {
311                 row.put(MatchType.DL_VLAN.id(), ((Short) flow.getMatch()
312                         .getField(MatchType.DL_VLAN).getValue()).toString());
313             }
314         } else {
315             row.put(MatchType.DL_VLAN.id(), "*");
316         }
317         //Vlan Priority
318         if (match.isPresent(MatchType.DL_VLAN_PR)) {
319             if (((Byte) flow.getMatch().getField(MatchType.DL_VLAN_PR).getValue())
320                     .shortValue() < 0) {
321                 row.put(MatchType.DL_VLAN_PR.id(), "0");
322             } else {
323                 row.put(MatchType.DL_VLAN_PR.id(), ((Byte) flow.getMatch()
324                         .getField(MatchType.DL_VLAN_PR).getValue()).toString());
325             }
326         } else {
327             row.put(MatchType.DL_VLAN_PR.id(), "*");
328         }
329
330         if (match.isPresent(MatchType.NW_SRC)) {
331             row.put(MatchType.NW_SRC.id(), ((InetAddress) flow.getMatch()
332                     .getField(MatchType.NW_SRC).getValue()).getHostAddress());
333         } else {
334             row.put(MatchType.NW_SRC.id(), "*");
335         }
336         if (match.isPresent(MatchType.NW_DST)) {
337             row.put(MatchType.NW_DST.id(), ((InetAddress) flow.getMatch()
338                     .getField(MatchType.NW_DST).getValue()).getHostAddress());
339         } else {
340             row.put(MatchType.NW_DST.id(), "*");
341         }
342         if (match.isPresent(MatchType.NW_TOS)) {
343             row.put(MatchType.NW_TOS.id(), ((Byte) flow.getMatch()
344                         .getField(MatchType.NW_TOS).getValue()).toString());
345         } else {
346             row.put(MatchType.NW_TOS.id(), "*");
347         }
348         if (match.isPresent(MatchType.NW_PROTO)) {
349             row.put(MatchType.NW_PROTO.id(),
350                     IPProtocols.getProtocolName(((Byte) flow.getMatch()
351                             .getField(MatchType.NW_PROTO).getValue())));
352         } else {
353             row.put(MatchType.NW_PROTO.id(), "*");
354         }
355         if (match.isPresent(MatchType.TP_SRC)) {
356             Short tpSrc = (Short) (flow.getMatch().getField(MatchType.TP_SRC)
357                     .getValue());
358             row.put(MatchType.TP_SRC.id(),
359                         String.valueOf(NetUtils.getUnsignedShort(tpSrc)));
360         } else {
361             row.put(MatchType.TP_SRC.id(), "*");
362         }
363         if (match.isPresent(MatchType.TP_DST)) {
364             Short tpDst = (Short) (flow.getMatch().getField(MatchType.TP_DST)
365                     .getValue());
366             row.put(MatchType.TP_DST.id(),
367                         String.valueOf(NetUtils.getUnsignedShort(tpDst)));
368         } else {
369             row.put(MatchType.TP_DST.id(), "*");
370         }
371
372         row.put("byteCount", ((Long) flowOnNode.getByteCount()).toString());
373         row.put("packetCount", ((Long) flowOnNode.getPacketCount()).toString());
374
375         StringBuffer actions = new StringBuffer();
376         StringBuffer outPorts = new StringBuffer();
377         for (Action action : flow.getActions()) {
378
379             if (action instanceof Output) {
380                 Output ao = (Output) action;
381                 if (outPorts.length() > 0) {
382                     outPorts.append(" ");
383                 }
384                 actions.append(action.getType().toString()).append(" = ").append(ao.getPort().getNodeConnectorIdAsString()).append("<br>");
385             } else if (action instanceof SetVlanId) {
386                 SetVlanId av = (SetVlanId) action;
387                 String outVlanId = String.valueOf(av.getVlanId());
388                 actions.append(action.getType().toString()).append(" = ").append(outVlanId).append("<br>");
389             } else if (action instanceof SetDlSrc) {
390                 SetDlSrc ads = (SetDlSrc) action;
391                 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(ads.getDlAddress())).append("<br>");
392             } else if (action instanceof SetDlDst) {
393                 SetDlDst add = (SetDlDst) action;
394                 actions.append(action.getType().toString()).append(" = ").append(HexEncode.bytesToHexStringFormat(add.getDlAddress())).append("<br>");
395             } else if (action instanceof SetNwSrc) {
396                 SetNwSrc ans = (SetNwSrc) action;
397                 actions.append(action.getType().toString()).append(" = ").append(ans.getAddressAsString()).append("<br>");
398             } else if (action instanceof SetNwDst) {
399                 SetNwDst and = (SetNwDst) action;
400                 actions.append(action.getType().toString()).append(" = ").append(and.getAddressAsString()).append("<br>");
401             } else if (action instanceof SetNwTos) {
402                 SetNwTos ant = (SetNwTos) action;
403                 actions.append(action.getType().toString()).append(" = ").append(ant.getNwTos()).append("<br>");
404             } else if (action instanceof SetTpSrc) {
405                 SetTpSrc ads = (SetTpSrc) action;
406                 actions.append(action.getType().toString()).append(" = ").append(ads.getPort()).append("<br>");
407             } else if (action instanceof SetTpDst) {
408                 SetTpDst atd = (SetTpDst) action;
409                 actions.append(action.getType().toString()).append(" = ").append(atd.getPort()).append("<br>");
410             } else if (action instanceof SetVlanPcp) {
411                 SetVlanPcp avp = (SetVlanPcp) action;
412                 actions.append(action.getType().toString()).append(" = ").append(avp.getPcp()).append("<br>");
413                 // } else if (action instanceof SetDlSrc) {
414                 // SetDlSrc ads = (SetDlSrc) action;
415             } else {
416                 actions.append(action.getType().toString()).append("<br>");
417             }
418         }
419         row.put("actions", actions.toString());
420         row.put("durationSeconds",
421                 ((Integer) flowOnNode.getDurationSeconds()).toString());
422         row.put("idleTimeout", ((Short) flow.getIdleTimeout()).toString());
423         row.put("priority", String.valueOf(NetUtils.getUnsignedShort(flow.getPriority())));
424         return row;
425     }
426
427     private String getNodeDesc(Node node, ISwitchManager switchManager) {
428         if (switchManager == null) {
429             return null;
430         }
431         Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
432         return (desc == null) ? "" : desc.getValue();
433     }
434 }