4cd71a37640ba2f303c04570eb9549c845a82816
[controller.git] / opendaylight / web / flows / src / main / java / org / opendaylight / controller / flows / web / Flows.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.flows.web;
10
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
18 import javax.servlet.http.HttpServletRequest;
19
20 import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
21 import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
22 import org.opendaylight.controller.sal.authorization.Privilege;
23 import org.opendaylight.controller.sal.authorization.UserLevel;
24 import org.opendaylight.controller.sal.core.Description;
25 import org.opendaylight.controller.sal.core.Name;
26 import org.opendaylight.controller.sal.core.Node;
27 import org.opendaylight.controller.sal.core.NodeConnector;
28 import org.opendaylight.controller.sal.utils.GlobalConstants;
29 import org.opendaylight.controller.sal.utils.ServiceHelper;
30 import org.opendaylight.controller.sal.utils.Status;
31 import org.opendaylight.controller.sal.utils.StatusCode;
32 import org.opendaylight.controller.switchmanager.ISwitchManager;
33 import org.opendaylight.controller.switchmanager.Switch;
34 import org.opendaylight.controller.switchmanager.SwitchConfig;
35 import org.opendaylight.controller.web.DaylightWebUtil;
36 import org.opendaylight.controller.web.IDaylightWeb;
37 import org.springframework.stereotype.Controller;
38 import org.springframework.web.bind.annotation.PathVariable;
39 import org.springframework.web.bind.annotation.RequestMapping;
40 import org.springframework.web.bind.annotation.RequestMethod;
41 import org.springframework.web.bind.annotation.RequestParam;
42 import org.springframework.web.bind.annotation.ResponseBody;
43
44 import com.google.gson.Gson;
45
46 @Controller
47 @RequestMapping("/")
48 public class Flows implements IDaylightWeb {
49     private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
50     private static final String WEB_NAME = "Flows";
51
52     private static final String WEB_ID = "flows";
53     private static final short WEB_ORDER = 2;
54
55     private final Gson gson;
56
57     public Flows() {
58         ServiceHelper.registerGlobalService(IDaylightWeb.class, this, null);
59         gson = new Gson();
60     }
61
62     @Override
63     public String getWebName() {
64         return WEB_NAME;
65     }
66
67     @Override
68     public String getWebId() {
69         return WEB_ID;
70     }
71
72     @Override
73     public short getWebOrder() {
74         return WEB_ORDER;
75     }
76
77     @Override
78     public boolean isAuthorized(UserLevel userLevel) {
79         return userLevel.ordinal() <= AUTH_LEVEL.ordinal();
80     }
81
82     @RequestMapping(value = "/main")
83     @ResponseBody
84     public Map<String, Object> getFlows(HttpServletRequest request,
85             @RequestParam(required = false) String container) {
86         String containerName = (container == null) ? GlobalConstants.DEFAULT
87                 .toString() : container;
88
89         // Derive the privilege this user has on the current container
90         String userName = request.getUserPrincipal().getName();
91         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName,
92                 containerName, this);
93         if (privilege == Privilege.NONE) {
94             return null;
95         }
96
97         // fetch frm
98         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
99                 .getInstance(IForwardingRulesManager.class, containerName, this);
100         if (frm == null) {
101             return null;
102         }
103
104         // fetch sm
105         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
106                 .getInstance(ISwitchManager.class, containerName, this);
107         if (switchManager == null) {
108             return null;
109         }
110
111         // get static flow list
112         List<FlowConfig> staticFlowList = frm.getStaticFlows();
113         Set<Map<String, Object>> flowSet = new HashSet<Map<String, Object>>();
114         for (FlowConfig flowConfig : staticFlowList) {
115             Map<String, Object> entry = new HashMap<String, Object>();
116             entry.put("flow", flowConfig);
117             entry.put("name", flowConfig.getName());
118             Node node = flowConfig.getNode();
119             entry.put("node", getNodeDesc(node, switchManager));
120             entry.put("nodeId", node.toString());
121             flowSet.add(entry);
122         }
123
124         Map<String, Object> output = new HashMap<String, Object>(2);
125         output.put("flows", flowSet);
126         output.put("privilege", privilege);
127         return output;
128     }
129
130     @RequestMapping(value = "/node-ports")
131     @ResponseBody
132     public Map<String, Object> getNodePorts(HttpServletRequest request,
133             @RequestParam(required = false) String container) {
134         String containerName = (container == null) ? GlobalConstants.DEFAULT
135                 .toString() : container;
136
137         // Derive the privilege this user has on the current container
138         String userName = request.getUserPrincipal().getName();
139         if (DaylightWebUtil
140                 .getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
141             return null;
142         }
143
144         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
145                 .getInstance(ISwitchManager.class, containerName, this);
146         if (switchManager == null) {
147             return null;
148         }
149
150         Map<String, Object> nodes = new HashMap<String, Object>();
151         Map<Short, String> port;
152
153         for (Switch node : switchManager.getNetworkDevices()) {
154             port = new HashMap<Short, String>(); // new port
155             Set<NodeConnector> nodeConnectorSet = node.getNodeConnectors();
156
157             if (nodeConnectorSet != null) {
158                 for (NodeConnector nodeConnector : nodeConnectorSet) {
159                     String nodeConnectorName = ((Name) switchManager
160                             .getNodeConnectorProp(nodeConnector,
161                                     Name.NamePropName)).getValue();
162                     port.put((Short) nodeConnector.getID(), nodeConnectorName
163                             + "(" + nodeConnector.getNodeConnectorIDString()
164                             + ")");
165                 }
166             }
167
168             // add ports
169             Map<String, Object> entry = new HashMap<String, Object>();
170             entry.put("ports", port);
171
172             // add name
173             entry.put("name", getNodeDesc(node.getNode(), switchManager));
174
175             // add to the node
176             nodes.put(node.getNode().toString(), entry);
177         }
178
179         return nodes;
180     }
181
182     @RequestMapping(value = "/node-flows")
183     @ResponseBody
184     public Map<String, Object> getNodeFlows(HttpServletRequest request,
185             @RequestParam(required = false) String container) {
186         String containerName = (container == null) ? GlobalConstants.DEFAULT
187                 .toString() : container;
188
189         // Derive the privilege this user has on the current container
190         String userName = request.getUserPrincipal().getName();
191         if (DaylightWebUtil
192                 .getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
193             return null;
194         }
195
196         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
197                 .getInstance(ISwitchManager.class, containerName, this);
198         if (switchManager == null) {
199             return null;
200         }
201         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
202                 .getInstance(IForwardingRulesManager.class, containerName, this);
203         if (frm == null) {
204             return null;
205         }
206
207         Map<String, Object> nodes = new HashMap<String, Object>();
208
209         for (Switch sw : switchManager.getNetworkDevices()) {
210             Node node = sw.getNode();
211
212             List<FlowConfig> flows = frm.getStaticFlows(node);
213
214             String nodeDesc = node.toString();
215             SwitchConfig config = switchManager
216                     .getSwitchConfig(node.toString());
217             if ((config != null)
218                     && (config.getProperty(Description.propertyName) != null)) {
219                 nodeDesc = ((Description) config
220                         .getProperty(Description.propertyName)).getValue();
221             }
222
223             nodes.put(nodeDesc, flows.size());
224         }
225
226         return nodes;
227     }
228
229     @RequestMapping(value = "/flow", method = RequestMethod.POST)
230     @ResponseBody
231     public String actionFlow(@RequestParam(required = true) String action,
232             @RequestParam(required = false) String body,
233             @RequestParam(required = true) String nodeId,
234             HttpServletRequest request,
235             @RequestParam(required = false) String container) {
236         String containerName = (container == null) ? GlobalConstants.DEFAULT
237                 .toString() : container;
238
239         // Authorization check
240         String userName = request.getUserPrincipal().getName();
241         if (DaylightWebUtil
242                 .getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
243             return "Operation not authorized";
244         }
245
246         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
247                 .getInstance(IForwardingRulesManager.class, containerName, this);
248         if (frm == null) {
249             return null;
250         }
251
252         FlowConfig flow = gson.fromJson(body, FlowConfig.class);
253
254         Node node = Node.fromString(nodeId);
255         flow.setNode(node);
256         Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
257         if (action.equals("add")) {
258             result = frm.addStaticFlow(flow);
259             DaylightWebUtil.auditlog("Flow", userName, "added", flow.getName(),
260                     containerName);
261         }
262
263         return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result
264                 .getDescription();
265     }
266
267     @RequestMapping(value = "/flow/{nodeId}/{name:.*}", method = RequestMethod.POST)
268     @ResponseBody
269     public String removeFlow(@PathVariable("nodeId") String nodeId,
270             @PathVariable("name") String name,
271             @RequestParam(required = true) String action,
272             HttpServletRequest request,
273             @RequestParam(required = false) String container) {
274         String containerName = (container == null) ? GlobalConstants.DEFAULT
275                 .toString() : container;
276
277         // Authorization check
278         String userName = request.getUserPrincipal().getName();
279         if (DaylightWebUtil
280                 .getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
281             return "Operation not authorized";
282         }
283
284         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
285                 .getInstance(IForwardingRulesManager.class, containerName, this);
286         if (frm == null) {
287             return null;
288         }
289
290         Status result = null;
291         Node node = Node.fromString(nodeId);
292         if (node == null) {
293             return null;
294         }
295         if (action.equals("remove")) {
296             result = frm.removeStaticFlow(name, node);
297             if (result.isSuccess()) {
298                 DaylightWebUtil.auditlog("Flow", userName, "removed", name,
299                         containerName);
300             }
301         } else if (action.equals("toggle")) {
302             result = frm.toggleStaticFlowStatus(name, node);
303             if (result.isSuccess()) {
304                 DaylightWebUtil.auditlog("Flow", userName, "toggled", name,
305                         containerName);
306             }
307         } else {
308             result = new Status(StatusCode.BADREQUEST, "Unknown action");
309         }
310
311         return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result
312                 .getDescription();
313     }
314
315     @SuppressWarnings("unchecked")
316     @RequestMapping(value = "/flow/deleteFlows", method = RequestMethod.POST)
317     @ResponseBody
318     public String removeSelectedFlows(
319             @RequestParam(required = false) String body,
320             HttpServletRequest request,
321             @RequestParam(required = false) String container) {
322         String containerName = (container == null) ? GlobalConstants.DEFAULT
323                 .toString() : container;
324
325         // Authorization check
326         String userName = request.getUserPrincipal().getName();
327         if (DaylightWebUtil
328                 .getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
329             return "Operation not authorized";
330         }
331
332         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
333                 .getInstance(IForwardingRulesManager.class, containerName, this);
334         if (frm == null) {
335             return "Forwarding Rules Manager is not available";
336         }
337
338         List<Map<String, String>> flowList = new ArrayList<Map<String, String>>();
339         flowList = gson.fromJson(body, flowList.getClass());
340         Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
341         String status = "";
342         for (Map<String, String> flowEntry : flowList) {
343             Node node = Node.fromString(flowEntry.get("node"));
344             result = frm.removeStaticFlow(flowEntry.get("name"), node);
345             if (result.isSuccess()) {
346                 DaylightWebUtil.auditlog("Flow", userName, "removed",
347                         flowEntry.get("name"), containerName);
348             } else {
349                 status = flowEntry.get("name") + ", " + status;
350             }
351         }
352         if (!status.equals("")) {
353             return "Could not remove "
354                     + status.substring(0, status.length() - 2) + " Flow(s)";
355         } else {
356             return "Success";
357         }
358     }
359
360     private String getNodeDesc(Node node, ISwitchManager switchManager) {
361         Description desc = (Description) switchManager.getNodeProp(node,
362                 Description.propertyName);
363         String description = (desc == null) ? "" : desc.getValue();
364         return (description.isEmpty() || description.equalsIgnoreCase("none")) ? node
365                 .toString() : description;
366     }
367
368 }