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