Merge "Fixed deserialization of IdentityRefs in Restconf URI."
[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, @RequestParam(required = false) String container) {
85         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
86
87         // Derive the privilege this user has on the current container
88         String userName = request.getUserPrincipal().getName();
89         Privilege privilege = DaylightWebUtil.getContainerPrivilege(userName, containerName, this);
90         if (privilege == Privilege.NONE) {
91             return null;
92         }
93
94         // fetch frm
95         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
96                 IForwardingRulesManager.class, containerName, this);
97         if (frm == null) {
98             return null;
99         }
100
101         // fetch sm
102         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
103                 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, @RequestParam(required = false) String container) {
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         if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
135             return null;
136         }
137
138         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
139                 this);
140         if (switchManager == null) {
141             return null;
142         }
143
144         Map<String, Object> nodes = new HashMap<String, Object>();
145         Map<String, String> port;
146
147         for (Switch node : switchManager.getNetworkDevices()) {
148             port = new HashMap<String, String>(); // new port
149             Set<NodeConnector> nodeConnectorSet = node.getNodeConnectors();
150
151             if (nodeConnectorSet != null) {
152                 for (NodeConnector nodeConnector : nodeConnectorSet) {
153                     String nodeConnectorName = ((Name) switchManager.getNodeConnectorProp(nodeConnector,
154                             Name.NamePropName)).getValue();
155                     port.put( nodeConnector.getID().toString(),
156                             nodeConnectorName + "(" + nodeConnector.getNodeConnectorIDString() + ")");
157                 }
158             }
159
160             // add ports
161             Map<String, Object> entry = new HashMap<String, Object>();
162             entry.put("ports", port);
163
164             // add name
165             entry.put("name", getNodeDesc(node.getNode(), switchManager));
166
167             // add to the node
168             nodes.put(node.getNode().toString(), entry);
169         }
170
171         return nodes;
172     }
173
174     @RequestMapping(value = "/node-flows")
175     @ResponseBody
176     public Map<String, Object> getNodeFlows(HttpServletRequest request, @RequestParam(required = false) String container) {
177         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
178
179         // Derive the privilege this user has on the current container
180         String userName = request.getUserPrincipal().getName();
181         if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) == Privilege.NONE) {
182             return null;
183         }
184
185         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
186                 this);
187         if (switchManager == null) {
188             return null;
189         }
190         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
191                 IForwardingRulesManager.class, containerName, this);
192         if (frm == null) {
193             return null;
194         }
195
196         Map<String, Object> nodes = new HashMap<String, Object>();
197
198         for (Switch sw : switchManager.getNetworkDevices()) {
199             Node node = sw.getNode();
200
201             List<FlowConfig> flows = frm.getStaticFlows(node);
202
203             String nodeDesc = node.toString();
204             SwitchConfig config = switchManager.getSwitchConfig(node.toString());
205             if ((config != null) && (config.getProperty(Description.propertyName) != null)) {
206                 nodeDesc = ((Description) config.getProperty(Description.propertyName)).getValue();
207             }
208
209             nodes.put(nodeDesc, flows.size());
210         }
211
212         return nodes;
213     }
214
215
216     @RequestMapping(value = "/flow", method = RequestMethod.POST)
217     @ResponseBody
218     public String actionFlow(@RequestParam(required = true) String action, @RequestParam(required = false) String body,
219             @RequestParam(required = true) String nodeId, HttpServletRequest request,
220             @RequestParam(required = false) String container) {
221         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
222
223         // Authorization check
224         String userName = request.getUserPrincipal().getName();
225         if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
226             return "Operation not authorized";
227         }
228
229         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
230                 IForwardingRulesManager.class, containerName, this);
231         if (frm == null) {
232             return null;
233         }
234
235         FlowConfig flow = gson.fromJson(body, FlowConfig.class);
236
237         Node node = Node.fromString(nodeId);
238         flow.setNode(node);
239
240         Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
241         if (action.equals("add")) {
242             result = frm.addStaticFlow(flow);
243             if (result.isSuccess()) {
244                 DaylightWebUtil.auditlog("Flow Entry", userName, "added", flow.getName() + " on Node "
245                         + DaylightWebUtil.getNodeDesc(node, containerName, this), containerName);
246             }
247         } else if (action.equals("edit")){
248             result = frm.modifyStaticFlow(flow);
249             if (result.isSuccess()) {
250                 DaylightWebUtil.auditlog("Flow Entry", userName, "updated", flow.getName() + " on Node "
251                         + DaylightWebUtil.getNodeDesc(node, containerName, this), containerName);
252             }
253         }
254
255         return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result.getDescription();
256     }
257
258     @RequestMapping(value = "/flow/{nodeId}/{name:.*}", method = RequestMethod.POST)
259     @ResponseBody
260     public String removeFlow(@PathVariable("nodeId") String nodeId, @PathVariable("name") String name,
261             @RequestParam(required = true) String action, HttpServletRequest request,
262             @RequestParam(required = false) String container) {
263         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
264
265         // Authorization check
266         String userName = request.getUserPrincipal().getName();
267         if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
268             return "Operation not authorized";
269         }
270
271         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
272                 IForwardingRulesManager.class, containerName, this);
273         if (frm == null) {
274             return null;
275         }
276
277         Status result = null;
278         Node node = Node.fromString(nodeId);
279         if (node == null) {
280             return null;
281         }
282         if (action.equals("remove")) {
283             result = frm.removeStaticFlow(name, node);
284             if (result.isSuccess()) {
285                 DaylightWebUtil.auditlog("Flow Entry", userName, "removed",
286                         name + " on Node " + DaylightWebUtil.getNodeDesc(node, containerName, this), containerName);
287             }
288         } else if (action.equals("toggle")) {
289             result = frm.toggleStaticFlowStatus(name, node);
290             if (result.isSuccess()) {
291                 DaylightWebUtil.auditlog("Flow Entry", userName, "toggled",
292                         name + " on Node " + DaylightWebUtil.getNodeDesc(node, containerName, this), containerName);
293             }
294         } else {
295             result = new Status(StatusCode.BADREQUEST, "Unknown action");
296         }
297
298         return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result.getDescription();
299     }
300
301     @SuppressWarnings("unchecked")
302     @RequestMapping(value = "/flow/deleteFlows", method = RequestMethod.POST)
303     @ResponseBody
304     public String removeSelectedFlows(@RequestParam(required = false) String body, HttpServletRequest request,
305             @RequestParam(required = false) String container) {
306         String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container;
307
308         // Authorization check
309         String userName = request.getUserPrincipal().getName();
310         if (DaylightWebUtil.getContainerPrivilege(userName, containerName, this) != Privilege.WRITE) {
311             return "Operation not authorized";
312         }
313         IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
314                 IForwardingRulesManager.class, containerName, this);
315         if (frm == null) {
316             return "Forwarding Rules Manager is not available";
317         }
318
319         List<Map<String, String>> flowList = new ArrayList<Map<String, String>>();
320         flowList = gson.fromJson(body, flowList.getClass());
321         Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
322         String status = "";
323         for (Map<String, String> flowEntry : flowList) {
324             Node node = Node.fromString(flowEntry.get("node"));
325             result = frm.removeStaticFlow(flowEntry.get("name"), node);
326             if (result.isSuccess()) {
327                 DaylightWebUtil.auditlog("Flow Entry", userName, "removed", flowEntry.get("name") + " on Node "
328                         + DaylightWebUtil.getNodeDesc(node, containerName, this), containerName);
329             } else {
330                 status = flowEntry.get("name") + ", " + status;
331             }
332         }
333         if (!status.equals("")) {
334             return "Could not remove " + status.substring(0, status.length() - 2) + " Flow(s)";
335         } else {
336             return "Success";
337         }
338     }
339
340     private String getNodeDesc(Node node, ISwitchManager switchManager) {
341         Description desc = (Description) switchManager.getNodeProp(node, Description.propertyName);
342         String description = (desc == null) ? "" : desc.getValue();
343         return (description.isEmpty() || description.equalsIgnoreCase("none")) ? node.toString() : description;
344     }
345
346 }