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
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>
168 * {"edgeProperties":[{"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
169 * "id":"2","type":"OF"},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
170 * "2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},
171 * {"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
172 * "2","type":"OF"}},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
173 * "id":"2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
177 @Path("/{containerName}")
179 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
180 @TypeHint(Topology.class)
181 @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
182 public Topology getTopology(@PathParam("containerName") String containerName) {
184 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
185 throw new UnauthorizedException("User is not authorized to perform this operation on container "
188 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
189 containerName, this);
190 if (topologyManager == null) {
191 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
194 Map<Edge, Set<Property>> topo = topologyManager.getEdges();
196 List<EdgeProperties> res = new ArrayList<EdgeProperties>();
197 for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
198 EdgeProperties el = new EdgeProperties(entry.getKey(), entry.getValue());
201 return new Topology(res);
208 * Retrieve the user configured links
210 * @param containerName
211 * The container for which we want to retrieve the user links
214 * @return A List of user configured links
221 * http://localhost:8080/controller/nb/v2/topology/default/userLinks
224 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
225 * <topologyUserLinks>
227 * <status>Success</status>
228 * <name>link1</name>
229 * <srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector>
230 * <dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector>
232 * </topologyUserLinks>
235 * {"userLinks":{"status":"Success","name":"link1","srcNodeConnector":
236 * "OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}}
240 @Path("/{containerName}/userLinks")
242 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
243 @TypeHint(TopologyUserLinks.class)
244 @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
245 public TopologyUserLinks getUserLinks(@PathParam("containerName") String containerName) {
247 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
248 throw new UnauthorizedException("User is not authorized to perform this operation on container "
251 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
252 containerName, this);
253 if (topologyManager == null) {
254 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
257 ConcurrentMap<String, TopologyUserLinkConfig> userLinks = topologyManager.getUserLinks();
258 if ((userLinks != null) && (userLinks.values() != null)) {
259 List<TopologyUserLinkConfig> res = new ArrayList<TopologyUserLinkConfig>(userLinks.values());
260 return new TopologyUserLinks(res);
269 * @param containerName
270 * Name of the Container (Eg. 'default')
272 * Name of the user link
273 * @param TopologyUserLinkConfig
274 * in JSON or XML format
275 * @return Response as dictated by the HTTP Response Status code
282 * http://localhost:8080/controller/nb/v2/topology/default/userLink/link1
285 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
286 * <topologyUserLinks>
287 * <status>Success</status>
288 * <name>link1</name>
289 * <srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector>
290 * <dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector>
291 * </topologyUserLinks>
294 * {"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"}
298 @Path("/{containerName}/userLink/{name}")
300 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
301 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
303 @ResponseCode(code = 201, condition = "User Link added successfully"),
304 @ResponseCode(code = 404, condition = "The Container Name was not found"),
305 @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"),
306 @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"),
307 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
308 public Response addUserLink(@PathParam(value = "containerName") String containerName,
309 @PathParam(value = "name") String name,
310 @TypeHint(TopologyUserLinkConfig.class) TopologyUserLinkConfig userLinkConfig) {
312 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
313 throw new UnauthorizedException("User is not authorized to perform this operation on container "
316 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
317 containerName, this);
318 if (topologyManager == null) {
319 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
322 Status status = topologyManager.addUserLink(userLinkConfig);
323 if (status.isSuccess()) {
326 "User Link",username,"added", userLinkConfig.getName() + " from " + NorthboundUtils.getPortName(
327 NodeConnector.fromString(userLinkConfig.getSrcNodeConnector()),
328 containerName, this) + " to "
329 + NorthboundUtils.getPortName(NodeConnector.fromString
330 (userLinkConfig.getDstNodeConnector()),containerName, this), containerName);
331 return Response.status(Response.Status.CREATED).build();
333 throw new InternalServerErrorException(status.getDescription());
337 * Delete an User Link
339 * @param containerName
340 * Name of the Container (Eg. 'default')
342 * Name of the Link Configuration (Eg. 'config1')
343 * @return Response as dictated by the HTTP Response Status code
350 * http://localhost:8080/controller/nb/v2/topology/default/userLink/config1
354 @Path("/{containerName}/userLink/{name}")
356 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
357 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
358 @StatusCodes({ @ResponseCode(code = 204, condition = "User link removed successfully"),
359 @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"),
360 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
361 public Response deleteUserLink(@PathParam("containerName") String containerName, @PathParam("name") String name) {
363 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
364 throw new UnauthorizedException("User is not authorized to perform this operation on container "
367 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper.getInstance(ITopologyManager.class,
368 containerName, this);
369 if (topologyManager == null) {
370 throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
373 Status ret = topologyManager.deleteUserLink(name);
374 if (ret.isSuccess()) {
375 NorthboundUtils.auditlog("User Link", username, "removed", name, containerName);
376 return Response.noContent().build();
378 return NorthboundUtils.getResponse(ret);