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