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