X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fnorthbound%2Ftopology%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Ftopology%2Fnorthbound%2FTopologyNorthboundJAXRS.java;h=ff26bfd21f30a6b67f683607924b366ef32a1011;hb=refs%2Fchanges%2F49%2F1149%2F2;hp=00b27b02c79a3137952b7a7e822a227a711385ff;hpb=29f7cfb54b580928c7feac63abce028a7014b0d5;p=controller.git diff --git a/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java b/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java index 00b27b02c7..ff26bfd21f 100644 --- a/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java +++ b/opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -13,64 +12,184 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentMap; +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.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; +import javax.xml.bind.JAXBElement; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; import org.codehaus.enunciate.jaxrs.TypeHint; import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException; import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +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.Edge; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.topologymanager.ITopologyManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig; /** * Topology Northbound REST API - * - *

+ * + *
+ *
* Authentication scheme : HTTP Basic
* Authentication realm : opendaylight
* Transport : HTTP and HTTPS
*
- * HTTPS Authentication is disabled by default. Administrator can enable it in tomcat-server.xml after adding - * a proper keystore / SSL certificate from a trusted authority.
- * More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * HTTPS Authentication is disabled by default. */ @Path("/") public class TopologyNorthboundJAXRS { - private static Logger logger = LoggerFactory - .getLogger(TopologyNorthboundJAXRS.class); + + private String username; + + @Context + public void setSecurityContext(SecurityContext context) { + if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName(); + } + + protected String getUserName() { + return username; + } /** * - * Retrieve the Topology for the + * Retrieve the Topology + * + * @param containerName + * The container for which we want to retrieve the topology (Eg. + * 'default') * - * @param containerName The container for which we want to retrieve the topology + * @return A List of EdgeProps each EdgeProp represent an Edge of the graph + * with the corresponding properties attached to it. * - * @return A List of EdgeProps each EdgeProp represent an Edge of - * the grap with the corresponding properties attached to it. + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/topology/default
+     *
+     * Response in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <topology>
+     *     <edgeProperties>
+     *         <edge>
+     *             <tailNodeConnector>
+     *                 <node>
+     *                     <id>00:00:00:00:00:00:00:02</id>
+     *                     <type>OF</type>
+     *                 </node>
+     *                 <id>2</id>
+     *                 <type>OF</type>
+     *             </tailNodeConnector>
+     *             <headNodeConnector>
+     *                 <node>
+     *                     <id>00:00:00:00:00:00:00:51</id>
+     *                     <type>OF</type>
+     *                 </node>
+     *                 <id>2</id>
+     *                 <type>OF</type>
+     *             </headNodeConnector>
+     *         </edge>
+     *         <properties>
+     *             <state>
+     *                 <value>1</value>
+     *             </state>
+     *             <config>
+     *                 <value>1</value>
+     *             </config>
+     *             <name>
+     *                 <value>C1_2-L2_2</value>
+     *             </name>
+     *             <timeStamp>
+     *                 <value>1377279422032</value>
+     *                 <name>creation</name>
+     *             </timeStamp>
+     *         </properties>
+     *     </edgeProperties>
+     *     <edgeProperties>
+     *         <edge>
+     *             <tailNodeConnector>
+     *                 <node>
+     *                     <id>00:00:00:00:00:00:00:51</id>
+     *                     <type>OF</type>
+     *                 </node>
+     *                 <id>2</id>
+     *                 <type>OF</type>
+     *             </tailNodeConnector>
+     *             <headNodeConnector>
+     *                 <node>
+     *                     <id>00:00:00:00:00:00:00:02</id>
+     *                     <type>OF</type>
+     *                 </node>
+     *                 <id>2</id>
+     *                 <type>OF</type>
+     *             </headNodeConnector>
+     *         </edge>
+     *         <properties>
+     *             <state>
+     *                 <value>1</value>
+     *             </state>
+     *             <name>
+     *                 <value>L2_2-C1_2</value>
+     *             </name>
+     *             <config>
+     *                 <value>1</value>
+     *             </config>
+     *             <timeStamp>
+     *                 <value>1377279423564</value>
+     *                 <name>creation</name>
+     *             </timeStamp>
+     *         </properties>
+     *     </edgeProperties>
+     * </topology>
+     *
+     * Response in JSON:
+     * {"edgeProperties":[{"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
+     * "id":"2","type":"OF"},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
+     * "2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},
+     * {"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
+     * "2","type":"OF"}},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
+     * "id":"2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
+     *
+     * 
*/ @Path("/{containerName}") @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @TypeHint(Topology.class) - @StatusCodes( { @ResponseCode(code = 404, condition = "The containerName passed was not found") }) - public Topology getTopology( - @PathParam("containerName") String containerName) { + @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") }) + public Topology getTopology(@PathParam("containerName") String containerName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } ITopologyManager topologyManager = (ITopologyManager) ServiceHelper .getInstance(ITopologyManager.class, containerName, this); if (topologyManager == null) { - throw new ResourceNotFoundException(RestMessages.NOCONTAINER - .toString()); + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); } Map> topo = topologyManager.getEdges(); @@ -85,4 +204,187 @@ public class TopologyNorthboundJAXRS { return null; } + + /** + * Retrieve the user configured links + * + * @param containerName + * The container for which we want to retrieve the user links (Eg. 'default') + * + * @return A List of user configured links + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/topology/default/userLinks
+     *
+     * Response in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <topologyUserLinks>
+     * <userLinks>
+     * <status>Success</status>
+     * <name>link1</name>
+     * <srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector>
+     * <dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector>
+     * </userLinks>
+     * </topologyUserLinks>
+     *
+     * Response in JSON:
+     * {"userLinks":{"status":"Success","name":"link1","srcNodeConnector":
+     * "OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}}
+     *
+     * 
+ */ + @Path("/{containerName}/userLinks") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @TypeHint(TopologyUserLinks.class) + @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") }) + public TopologyUserLinks getUserLinks( + @PathParam("containerName") String containerName) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.READ, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ITopologyManager topologyManager = (ITopologyManager) ServiceHelper + .getInstance(ITopologyManager.class, containerName, this); + if (topologyManager == null) { + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); + } + + ConcurrentMap userLinks = topologyManager + .getUserLinks(); + if ((userLinks != null) && (userLinks.values() != null)) { + List res = new ArrayList( + userLinks.values()); + return new TopologyUserLinks(res); + } + + return null; + } + + /** + * Add an User Link + * + * @param containerName + * Name of the Container (Eg. 'default') + * @param name + * Name of the user link + * @param TopologyUserLinkConfig + * in JSON or XML format + * @return Response as dictated by the HTTP Response Status code + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/topology/default/userLink/link1
+     *
+     * Request in XML:
+     * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+     * <topologyUserLinks>
+     * <status>Success</status>
+     * <name>link1</name>
+     * <srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector>
+     * <dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector>
+     * </topologyUserLinks>
+     *
+     * Request in JSON:
+     * {"status":"Success","name":"link1","srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}
+     *
+     * 
+ */ + @Path("/{containerName}/userLink/{name}") + @PUT + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 201, condition = "User Link added successfully"), + @ResponseCode(code = 404, condition = "The Container Name was not found"), + @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"), + @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"), + @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) + public Response addUserLink( + @PathParam(value = "containerName") String containerName, + @PathParam(value = "name") String name, + @TypeHint(TopologyUserLinkConfig.class) TopologyUserLinkConfig userLinkConfig) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ITopologyManager topologyManager = (ITopologyManager) ServiceHelper + .getInstance(ITopologyManager.class, containerName, this); + if (topologyManager == null) { + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); + } + + Status status = topologyManager.addUserLink(userLinkConfig); + if (status.isSuccess()) { + NorthboundUtils.auditlog("User Link", username, "added", userLinkConfig.getName(), containerName); + return Response.status(Response.Status.CREATED).build(); + } + throw new InternalServerErrorException(status.getDescription()); + } + + /** + * Delete an User Link + * + * @param containerName + * Name of the Container (Eg. 'default') + * @param name + * Name of the Link Configuration (Eg. 'config1') + * @return Response as dictated by the HTTP Response Status code + * + *
+     *
+     * Example:
+     *
+     * RequestURL:
+     * http://localhost:8080/controller/nb/v2/topology/default/userLink/config1
+     *
+     * 
+ */ + @Path("/{containerName}/userLink/{name}") + @DELETE + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @StatusCodes({ + @ResponseCode(code = 204, condition = "User link removed successfully"), + @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"), + @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") }) + public Response deleteUserLink( + @PathParam("containerName") String containerName, + @PathParam("name") String name) { + + if (!NorthboundUtils.isAuthorized( + getUserName(), containerName, Privilege.WRITE, this)) { + throw new UnauthorizedException( + "User is not authorized to perform this operation on container " + + containerName); + } + ITopologyManager topologyManager = (ITopologyManager) ServiceHelper + .getInstance(ITopologyManager.class, containerName, this); + if (topologyManager == null) { + throw new ResourceNotFoundException( + RestMessages.NOCONTAINER.toString()); + } + + Status ret = topologyManager.deleteUserLink(name); + if (ret.isSuccess()) { + NorthboundUtils.auditlog("User Link", username, "removed", name, containerName); + return Response.noContent().build(); + } + return NorthboundUtils.getResponse(ret); + } }