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.PUT;
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;
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.northbound.commons.RestMessages;
33 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
34 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
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.core.Edge;
39 import org.opendaylight.controller.sal.core.NodeConnector;
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.
59 public class TopologyNorthboundJAXRS {
61 private String username;
64 public void setSecurityContext(SecurityContext context) {
65 if (context != null && context.getUserPrincipal() != null) {
66 username = context.getUserPrincipal().getName();
70 protected String getUserName() {
76 * Retrieve the Topology
78 * @param containerName
79 * The container for which we want to retrieve the topology (Eg.
82 * @return A List of EdgeProps each EdgeProp represent an Edge of the graph
83 * with the corresponding properties attached to it.
90 * http://localhost:8080/controller/nb/v2/topology/default
92 * Response body in XML:
93 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
95 * <edgeProperties>
97 * <tailNodeConnector>
99 * <id>00:00:00:00:00:00:00:02</id>
100 * <type>OF</type>
102 * <id>2</id>
103 * <type>OF</type>
104 * </tailNodeConnector>
105 * <headNodeConnector>
107 * <id>00:00:00:00:00:00:00:51</id>
108 * <type>OF</type>
110 * <id>2</id>
111 * <type>OF</type>
112 * </headNodeConnector>
116 * <value>1</value>
119 * <value>1</value>
122 * <value>C1_2-L2_2</value>
125 * <value>1377279422032</value>
126 * <name>creation</name>
128 * </properties>
129 * </edgeProperties>
130 * <edgeProperties>
132 * <tailNodeConnector>
134 * <id>00:00:00:00:00:00:00:51</id>
135 * <type>OF</type>
137 * <id>2</id>
138 * <type>OF</type>
139 * </tailNodeConnector>
140 * <headNodeConnector>
142 * <id>00:00:00:00:00:00:00:02</id>
143 * <type>OF</type>
145 * <id>2</id>
146 * <type>OF</type>
147 * </headNodeConnector>
151 * <value>1</value>
154 * <value>L2_2-C1_2</value>
157 * <value>1</value>
160 * <value>1377279423564</value>
161 * <name>creation</name>
163 * </properties>
164 * </edgeProperties>
167 * Response body in JSON:
172 * "tailNodeConnector":{
174 * "id":"00:00:00:00:00:00:00:02",
180 * "headNodeConnector":{
182 * "id":"00:00:00:00:00:00:00:51",
191 * "value": 1379527162648,
192 * "name": "creation",
204 * "value": 10000000000
210 * "tailNodeConnector":{
212 * "id":"00:00:00:00:00:00:00:51",
218 * "headNodeConnector":{
220 * "id":"00:00:00:00:00:00:00:02",
229 * "value": 1379527162648,
230 * "name": "creation",
238 @Path("/{containerName}")
240 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
241 @TypeHint(Topology.class)
242 @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
243 public Topology getTopology(@PathParam("containerName") String containerName) {
245 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
246 throw new UnauthorizedException("User is not authorized to perform this operation on container "
249 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
250 containerName, this);
251 if (topologyManager == null) {
252 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
255 Map<Edge, Set<Property>> topo = topologyManager.getEdges();
257 List<EdgeProperties> res = new ArrayList<EdgeProperties>();
258 for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
259 EdgeProperties el = new EdgeProperties(entry.getKey(), entry.getValue());
262 return new Topology(res);
269 * Retrieve the user configured links
271 * @param containerName
272 * The container for which we want to retrieve the user links
275 * @return A List of user configured links
282 * http://localhost:8080/controller/nb/v2/topology/default/userLinks
284 * Response body in XML:
285 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
288 * <status>Success</status>
289 * <name>link1</name>
290 * <srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector>
291 * <dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector>
295 * Response body in JSON:
299 * "status": "Success",
301 * "srcNodeConnector": "OF|2@OF|00:00:00:00:00:00:00:02",
302 * "dstNodeConnector": "OF|5@OF|00:00:00:00:00:00:00:05"
309 @Path("/{containerName}/userLinks")
311 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
312 @TypeHint(TopologyUserLinks.class)
313 @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
314 public TopologyUserLinks getUserLinks(@PathParam("containerName") String containerName) {
316 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
317 throw new UnauthorizedException("User is not authorized to perform this operation on container "
320 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
321 containerName, this);
322 if (topologyManager == null) {
323 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
326 ConcurrentMap<String, TopologyUserLinkConfig> userLinks = topologyManager.getUserLinks();
327 if ((userLinks != null) && (userLinks.values() != null)) {
328 List<TopologyUserLinkConfig> res = new ArrayList<TopologyUserLinkConfig>(userLinks.values());
329 return new TopologyUserLinks(res);
338 * @param containerName
339 * Name of the Container (Eg. 'default')
341 * Name of the user link
342 * @param TopologyUserLinkConfig
343 * in JSON or XML format
344 * @return Response as dictated by the HTTP Response Status code
351 * http://localhost:8080/controller/nb/v2/topology/default/userLink/link1
353 * Request body in XML:
354 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
355 * <topologyUserLinkConfig>
356 * <status>Success</status>
357 * <name>link1</name>
358 * <srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector>
359 * <dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector>
360 * </topologyUserLinkConfig>
362 * Request body in JSON:
364 * "status":"Success",
366 * "srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02",
367 * "dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"
372 @Path("/{containerName}/userLink/{name}")
374 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
375 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
377 @ResponseCode(code = 201, condition = "User Link added successfully"),
378 @ResponseCode(code = 404, condition = "The Container Name was not found"),
379 @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"),
380 @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"),
381 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
382 public Response addUserLink(@PathParam(value = "containerName") String containerName,
383 @PathParam(value = "name") String name,
384 @TypeHint(TopologyUserLinkConfig.class) TopologyUserLinkConfig userLinkConfig) {
386 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
387 throw new UnauthorizedException("User is not authorized to perform this operation on container "
390 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
391 containerName, this);
392 if (topologyManager == null) {
393 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
396 Status status = topologyManager.addUserLink(userLinkConfig);
397 if (status.isSuccess()) {
400 "User Link",username,"added", userLinkConfig.getName() + " from " + NorthboundUtils.getPortName(
401 NodeConnector.fromString(userLinkConfig.getSrcNodeConnector()),
402 containerName, this) + " to "
403 + NorthboundUtils.getPortName(NodeConnector.fromString
404 (userLinkConfig.getDstNodeConnector()),containerName, this), containerName);
405 return Response.status(Response.Status.CREATED).build();
407 throw new InternalServerErrorException(status.getDescription());
411 * Delete an User Link
413 * @param containerName
414 * Name of the Container (Eg. 'default')
416 * Name of the Link Configuration (Eg. 'config1')
417 * @return Response as dictated by the HTTP Response Status code
424 * http://localhost:8080/controller/nb/v2/topology/default/userLink/config1
428 @Path("/{containerName}/userLink/{name}")
430 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
431 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
432 @StatusCodes({ @ResponseCode(code = 204, condition = "User link removed successfully"),
433 @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"),
434 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
435 public Response deleteUserLink(@PathParam("containerName") String containerName, @PathParam("name") String name) {
437 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
438 throw new UnauthorizedException("User is not authorized to perform this operation on container "
441 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
442 containerName, this);
443 if (topologyManager == null) {
444 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
447 Status ret = topologyManager.deleteUserLink(name);
448 if (ret.isSuccess()) {
449 NorthboundUtils.auditlog("User Link", username, "removed", name, containerName);
450 return Response.noContent().build();
452 return NorthboundUtils.getResponse(ret);