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
8 package org.opendaylight.controller.subnets.northbound;
10 import java.util.ArrayList;
11 import java.util.HashSet;
14 import javax.ws.rs.Consumes;
15 import javax.ws.rs.DELETE;
16 import javax.ws.rs.GET;
17 import javax.ws.rs.POST;
18 import javax.ws.rs.Path;
19 import javax.ws.rs.PathParam;
20 import javax.ws.rs.Produces;
21 import javax.ws.rs.QueryParam;
22 import javax.ws.rs.core.Context;
23 import javax.ws.rs.core.MediaType;
24 import javax.ws.rs.core.Response;
25 import javax.ws.rs.core.SecurityContext;
26 import javax.xml.bind.JAXBElement;
28 import org.codehaus.enunciate.jaxrs.ResponseCode;
29 import org.codehaus.enunciate.jaxrs.StatusCodes;
30 import org.codehaus.enunciate.jaxrs.TypeHint;
31 import org.opendaylight.controller.northbound.commons.RestMessages;
32 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
33 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
34 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
35 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
36 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
37 import org.opendaylight.controller.sal.authorization.Privilege;
38 import org.opendaylight.controller.sal.utils.ServiceHelper;
39 import org.opendaylight.controller.sal.utils.Status;
40 import org.opendaylight.controller.switchmanager.ISwitchManager;
41 import org.opendaylight.controller.switchmanager.SubnetConfig;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
46 public class SubnetsNorthboundJAXRS {
47 protected static final Logger logger = LoggerFactory
48 .getLogger(SubnetsNorthboundJAXRS.class);
50 private String username;
53 public void setSecurityContext(SecurityContext context) {
54 username = context.getUserPrincipal().getName();
57 protected String getUserName() {
62 * List all the subnets in a given container
64 * @param containerName
65 * container in which we want to query the subnets
67 * @return a List of SubnetConfig
69 @Path("/{containerName}")
71 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
72 @StatusCodes({ @ResponseCode(code = 404, condition = "The containerName passed was not found") })
73 @TypeHint(SubnetConfigs.class)
74 public SubnetConfigs listSubnets(
75 @PathParam("containerName") String containerName) {
76 if (!NorthboundUtils.isAuthorized(
77 getUserName(), containerName, Privilege.READ, this)) {
78 throw new UnauthorizedException(
79 "User is not authorized to perform this operation on container "
82 ISwitchManager switchManager = null;
83 switchManager = (ISwitchManager) ServiceHelper.getInstance(
84 ISwitchManager.class, containerName, this);
85 if (switchManager == null) {
86 throw new ResourceNotFoundException(
87 RestMessages.NOCONTAINER.toString());
89 return new SubnetConfigs(switchManager.getSubnetsConfigList());
93 * List the configuration of a subnet in a given container
95 * @param containerName
96 * container in which we want to query the subnet
98 * of the subnet being queried
100 * @return a SubnetConfig
102 @Path("/{containerName}/{subnetName}")
104 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
106 @ResponseCode(code = 404, condition = "The containerName passed was not found"),
107 @ResponseCode(code = 404, condition = "Subnet does not exist") })
108 @TypeHint(SubnetConfig.class)
109 public SubnetConfig listSubnet(
110 @PathParam("containerName") String containerName,
111 @PathParam("subnetName") String subnetName) {
113 if (!NorthboundUtils.isAuthorized(
114 getUserName(), containerName, Privilege.READ, this)) {
115 throw new UnauthorizedException(
116 "User is not authorized to perform this operation on container "
119 ISwitchManager switchManager = null;
120 switchManager = (ISwitchManager) ServiceHelper.getInstance(
121 ISwitchManager.class, containerName, this);
122 if (switchManager == null) {
123 throw new ResourceNotFoundException(
124 RestMessages.NOCONTAINER.toString());
126 SubnetConfig res = switchManager.getSubnetConfig(subnetName);
128 throw new ResourceNotFoundException(
129 RestMessages.NOSUBNET.toString());
136 * Add a subnet to a container
138 * @param containerName
139 * container in which we want to add/update the subnet
141 * that has to be added
143 * pair default gateway IP/mask that identify the subnet being
147 @Path("/{containerName}/{subnetName}")
150 @ResponseCode(code = 404, condition = "Invalid Data passed"),
151 @ResponseCode(code = 201, condition = "Subnet added"),
152 @ResponseCode(code = 500, condition = "Addition of subnet failed") })
153 public Response addSubnet(@PathParam("containerName") String containerName,
154 @PathParam("subnetName") String subnetName,
155 @QueryParam("subnet") String subnet) {
157 if (!NorthboundUtils.isAuthorized(
158 getUserName(), containerName, Privilege.WRITE, this)) {
159 throw new UnauthorizedException(
160 "User is not authorized to perform this operation on container "
163 if (subnetName == null) {
164 throw new ResourceNotFoundException(
165 RestMessages.INVALIDDATA.toString());
167 if (subnet == null) {
168 throw new ResourceNotFoundException(
169 RestMessages.INVALIDDATA.toString());
171 ISwitchManager switchManager = null;
172 switchManager = (ISwitchManager) ServiceHelper.getInstance(
173 ISwitchManager.class, containerName, this);
174 if (switchManager == null) {
175 throw new ResourceNotFoundException(
176 RestMessages.NOCONTAINER.toString());
179 SubnetConfig cfgObject = new SubnetConfig(subnetName, subnet,
180 new ArrayList<String>(0));
181 Status status = switchManager.addSubnet(cfgObject);
182 if (status.isSuccess()) {
183 return Response.status(Response.Status.CREATED).build();
185 throw new InternalServerErrorException(status.getDescription());
189 * Delete a subnet from a container
191 * @param containerName
192 * container in which we want to delete the subnet by name
194 * of the subnet to be remove.
197 @Path("/{containerName}/{subnetName}")
200 @ResponseCode(code = 404, condition = "The containerName passed was not found"),
201 @ResponseCode(code = 500, condition = "Removal of subnet failed") })
202 public Response removeSubnet(
203 @PathParam("containerName") String containerName,
204 @PathParam("subnetName") String subnetName) {
205 if (subnetName == null) {
206 throw new ResourceNotFoundException(
207 RestMessages.INVALIDDATA.toString());
210 if (!NorthboundUtils.isAuthorized(
211 getUserName(), containerName, Privilege.WRITE, this)) {
212 throw new UnauthorizedException(
213 "User is not authorized to perform this operation on container "
217 ISwitchManager switchManager = null;
218 switchManager = (ISwitchManager) ServiceHelper.getInstance(
219 ISwitchManager.class, containerName, this);
220 if (switchManager == null) {
221 throw new ResourceNotFoundException(
222 RestMessages.NOCONTAINER.toString());
224 Status status = switchManager.removeSubnet(subnetName);
225 if (status.isSuccess()) {
226 return Response.status(Response.Status.OK).build();
228 throw new InternalServerErrorException(status.getDescription());
232 * Modify a subnet. For now only changing the port list is allowed.
234 * @param containerName
235 * Name of the Container
237 * Name of the SubnetConfig to be modified
238 * @param subnetConfigData
239 * the {@link SubnetConfig} structure in JSON passed as a POST
241 * @return If the operation is successful or not
243 @Path("/{containerName}/{subnetName}/modify")
245 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
247 @ResponseCode(code = 202, condition = "Operation successful"),
248 @ResponseCode(code = 400, condition = "Invalid request, i.e., requested changing the subnet name"),
249 @ResponseCode(code = 404, condition = "The containerName or subnetName is not found"),
250 @ResponseCode(code = 500, condition = "Internal server error")})
251 public Response modifySubnet(@PathParam("containerName") String containerName,
252 @PathParam("subnetName") String name,
253 @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
255 if (!NorthboundUtils.isAuthorized(getUserName(), containerName,
256 Privilege.WRITE, this)) {
257 throw new UnauthorizedException(
258 "User is not authorized to perform this operation on container " + containerName);
261 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class,
262 containerName, this);
263 if (switchManager == null) {
264 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
267 SubnetConfig subnetConf = subnetConfigData.getValue();
268 SubnetConfig existingConf = switchManager.getSubnetConfig(name);
270 boolean successful = true;
272 // make sure that the name matches an existing subnet and we're not
273 // changing the name or subnet IP/mask
274 if (existingConf == null){
275 // don't have a subnet by that name
276 return Response.status(Response.Status.NOT_FOUND).build();
278 }else if( !existingConf.getName().equals(subnetConf.getName())
279 || !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
280 // can't change the name of a subnet
281 return Response.status(Response.Status.BAD_REQUEST).build();
284 // create a set for fast lookups
285 Set<String> newPorts = new HashSet<String>(subnetConf.getNodePorts());
287 // go through the current ports and (1) remove ports that aren't
288 // there anymore and (2) remove ports that are still there from the
289 // set of ports to add
290 for(String s : existingConf.getNodePorts()){
291 if(newPorts.contains(s)){
294 Status st = switchManager.removePortsFromSubnet(name, s);
295 successful = successful && st.isSuccess();
299 // add any remaining ports
300 for(String s : newPorts){
301 Status st = switchManager.addPortsToSubnet(name, s);
302 successful = successful && st.isSuccess();
307 return Response.status(Response.Status.ACCEPTED).build();
309 return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
315 * Add or remove switch ports to a subnet POST subnets/green/sw
319 * @param containerName
323 * @param subnet: the subnet name name
325 * @param switchports: datapath ID/port list =>
326 * xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
330 * @RequestMapping(value = "/{containerName}/{name}", method =
331 * RequestMethod.POST)
333 * public View addSwitchports(Map<String, Object> model,
335 * @PathVariable(value = "containerName") String containerName,
337 * @PathVariable(value = "name") String name,
339 * @RequestParam(value = "nodeports") String nodePorts,
341 * @RequestParam(value = "action") String action) {
343 * checkDefaultDisabled(containerName); ISwitchManager switchManager = null;
344 * try { BundleContext bCtx = FrameworkUtil.getBundle(this.getClass())
345 * .getBundleContext();
347 * ServiceReference[] services = bCtx.getServiceReferences(
348 * ISwitchManager.class.getName(), "(containerName=" + containerName + ")");
350 * if (services != null) { switchManager = (ISwitchManager)
351 * bCtx.getService(services[0]); logger.debug("Switch manager reference is:"
352 * + switchManager); } } catch (Exception e) {
353 * logger.error("Switch Manager reference is NULL"); }
355 * checkContainerExists(switchManager);
357 * String ret; if (action.equals("add")) { ret =
358 * switchManager.addPortsToSubnet(name, nodePorts); } else if
359 * (action.equals("remove")) { ret =
360 * switchManager.removePortsFromSubnet(name, nodePorts); } else { throw new
361 * UnsupportedMediaTypeException(RestMessages.UNKNOWNACTION .toString() +
364 * return returnViewOrThrowConflicEx(model, ret); }