/* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.controllermanager.northbound; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; import org.codehaus.enunciate.jaxrs.TypeHint; import org.opendaylight.controller.configuration.IConfigurationService; import org.opendaylight.controller.containermanager.IContainerManager; import org.opendaylight.controller.northbound.commons.RestMessages; import org.opendaylight.controller.northbound.commons.exception.BadRequestException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; import org.opendaylight.controller.sal.authorization.Privilege; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.switchmanager.ISwitchManager; /** * The class provides Northbound REST APIs to manager the controller. Currently * it supports getting controller property(ies), setting a property, and * removing a property * */ @Path("/") public class ControllerManagerNorthbound { private String username; @Context public void setSecurityContext(SecurityContext context) { if (context != null && context.getUserPrincipal() != null) { username = context.getUserPrincipal().getName(); } } protected String getUserName() { return username; } private ISwitchManager getISwitchManagerService(String containerName) { ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this); if (switchManager == null) { throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString()); } return switchManager; } /** * Retrieve a property or all properties for the controller in the network * * @param containerName * Name of the Container (Eg. 'default') * @param propertyName * Name of the Property specified by * {@link org.opendaylight.controller.sal.core.Property} and its * extended classes * * Example: * * Request URL: * http://localhost:8080/controller/nb/v2/controllermanager/default/properties/?propertyName=macAddress * * Response Body in XML: * * * * * 3e:04:ef:11:13:80 * * * * * Response Body in JSON: * { "controllerProperties": * {"properties": * { "macAddress": * { "value": "3e:04:ef:11:13:80" } * } * } * } * */ @Path("/{containerName}/properties/") @GET @TypeHint(Property.class) @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"), @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), @ResponseCode(code = 404, condition = "The containerName or property is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public ControllerProperties getControllerProperties(@PathParam("containerName") String containerName, @QueryParam("propertyName") String propertyName) { if (!isValidContainer(containerName)) { throw new ResourceNotFoundException("Container " + containerName + " does not exist."); } if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) { throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName); } ISwitchManager switchManager = getISwitchManagerService(containerName); if (propertyName == null) { Map propertyMap = switchManager.getControllerProperties(); Set properties = new HashSet(propertyMap.values()); return new ControllerProperties(properties); } Set properties = new HashSet(); Property property = switchManager.getControllerProperty(propertyName); if (property == null) { throw new ResourceNotFoundException("Unable to find property with name: " + propertyName); } properties.add(property); return new ControllerProperties(properties); } /** * Add a controller property to the controller. This method overrides * previously set property values if the property already exist. * * @param containerName * Name of the Container (Eg. 'default') * @param propertyName * Name of the Property specified by * {@link org.opendaylight.controller.sal.core.Property} and its * extended classes * @param propertyValue * Value of the Property specified by * {@link org.opendaylight.controller.sal.core.Property} and its * extended classes * @return Response as dictated by the HTTP Response Status code * * Example: * * Request URL: * http://localhost:8080/controller/nb/v2/controllermanager/default/properties/description/defaultController */ @Path("/{containerName}/properties/{propertyName}/{propertyValue}") @PUT @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @StatusCodes({ @ResponseCode(code = 201, condition = "Operation successful"), @ResponseCode(code = 400, condition = "Invalid property parameters"), @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), @ResponseCode(code = 404, condition = "The containerName or property is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public Response setControllerProperty(@Context UriInfo uriInfo, @PathParam("containerName") String containerName, @PathParam("propertyName") String propertyName, @PathParam("propertyValue") String propertyValue) { if (!isValidContainer(containerName)) { throw new ResourceNotFoundException("Container " + containerName + " does not exist."); } if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) { throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName); } ISwitchManager switchManager = getISwitchManagerService(containerName); Property prop = switchManager.createProperty(propertyName, propertyValue); if (prop == null) { throw new BadRequestException("Property with name " + propertyName + " cannot be created."); } Status status = switchManager.setControllerProperty(prop); if (status.isSuccess()) { NorthboundUtils.auditlog("Controller Property", username, "updated", propertyName); return Response.created(uriInfo.getRequestUri()).build(); } return NorthboundUtils.getResponse(status); } /** * Delete a property of the controller * * @param containerName * Name of the Container (Eg. 'default') * @param propertyName * Name of the Property specified by * {@link org.opendaylight.controller.sal.core.Property} and its * extended classes * @return Response as dictated by the HTTP Response Status code * * Example: * * Request URL: * http://localhost:8080/controller/nb/v2/controllermanager/default/properties/description */ @Path("/{containerName}/properties/{propertyName}") @DELETE @StatusCodes({ @ResponseCode(code = 204, condition = "Property removed successfully"), @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), @ResponseCode(code = 404, condition = "The containerName is not found"), @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") }) public Response removeControllerProperty(@PathParam("containerName") String containerName, @PathParam("propertyName") String propertyName) { if (!isValidContainer(containerName)) { throw new ResourceNotFoundException("Container " + containerName + " does not exist."); } if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) { throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName); } ISwitchManager switchManager = getISwitchManagerService(containerName); Status status = switchManager.removeControllerProperty(propertyName); if (status.isSuccess()) { NorthboundUtils.auditlog("Controller Property", username, "removed", propertyName); return Response.noContent().build(); } return NorthboundUtils.getResponse(status); } /** * Save controller configuration * * Request URL: * http://localhost:8080/controller/nb/v2/controllermanager/configuration * * Request body is empty */ @Path("/configuration") @PUT @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @StatusCodes({ @ResponseCode(code = 204, condition = "Operation successful"), @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), @ResponseCode(code = 503, condition = "Configuration service is unavailable.") }) public Response saveConfiguration() { if (!NorthboundUtils.isAuthorized(getUserName(), "default", Privilege.WRITE, this)) { throw new UnauthorizedException("User is not authorized to perform this operation"); } IConfigurationService configService = (IConfigurationService) ServiceHelper.getGlobalInstance(IConfigurationService.class, this); if (configService == null) { throw new ServiceUnavailableException("Configuration Service " + RestMessages.SERVICEUNAVAILABLE.toString()); } Status status = configService.saveConfigurations(); if (status.isSuccess()) { NorthboundUtils.auditlog("Controller Configuration", username, "save", "configuration"); return Response.noContent().build(); } return NorthboundUtils.getResponse(status); } private boolean isValidContainer(String containerName) { if (containerName.equals(GlobalConstants.DEFAULT.toString())) { return true; } IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance( IContainerManager.class, this); if (containerManager == null) { throw new ServiceUnavailableException("Container Manager " + RestMessages.SERVICEUNAVAILABLE.toString()); } if (containerManager.getContainerNames().contains(containerName)) { return true; } return false; } }