2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.controllermanager.northbound;
11 import java.util.HashSet;
15 import javax.ws.rs.Consumes;
16 import javax.ws.rs.DELETE;
17 import javax.ws.rs.GET;
18 import javax.ws.rs.PUT;
19 import javax.ws.rs.Path;
20 import javax.ws.rs.PathParam;
21 import javax.ws.rs.Produces;
22 import javax.ws.rs.QueryParam;
23 import javax.ws.rs.core.Context;
24 import javax.ws.rs.core.MediaType;
25 import javax.ws.rs.core.Response;
26 import javax.ws.rs.core.SecurityContext;
27 import javax.ws.rs.core.UriInfo;
29 import org.codehaus.enunciate.jaxrs.ResponseCode;
30 import org.codehaus.enunciate.jaxrs.StatusCodes;
31 import org.codehaus.enunciate.jaxrs.TypeHint;
32 import org.opendaylight.controller.configuration.IConfigurationService;
33 import org.opendaylight.controller.containermanager.IContainerManager;
34 import org.opendaylight.controller.northbound.commons.RestMessages;
35 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
36 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
37 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
38 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
39 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
40 import org.opendaylight.controller.sal.authorization.Privilege;
41 import org.opendaylight.controller.sal.core.Property;
42 import org.opendaylight.controller.sal.utils.GlobalConstants;
43 import org.opendaylight.controller.sal.utils.ServiceHelper;
44 import org.opendaylight.controller.sal.utils.Status;
45 import org.opendaylight.controller.switchmanager.ISwitchManager;
48 * The class provides Northbound REST APIs to manager the controller. Currently
49 * it supports getting controller property(ies), setting a property, and
55 public class ControllerManagerNorthbound {
57 private String username;
60 public void setSecurityContext(SecurityContext context) {
61 if (context != null && context.getUserPrincipal() != null) {
62 username = context.getUserPrincipal().getName();
66 protected String getUserName() {
70 private ISwitchManager getISwitchManagerService(String containerName) {
71 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
74 if (switchManager == null) {
75 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
82 * Retrieve a property or all properties for the controller in the network
84 * @param containerName
85 * Name of the Container (Eg. 'default')
87 * Name of the Property specified by
88 * {@link org.opendaylight.controller.sal.core.Property} and its
94 * http://localhost:8080/controller/nb/v2/controllermanager/default/properties/?propertyName=macAddress
96 * Response Body in XML:
97 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
98 * <controllerProperties>
101 * <value>3e:04:ef:11:13:80</value>
104 * </controllerProperties>
106 * Response Body in JSON:
107 * { "controllerProperties":
110 * { "value": "3e:04:ef:11:13:80" }
116 @Path("/{containerName}/properties/")
118 @TypeHint(Property.class)
119 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
120 @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
121 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
122 @ResponseCode(code = 404, condition = "The containerName or property is not found"),
123 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
124 public ControllerProperties getControllerProperties(@PathParam("containerName") String containerName,
125 @QueryParam("propertyName") String propertyName) {
127 if (!isValidContainer(containerName)) {
128 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
131 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
132 throw new UnauthorizedException("User is not authorized to perform this operation on container "
136 ISwitchManager switchManager = getISwitchManagerService(containerName);
138 if (propertyName == null) {
139 Map<String, Property> propertyMap = switchManager.getControllerProperties();
140 Set<Property> properties = new HashSet<Property>(propertyMap.values());
141 return new ControllerProperties(properties);
144 Set<Property> properties = new HashSet<Property>();
145 Property property = switchManager.getControllerProperty(propertyName);
146 if (property == null) {
147 throw new ResourceNotFoundException("Unable to find property with name: " + propertyName);
149 properties.add(property);
151 return new ControllerProperties(properties);
156 * Add a controller property to the controller. This method overrides
157 * previously set property values if the property already exist.
159 * @param containerName
160 * Name of the Container (Eg. 'default')
161 * @param propertyName
162 * Name of the Property specified by
163 * {@link org.opendaylight.controller.sal.core.Property} and its
165 * @param propertyValue
166 * Value of the Property specified by
167 * {@link org.opendaylight.controller.sal.core.Property} and its
169 * @return Response as dictated by the HTTP Response Status code
174 * http://localhost:8080/controller/nb/v2/controllermanager/default/properties/description/defaultController
176 @Path("/{containerName}/properties/{propertyName}/{propertyValue}")
178 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
179 @StatusCodes({ @ResponseCode(code = 201, condition = "Operation successful"),
180 @ResponseCode(code = 400, condition = "Invalid property parameters"),
181 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
182 @ResponseCode(code = 404, condition = "The containerName or property is not found"),
183 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
184 public Response setControllerProperty(@Context UriInfo uriInfo, @PathParam("containerName") String containerName,
185 @PathParam("propertyName") String propertyName, @PathParam("propertyValue") String propertyValue) {
187 if (!isValidContainer(containerName)) {
188 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
191 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
192 throw new UnauthorizedException("User is not authorized to perform this operation on container "
196 ISwitchManager switchManager = getISwitchManagerService(containerName);
198 Property prop = switchManager.createProperty(propertyName, propertyValue);
200 throw new BadRequestException("Property with name " + propertyName + " cannot be created.");
203 Status status = switchManager.setControllerProperty(prop);
205 if (status.isSuccess()) {
206 NorthboundUtils.auditlog("Controller Property", username, "updated", propertyName);
207 return Response.created(uriInfo.getRequestUri()).build();
209 return NorthboundUtils.getResponse(status);
213 * Delete a property of the controller
215 * @param containerName
216 * Name of the Container (Eg. 'default')
217 * @param propertyName
218 * Name of the Property specified by
219 * {@link org.opendaylight.controller.sal.core.Property} and its
221 * @return Response as dictated by the HTTP Response Status code
226 * http://localhost:8080/controller/nb/v2/controllermanager/default/properties/description
228 @Path("/{containerName}/properties/{propertyName}")
230 @StatusCodes({ @ResponseCode(code = 204, condition = "Property removed successfully"),
231 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
232 @ResponseCode(code = 404, condition = "The containerName is not found"),
233 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
234 public Response removeControllerProperty(@PathParam("containerName") String containerName,
235 @PathParam("propertyName") String propertyName) {
237 if (!isValidContainer(containerName)) {
238 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
241 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
242 throw new UnauthorizedException("User is not authorized to perform this operation on container "
246 ISwitchManager switchManager = getISwitchManagerService(containerName);
248 Status status = switchManager.removeControllerProperty(propertyName);
250 if (status.isSuccess()) {
251 NorthboundUtils.auditlog("Controller Property", username, "removed", propertyName);
253 return Response.noContent().build();
255 return NorthboundUtils.getResponse(status);
259 * Save controller configuration
262 * http://localhost:8080/controller/nb/v2/controllermanager/configuration
264 * Request body is empty
266 @Path("/configuration")
268 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
270 @ResponseCode(code = 204, condition = "Operation successful"),
271 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
272 @ResponseCode(code = 503, condition = "Configuration service is unavailable.")
274 public Response saveConfiguration() {
276 if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) {
277 throw new UnauthorizedException("User is not authorized to perform this operation");
280 IConfigurationService configService = (IConfigurationService)
281 ServiceHelper.getGlobalInstance(IConfigurationService.class, this);
283 if (configService == null) {
284 throw new ServiceUnavailableException("Configuration Service " +
285 RestMessages.SERVICEUNAVAILABLE.toString());
287 Status status = configService.saveConfigurations();
288 if (status.isSuccess()) {
289 NorthboundUtils.auditlog("Controller Configuration", username,
290 "save", "configuration");
291 return Response.noContent().build();
293 return NorthboundUtils.getResponse(status);
296 private boolean isValidContainer(String containerName) {
297 if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
300 IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(
301 IContainerManager.class, this);
302 if (containerManager == null) {
303 throw new ServiceUnavailableException("Container Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
305 if (containerManager.getContainerNames().contains(containerName)) {