blob: a3f06ceaf3f7ab615ae062d9e4d35d02117eb4e9 [file] [log] [blame]
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001package net.floodlightcontroller.debugevent.web;
2
3
4import java.util.HashMap;
5import java.util.List;
6import java.util.Map;
7
8import net.floodlightcontroller.debugevent.IDebugEventService.DebugEventInfo;
9import net.floodlightcontroller.debugevent.IDebugEventService.EventType;
10
11import org.restlet.resource.Get;
12import org.restlet.resource.Post;
13import org.slf4j.Logger;
14import org.slf4j.LoggerFactory;
15
16/**
17 * Web interface for Debug Events
18 *
19 * @author Saurav
20 */
21public class DebugEventResource extends DebugEventResourceBase {
22 protected static Logger logger =
23 LoggerFactory.getLogger(DebugEventResource.class);
24
25 /**
26 * The output JSON model that contains the counter information
27 */
28 public static class DebugEventInfoOutput {
29 protected class DEInfo {
30 private final boolean enabled;
31 private final int bufferCapacity;
32 private final EventType eventType;
33 private final String eventDesc;
34 private final String eventName;
35 private final String moduleName;
36 private final String[] metaData;
37 private final List<Map<String,String>> eventHistory;
38
39 DEInfo(DebugEventInfo dei) {
40 this.moduleName = dei.getEventInfo().getModuleName();
41 this.eventName = dei.getEventInfo().getEventName();
42 this.eventDesc = dei.getEventInfo().getEventDesc();
43 this.metaData = dei.getEventInfo().getMetaData();
44 this.enabled = dei.getEventInfo().isEnabled();
45 this.eventType = dei.getEventInfo().getEtype();
46 this.bufferCapacity = dei.getEventInfo().getBufferCapacity();
47 this.eventHistory = dei.getEvents();
48 }
49 public boolean isEnabled() {
50 return enabled;
51 }
52 public int getBufferCapacity() {
53 return bufferCapacity;
54 }
55 public String getEventDesc() {
56 return eventDesc;
57 }
58 public String getEventName() {
59 return eventName;
60 }
61 public String getModuleName() {
62 return moduleName;
63 }
64 public String[] getMetaData() {
65 return metaData;
66 }
67 public EventType getEventType() {
68 return eventType;
69 }
70 public List<Map<String,String>> getEventHistory() {
71 return eventHistory;
72 }
73
74 }
75
76 public Map<String, DEInfo> eventMap = null;
77 public List<String> names = null;
78 public String error = null;
79
80 DebugEventInfoOutput(boolean getList) {
81 if (!getList) {
82 eventMap = new HashMap<String, DEInfo>();
83 }
84 }
85 public Map<String, DEInfo> getEventMap() {
86 return eventMap;
87 }
88 public List<String> getNames() {
89 return names;
90 }
91 public String getError() {
92 return error;
93 }
94
95 }
96
97 public enum Option {
98 ALL, ONE_MODULE, ONE_MODULE_EVENT, ERROR_BAD_MODULE_NAME, ERROR_BAD_PARAM,
99 ERROR_BAD_MODULE_EVENT_NAME
100 }
101
102 public static class DebugEventPost {
103 public Boolean reset;
104
105 public Boolean getReset() {
106 return reset;
107 }
108 public void setReset(Boolean reset) {
109 this.reset = reset;
110 }
111 }
112
113 public static class ResetOutput {
114 String error = null;
115
116 public String getError() {
117 return error;
118 }
119 public void setError(String error) {
120 this.error = error;
121 }
122 }
123
124 /**
125 * Reset events
126 *
127 * If using curl:
128 * curl -X POST -d {\"reset\":true} -H "Content-Type: application/json" URL
129 * where URL must be in one of the following forms for resetting registered events:
130 * "http://{controller-hostname}:8080/wm/debugevent/
131 * "http://{controller-hostname}:8080/wm/debugevent/{param1}
132 * "http://{controller-hostname}:8080/wm/debugevent/{param1}/{param2}
133 *
134 * Not giving {param1} will reset all events
135 * {param1} can be 'all' or the name of a module. The former case will reset
136 * all events, while the latter will reset all events for the moduleName (if
137 * param2 is null).{param2} must be an eventName for the given moduleName to
138 * reset a specific event.
139 */
140 @Post
141 public ResetOutput postHandler(DebugEventPost postData) {
142 ResetOutput output = new ResetOutput();
143 String param1 = (String)getRequestAttributes().get("param1");
144 String param2 = (String)getRequestAttributes().get("param2");
145
146 if (postData.getReset() != null && postData.getReset()) {
147 Option choice = Option.ERROR_BAD_PARAM;
148
149 if (param1 == null) {
150 param1 = "all";
151 choice = Option.ALL;
152 } else if (param1.equals("all")) {
153 choice = Option.ALL;
154 } else if (param2 == null) {
155 boolean isRegistered = debugEvent.containsModuleName(param1);
156 if (isRegistered) {
157 choice = Option.ONE_MODULE;
158 } else {
159 choice = Option.ERROR_BAD_MODULE_NAME;
160 }
161 } else {
162 // differentiate between disabled and non-existing events
163 boolean isRegistered = debugEvent.containsModuleEventName(param1, param2);
164 if (isRegistered) {
165 choice = Option.ONE_MODULE_EVENT;
166 } else {
167 choice = Option.ERROR_BAD_MODULE_EVENT_NAME;
168 }
169 }
170
171 switch (choice) {
172 case ALL:
173 debugEvent.resetAllEvents();
174 break;
175 case ONE_MODULE:
176 debugEvent.resetAllModuleEvents(param1);
177 break;
178 case ONE_MODULE_EVENT:
179 debugEvent.resetSingleEvent(param1, param2);
180 break;
181 case ERROR_BAD_MODULE_NAME:
182 output.error = "Module name has no corresponding registered events";
183 break;
184 case ERROR_BAD_MODULE_EVENT_NAME:
185 output.error = "Event not registered";
186 break;
187 case ERROR_BAD_PARAM:
188 output.error = "Bad param";
189 }
190 }
191
192 return output;
193
194 }
195
196 /**
197 * Return the debug event data for the get rest-api call
198 *
199 * URL must be in one of the following forms for retrieving a list
200 * moduleNames "http://{controller-hostname}:8080/wm/debugevent/
201 * counterNames "http://{controller-hostname}:8080/wm/debugevent/{moduleName}
202 *
203 * URL must be in one of the following forms for retrieving event data:
204 * "http://{controller-hostname}:8080/wm/debugevent/{param1}
205 * "http://{controller-hostname}:8080/wm/debugevent/{param1}/{param2}
206 *
207 * where {param1} must be one of (no quotes):
208 * null if nothing is given then by default the list
209 * of all moduleNames is returned for which
210 * events have been registered
211 * "all" can return value/info on all active events
212 * but is currently disallowed
213 * "{moduleName}" returns value/info on events for the specified module
214 * depending on the value of param2
215 * and {param2} must be one of (no quotes):
216 * null returns all eventNames registered for the
217 * given moduleName (in param1)
218 * "{eventName}" returns value/info for specific event if it is active.
219 *
220 */
221 @Get("json")
222 public DebugEventInfoOutput handleEventInfoQuery() {
223 Option choice = Option.ERROR_BAD_PARAM;
224 DebugEventInfoOutput output;
225 String laststr = getQueryValue("last");
226 int last = Integer.MAX_VALUE;
227 try {
228 if (laststr != null)
229 last = Integer.valueOf(laststr);
230 if (last < 1) last = Integer.MAX_VALUE;
231 } catch (NumberFormatException e) {
232 output = new DebugEventInfoOutput(false);
233 output.error = "Expected an integer requesting last X events;" +
234 " received " + laststr;
235 return output;
236 }
237 String param1 = (String)getRequestAttributes().get("param1");
238 String param2 = (String)getRequestAttributes().get("param2");
239
240 if (param1 == null) {
241 output = new DebugEventInfoOutput(true);
242 return listEvents(output);
243 } else if (param1.equals("all")) {
244 output = new DebugEventInfoOutput(false);
245 //populateEvents(debugEvent.getAllEventHistory(), output);
246 output.error = "Cannot retrieve all events - please select a specific event";
247 return output;
248 }
249
250 if (param2 == null) {
251 output = new DebugEventInfoOutput(true);
252 boolean isRegistered = debugEvent.containsModuleName(param1);
253 if (isRegistered) {
254 return listEvents(param1, output);
255 } else {
256 choice = Option.ERROR_BAD_MODULE_NAME;
257 }
258 } else if (param2.equals("all")) {
259 output = new DebugEventInfoOutput(false);
260 //choice = Option.ONE_MODULE;
261 output.error = "Cannot retrieve all events - please select a specific event";
262 return output;
263 } else {
264 // differentiate between disabled and non-existing events
265 boolean isRegistered = debugEvent.containsModuleEventName(param1, param2);
266 if (isRegistered) {
267 choice = Option.ONE_MODULE_EVENT;
268 } else {
269 choice = Option.ERROR_BAD_MODULE_EVENT_NAME;
270 }
271 }
272
273 output = new DebugEventInfoOutput(false);
274 switch (choice) {
275 case ONE_MODULE:
276 populateEvents(debugEvent.getModuleEventHistory(param1), output);
277 break;
278 case ONE_MODULE_EVENT:
279 populateSingleEvent(debugEvent.getSingleEventHistory(param1, param2, last),
280 output);
281 break;
282 case ERROR_BAD_MODULE_NAME:
283 output.error = "Module name has no corresponding registered events";
284 break;
285 case ERROR_BAD_MODULE_EVENT_NAME:
286 output.error = "Event not registered";
287 break;
288 case ERROR_BAD_PARAM:
289 default:
290 output.error = "Bad param";
291 }
292
293 return output;
294 }
295
296 private DebugEventInfoOutput listEvents(DebugEventInfoOutput output) {
297 output.names = debugEvent.getModuleList();
298 return output;
299 }
300
301 private DebugEventInfoOutput listEvents(String moduleName,
302 DebugEventInfoOutput output) {
303 output.names = debugEvent.getModuleEventList(moduleName);
304 return output;
305 }
306
307 private void populateSingleEvent(DebugEventInfo singleEventHistory,
308 DebugEventInfoOutput output) {
309 if (singleEventHistory != null) {
310 output.eventMap.put(singleEventHistory.getEventInfo().getModuleEventName(),
311 output.new DEInfo(singleEventHistory));
312 }
313 }
314
315 private void populateEvents(List<DebugEventInfo> eventHistory,
316 DebugEventInfoOutput output) {
317 if (eventHistory != null) {
318 for (DebugEventInfo de : eventHistory)
319 populateSingleEvent(de, output);
320 }
321 }
322}