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