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.topology.northbound;
11 import java.util.ArrayList;
12 import java.util.List;
15 import java.util.concurrent.ConcurrentMap;
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.GET;
20 import javax.ws.rs.POST;
21 import javax.ws.rs.Path;
22 import javax.ws.rs.PathParam;
23 import javax.ws.rs.Produces;
24 import javax.ws.rs.core.Context;
25 import javax.ws.rs.core.MediaType;
26 import javax.ws.rs.core.Response;
27 import javax.ws.rs.core.SecurityContext;
28 import javax.xml.bind.JAXBElement;
30 import org.codehaus.enunciate.jaxrs.ResponseCode;
31 import org.codehaus.enunciate.jaxrs.StatusCodes;
32 import org.codehaus.enunciate.jaxrs.TypeHint;
33 import org.opendaylight.controller.northbound.commons.RestMessages;
34 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
35 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
36 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
37 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
38 import org.opendaylight.controller.sal.authorization.Privilege;
39 import org.opendaylight.controller.sal.core.Edge;
40 import org.opendaylight.controller.sal.core.Property;
41 import org.opendaylight.controller.sal.utils.ServiceHelper;
42 import org.opendaylight.controller.sal.utils.Status;
43 import org.opendaylight.controller.topologymanager.ITopologyManager;
44 import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
47 * Topology Northbound REST API
51 * Authentication scheme : <b>HTTP Basic</b><br>
52 * Authentication realm : <b>opendaylight</b><br>
53 * Transport : <b>HTTP and HTTPS</b><br>
55 * HTTPS Authentication is disabled by default. Administrator can enable it in
56 * tomcat-server.xml after adding a proper keystore / SSL certificate from a
57 * trusted authority.<br>
59 * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
63 public class TopologyNorthboundJAXRS {
65 private String username;
68 public void setSecurityContext(SecurityContext context) {
69 username = context.getUserPrincipal().getName();
72 protected String getUserName() {
78 * Retrieve the Topology
80 * @param containerName
81 * The container for which we want to retrieve the topology (Eg. 'default')
83 * @return A List of EdgeProps each EdgeProp represent an Edge of the grap
84 * with the corresponding properties attached to it.
91 * http://localhost:8080/controller/nb/v2/topology/default
94 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?><topology><edgeProperties><edge><tailNodeConnector id="2" type="OF"><node id="00:00:00:00:00:00:00:02" type="OF"/></tailNodeConnector><headNodeConnector id="2" type="OF"><node id="00:00:00:00:00:00:00:51" type="OF"/></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 id="2" type="OF"><node id="00:00:00:00:00:00:00:51" type="OF"/></tailNodeConnector><headNodeConnector id="2" type="OF"><node id="00:00:00:00:00:00:00:02" type="OF"/></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>
97 * {"edgeProperties":[{"edge":{"tailNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:02","@type":"OF"}},"headNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:51","@type":"OF"}}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},{"edge":{"tailNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:51","@type":"OF"}},"headNodeConnector":{"@id":"2","@type":"OF","node":{"@id":"00:00:00:00:00:00:00:02","@type":"OF"}}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
101 @Path("/{containerName}")
103 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
104 @TypeHint(Topology.class)
105 @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
106 public Topology getTopology(@PathParam("containerName") String containerName) {
108 if (!NorthboundUtils.isAuthorized(
109 getUserName(), containerName, Privilege.READ, this)) {
110 throw new UnauthorizedException(
111 "User is not authorized to perform this operation on container "
114 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
115 .getInstance(ITopologyManager.class, containerName, this);
116 if (topologyManager == null) {
117 throw new ResourceNotFoundException(
118 RestMessages.NOCONTAINER.toString());
121 Map<Edge, Set<Property>> topo = topologyManager.getEdges();
123 List<EdgeProperties> res = new ArrayList<EdgeProperties>();
124 for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
125 EdgeProperties el = new EdgeProperties(entry.getKey(),
129 return new Topology(res);
136 * Retrieve the user configured links
138 * @param containerName
139 * The container for which we want to retrieve the user links (Eg. 'default')
141 * @return A List of user configured links
148 * http://localhost:8080/controller/nb/v2/topology/default/user-link
151 * <?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>
154 * {"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"}}
158 @Path("/{containerName}/user-link")
160 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
161 @TypeHint(TopologyUserLinks.class)
162 @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
163 public TopologyUserLinks getUserLinks(
164 @PathParam("containerName") String containerName) {
166 if (!NorthboundUtils.isAuthorized(
167 getUserName(), containerName, Privilege.READ, this)) {
168 throw new UnauthorizedException(
169 "User is not authorized to perform this operation on container "
172 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
173 .getInstance(ITopologyManager.class, containerName, this);
174 if (topologyManager == null) {
175 throw new ResourceNotFoundException(
176 RestMessages.NOCONTAINER.toString());
179 ConcurrentMap<String, TopologyUserLinkConfig> userLinks = topologyManager
181 if ((userLinks != null) && (userLinks.values() != null)) {
182 List<TopologyUserLinkConfig> res = new ArrayList<TopologyUserLinkConfig>(
184 return new TopologyUserLinks(res);
193 * @param containerName
194 * Name of the Container (Eg. 'default')
195 * @param TopologyUserLinkConfig
196 * in JSON or XML format
197 * @return Response as dictated by the HTTP Response Status code
204 * http://localhost:8080/controller/nb/v2/topology/default/user-link/config1-content
207 * <?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>
210 * {"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"}
214 @Path("/{containerName}/user-link")
216 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
217 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
219 @ResponseCode(code = 201, condition = "User Link added successfully"),
220 @ResponseCode(code = 404, condition = "The Container Name was not found"),
221 @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"),
222 @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"),
223 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
224 public Response addUserLink(
225 @PathParam(value = "containerName") String containerName,
226 @TypeHint(TopologyUserLinkConfig.class) JAXBElement<TopologyUserLinkConfig> userLinkConfig) {
228 if (!NorthboundUtils.isAuthorized(
229 getUserName(), containerName, Privilege.WRITE, this)) {
230 throw new UnauthorizedException(
231 "User is not authorized to perform this operation on container "
234 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
235 .getInstance(ITopologyManager.class, containerName, this);
236 if (topologyManager == null) {
237 throw new ResourceNotFoundException(
238 RestMessages.NOCONTAINER.toString());
241 Status status = topologyManager.addUserLink(userLinkConfig.getValue());
242 if (status.isSuccess()) {
243 NorthboundUtils.auditlog("User Link", username, "added", userLinkConfig.getValue().getName(), containerName);
244 return Response.status(Response.Status.CREATED).build();
246 throw new InternalServerErrorException(status.getDescription());
250 * Delete an User Link
252 * @param containerName
253 * Name of the Container (Eg. 'default')
255 * Name of the Link Configuration (Eg. 'config1')
256 * @return Response as dictated by the HTTP Response Status code
263 * http://localhost:8080/controller/nb/v2/topology/default/user-link/config1
267 @Path("/{containerName}/user-link/{name}")
269 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
270 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
272 @ResponseCode(code = 200, condition = "Operation successful"),
273 @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"),
274 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
275 public Response deleteUserLink(
276 @PathParam("containerName") String containerName,
277 @PathParam("name") String name) {
279 if (!NorthboundUtils.isAuthorized(
280 getUserName(), containerName, Privilege.WRITE, this)) {
281 throw new UnauthorizedException(
282 "User is not authorized to perform this operation on container "
285 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
286 .getInstance(ITopologyManager.class, containerName, this);
287 if (topologyManager == null) {
288 throw new ResourceNotFoundException(
289 RestMessages.NOCONTAINER.toString());
292 Status ret = topologyManager.deleteUserLink(name);
293 if (ret.isSuccess()) {
294 NorthboundUtils.auditlog("User Link", username, "removed", name, containerName);
295 return Response.ok().build();
297 throw new ResourceNotFoundException(ret.getDescription());