Merge "Replace exception.printStacktrace with write to log."
[controller.git] / opendaylight / web / root / src / main / java / org / opendaylight / controller / web / DaylightWebAdmin.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.web;
10
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Set;
16
17 import javax.servlet.http.HttpServletRequest;
18
19 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
20 import org.opendaylight.controller.connectionmanager.IConnectionManager;
21 import org.opendaylight.controller.sal.authorization.UserLevel;
22 import org.opendaylight.controller.sal.core.Description;
23 import org.opendaylight.controller.sal.core.Node;
24 import org.opendaylight.controller.sal.utils.GlobalConstants;
25 import org.opendaylight.controller.sal.utils.ServiceHelper;
26 import org.opendaylight.controller.sal.utils.Status;
27 import org.opendaylight.controller.sal.utils.StatusCode;
28 import org.opendaylight.controller.switchmanager.ISwitchManager;
29 import org.opendaylight.controller.usermanager.IUserManager;
30 import org.opendaylight.controller.usermanager.UserConfig;
31 import org.springframework.stereotype.Controller;
32 import org.springframework.web.bind.annotation.PathVariable;
33 import org.springframework.web.bind.annotation.RequestMapping;
34 import org.springframework.web.bind.annotation.RequestMethod;
35 import org.springframework.web.bind.annotation.RequestParam;
36 import org.springframework.web.bind.annotation.ResponseBody;
37
38 import com.google.gson.Gson;
39
40 @Controller
41 @RequestMapping("/admin")
42 public class DaylightWebAdmin {
43     Gson gson = new Gson();
44
45     /**
46      * Returns list of clustered controllers. Highlights "this" controller and
47      * if controller is coordinator
48      * @return List<ClusterBean>
49      */
50     @RequestMapping("/cluster")
51     @ResponseBody
52     public String getClusteredControllers() {
53         IClusterGlobalServices clusterServices = (IClusterGlobalServices) ServiceHelper.getGlobalInstance(
54                 IClusterGlobalServices.class, this);
55         if (clusterServices == null) {
56             return null;
57         }
58
59         List<ClusterNodeBean> clusterNodes = new ArrayList<ClusterNodeBean>();
60
61         List<InetAddress> controllers = clusterServices.getClusteredControllers();
62         for (InetAddress controller : controllers) {
63             ClusterNodeBean.Builder clusterBeanBuilder = new ClusterNodeBean.Builder(controller);
64             if (controller.equals(clusterServices.getMyAddress())) {
65                 clusterBeanBuilder.highlightMe();
66             }
67             if (clusterServices.getCoordinatorAddress().equals(controller)) {
68                 clusterBeanBuilder.iAmCoordinator();
69             }
70             clusterNodes.add(clusterBeanBuilder.build());
71         }
72
73         return gson.toJson(clusterNodes);
74     }
75
76     /**
77      * Return nodes connected to controller {controller}
78      * @param controller
79      *            - byte[] of the address of the controller
80      * @return List<NodeBean>
81      */
82     @RequestMapping("/cluster/controller/{controller}")
83     @ResponseBody
84     public String getNodesConnectedToController(@PathVariable("controller") String controller) {
85         IClusterGlobalServices clusterServices = (IClusterGlobalServices) ServiceHelper.getGlobalInstance(
86                 IClusterGlobalServices.class, this);
87         if (clusterServices == null) {
88             return null;
89         }
90         IConnectionManager connectionManager = (IConnectionManager) ServiceHelper.getGlobalInstance(
91                 IConnectionManager.class, this);
92         if (connectionManager == null) {
93             return null;
94         }
95         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class,
96                 GlobalConstants.DEFAULT.toString(), this);
97         if (switchManager == null) {
98             return null;
99         }
100
101         byte[] address = gson.fromJson(controller, byte[].class);
102         InetAddress controllerAddress = null;
103         try {
104             controllerAddress = InetAddress.getByAddress(address);
105         } catch (UnknownHostException e) {
106             return null;
107         }
108
109         List<NodeBean> result = new ArrayList<NodeBean>();
110
111         Set<Node> nodes = connectionManager.getNodes(controllerAddress);
112         if (nodes == null) {
113             return gson.toJson(result);
114         }
115         for (Node node : nodes) {
116             Description description = (Description) switchManager.getNodeProp(node, Description.propertyName);
117             NodeBean nodeBean;
118             if (description == null || description.getValue().equals("None")) {
119                 nodeBean = new NodeBean(node);
120             } else {
121                 nodeBean = new NodeBean(node, description.getValue());
122             }
123             result.add(nodeBean);
124         }
125
126         return gson.toJson(result);
127     }
128
129     @RequestMapping("/users")
130     @ResponseBody
131     public List<UserConfig> getUsers() {
132         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
133         if (userManager == null) {
134             return null;
135         }
136
137         List<UserConfig> userConfList = userManager.getLocalUserList();
138
139         return userConfList;
140     }
141
142     /*
143      * Password in clear text, moving to HTTP/SSL soon
144      */
145     @RequestMapping(value = "/users", method = RequestMethod.POST)
146     @ResponseBody
147     public String saveLocalUserConfig(@RequestParam(required = true) String json,
148             @RequestParam(required = true) String action, HttpServletRequest request) {
149
150         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
151         if (userManager == null) {
152             return "Internal Error";
153         }
154
155         if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
156             return "Operation not permitted";
157         }
158
159         Gson gson = new Gson();
160         UserConfig config = gson.fromJson(json, UserConfig.class);
161
162         Status result = (action.equals("add")) ? userManager.addLocalUser(config) : userManager.removeLocalUser(config);
163         if (result.isSuccess()) {
164             String userAction = (action.equals("add")) ? "added" : "removed";
165             DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser());
166             return "Success";
167         }
168         return result.getDescription();
169     }
170
171     @RequestMapping(value = "/users/{username}", method = RequestMethod.POST)
172     @ResponseBody
173     public String removeLocalUser(@PathVariable("username") String userName, HttpServletRequest request) {
174
175         String username = request.getUserPrincipal().getName();
176         if (username.equals(userName)) {
177             return "Invalid Request: User cannot delete itself";
178         }
179
180         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
181         if (userManager == null) {
182             return "Internal Error";
183         }
184
185         if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
186             return "Operation not permitted";
187         }
188
189         Status result = userManager.removeLocalUser(userName);
190         if (result.isSuccess()) {
191             DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", userName);
192             return "Success";
193         }
194         return result.getDescription();
195     }
196
197     @RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST)
198     @ResponseBody
199     public Status changePassword(@PathVariable("username") String username, HttpServletRequest request,
200             @RequestParam("currentPassword") String currentPassword, @RequestParam("newPassword") String newPassword) {
201         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
202         if (userManager == null) {
203             return new Status(StatusCode.GONE, "User Manager not found");
204         }
205
206         if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
207             return new Status(StatusCode.FORBIDDEN, "Operation not permitted");
208         }
209
210         if (newPassword.isEmpty()) {
211             return new Status(StatusCode.BADREQUEST, "Empty passwords not allowed");
212         }
213
214         Status status = userManager.changeLocalUserPassword(username, currentPassword, newPassword);
215         if (status.isSuccess()) {
216             DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for", username);
217         }
218         return status;
219     }
220
221     /**
222      * Is the operation permitted for the given level
223      * @param level
224      */
225     private boolean authorize(IUserManager userManager, UserLevel level, HttpServletRequest request) {
226         String username = request.getUserPrincipal().getName();
227         UserLevel userLevel = userManager.getUserLevel(username);
228         return userLevel.toNumber() <= level.toNumber();
229     }
230 }