c5153962125445ead7ce27411f4bc87ea0b989f8
[controller.git] / opendaylight / northbound / controllermanager / src / main / java / org / opendaylight / controller / controllermanager / northbound / ControllerManagerNorthbound.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.controllermanager.northbound;
10
11 import java.util.HashSet;
12 import java.util.Map;
13 import java.util.Set;
14
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;
28
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.containermanager.IContainerManager;
33 import org.opendaylight.controller.northbound.commons.RestMessages;
34 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
35 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
36 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
37 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
38 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
39 import org.opendaylight.controller.sal.authorization.Privilege;
40 import org.opendaylight.controller.sal.core.Property;
41 import org.opendaylight.controller.sal.utils.GlobalConstants;
42 import org.opendaylight.controller.sal.utils.ServiceHelper;
43 import org.opendaylight.controller.sal.utils.Status;
44 import org.opendaylight.controller.switchmanager.ISwitchManager;
45
46 /**
47  * The class provides Northbound REST APIs to manager the controller. Currently
48  * it supports getting controller property(ies), setting a property, and
49  * removing a property
50  *
51  */
52
53 @Path("/")
54 public class ControllerManagerNorthbound {
55
56     private String username;
57
58     @Context
59     public void setSecurityContext(SecurityContext context) {
60         if (context != null && context.getUserPrincipal() != null) {
61             username = context.getUserPrincipal().getName();
62         }
63     }
64
65     protected String getUserName() {
66         return username;
67     }
68
69     private ISwitchManager getISwitchManagerService(String containerName) {
70         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
71                 this);
72
73         if (switchManager == null) {
74             throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
75         }
76
77         return switchManager;
78     }
79
80     /**
81      * Retrieve a property or all properties for the controller in the network
82      *
83      * @param containerName
84      *            Name of the Container (Eg. 'default')
85      * @param propertyName
86      *            Name of the Property specified by
87      *            {@link org.opendaylight.controller.sal.core.Property} and its
88      *            extended classes
89      *
90      *            Example:
91      *
92      *            Request URL:
93      *            http://localhost:8080/controller/nb/v2/controllermanager/default/properties/?propertyName=macAddress
94      *
95      *            Response Body in XML:
96      *            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
97      *            <controllerProperties>
98      *                  <properties>
99      *                           <macAddress>
100      *                                   <value>3e:04:ef:11:13:80</value>
101      *                          </macAddress>
102      *                   </properties>
103      *            </controllerProperties>
104      *
105      *            Response Body in JSON:
106      *            { "controllerProperties":
107      *                  {"properties":
108      *                          { "macAddress":
109      *                                  { "value": "3e:04:ef:11:13:80" }
110      *                           }
111      *                   }
112      *            }
113      *
114      */
115     @Path("/{containerName}/properties/")
116     @GET
117     @TypeHint(Property.class)
118     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
119     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
120             @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
121             @ResponseCode(code = 404, condition = "The containerName or property is not found"),
122             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
123     public ControllerProperties getControllerProperties(@PathParam("containerName") String containerName,
124             @QueryParam("propertyName") String propertyName) {
125
126         if (!isValidContainer(containerName)) {
127             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
128         }
129
130         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
131             throw new UnauthorizedException("User is not authorized to perform this operation on container "
132                     + containerName);
133         }
134
135         ISwitchManager switchManager = getISwitchManagerService(containerName);
136
137         if (propertyName == null) {
138             Map<String, Property> propertyMap = switchManager.getControllerProperties();
139             Set<Property> properties = new HashSet<Property>(propertyMap.values());
140             return new ControllerProperties(properties);
141         }
142
143         Set<Property> properties = new HashSet<Property>();
144         Property property = switchManager.getControllerProperty(propertyName);
145         if (property == null) {
146             throw new ResourceNotFoundException("Unable to find property with name: " + propertyName);
147         }
148         properties.add(property);
149
150         return new ControllerProperties(properties);
151
152     }
153
154     /**
155      * Add a controller property to the controller. This method overrides
156      * previously set property values if the property already exist.
157      *
158      * @param containerName
159      *            Name of the Container (Eg. 'default')
160      * @param propertyName
161      *            Name of the Property specified by
162      *            {@link org.opendaylight.controller.sal.core.Property} and its
163      *            extended classes
164      * @param propertyValue
165      *            Value of the Property specified by
166      *            {@link org.opendaylight.controller.sal.core.Property} and its
167      *            extended classes
168      * @return Response as dictated by the HTTP Response Status code
169      *
170      *         Example:
171      *
172      *         Request URL:
173      *         http://localhost:8080/controller/nb/v2/controllermanager/default/properties/description/defaultController
174      */
175     @Path("/{containerName}/properties/{propertyName}/{propertyValue}")
176     @PUT
177     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
178     @StatusCodes({ @ResponseCode(code = 201, condition = "Operation successful"),
179             @ResponseCode(code = 400, condition = "Invalid property parameters"),
180             @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
181             @ResponseCode(code = 404, condition = "The containerName or property is not found"),
182             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
183     public Response setControllerProperty(@Context UriInfo uriInfo, @PathParam("containerName") String containerName,
184             @PathParam("propertyName") String propertyName, @PathParam("propertyValue") String propertyValue) {
185
186         if (!isValidContainer(containerName)) {
187             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
188         }
189
190         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
191             throw new UnauthorizedException("User is not authorized to perform this operation on container "
192                     + containerName);
193         }
194
195         ISwitchManager switchManager = getISwitchManagerService(containerName);
196
197         Property prop = switchManager.createProperty(propertyName, propertyValue);
198         if (prop == null) {
199             throw new BadRequestException("Property with name " + propertyName + " cannot be created.");
200         }
201
202         Status status = switchManager.setControllerProperty(prop);
203
204         if (status.isSuccess()) {
205             NorthboundUtils.auditlog("Controller Property", username, "updated", propertyName);
206             return Response.created(uriInfo.getRequestUri()).build();
207         }
208         return NorthboundUtils.getResponse(status);
209     }
210
211     /**
212      * Delete a property of the controller
213      *
214      * @param containerName
215      *            Name of the Container (Eg. 'default')
216      * @param propertyName
217      *            Name of the Property specified by
218      *            {@link org.opendaylight.controller.sal.core.Property} and its
219      *            extended classes
220      * @return Response as dictated by the HTTP Response Status code
221      *
222      *         Example:
223      *
224      *         Request URL:
225      *         http://localhost:8080/controller/nb/v2/controllermanager/default/properties/description
226      */
227     @Path("/{containerName}/properties/{propertyName}")
228     @DELETE
229     @StatusCodes({ @ResponseCode(code = 204, condition = "Property removed successfully"),
230             @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
231             @ResponseCode(code = 404, condition = "The containerName is not found"),
232             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
233     public Response removeControllerProperty(@PathParam("containerName") String containerName,
234             @PathParam("propertyName") String propertyName) {
235
236         if (!isValidContainer(containerName)) {
237             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
238         }
239
240         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
241             throw new UnauthorizedException("User is not authorized to perform this operation on container "
242                     + containerName);
243         }
244
245         ISwitchManager switchManager = getISwitchManagerService(containerName);
246
247         Status status = switchManager.removeControllerProperty(propertyName);
248
249         if (status.isSuccess()) {
250             NorthboundUtils.auditlog("Controller Property", username, "removed", propertyName);
251
252             return Response.noContent().build();
253         }
254         return NorthboundUtils.getResponse(status);
255     }
256
257     private boolean isValidContainer(String containerName) {
258         if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
259             return true;
260         }
261         IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(
262                 IContainerManager.class, this);
263         if (containerManager == null) {
264             throw new ServiceUnavailableException("Container Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
265         }
266         if (containerManager.getContainerNames().contains(containerName)) {
267             return true;
268         }
269         return false;
270     }
271
272 }