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;
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.
59 public class TopologyNorthboundJAXRS {
61 private String username;
64 public void setSecurityContext(SecurityContext context) {
65 if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
68 protected String getUserName() {
74 * Retrieve the Topology
76 * @param containerName
77 * The container for which we want to retrieve the topology (Eg.
80 * @return A List of EdgeProps each EdgeProp represent an Edge of the graph
81 * with the corresponding properties attached to it.
88 * http://localhost:8080/controller/nb/v2/topology/default
91 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
93 * <edgeProperties>
95 * <tailNodeConnector>
97 * <id>00:00:00:00:00:00:00:02</id>
98 * <type>OF</type>
100 * <id>2</id>
101 * <type>OF</type>
102 * </tailNodeConnector>
103 * <headNodeConnector>
105 * <id>00:00:00:00:00:00:00:51</id>
106 * <type>OF</type>
108 * <id>2</id>
109 * <type>OF</type>
110 * </headNodeConnector>
114 * <value>1</value>
117 * <value>1</value>
120 * <value>C1_2-L2_2</value>
123 * <value>1377279422032</value>
124 * <name>creation</name>
126 * </properties>
127 * </edgeProperties>
128 * <edgeProperties>
130 * <tailNodeConnector>
132 * <id>00:00:00:00:00:00:00:51</id>
133 * <type>OF</type>
135 * <id>2</id>
136 * <type>OF</type>
137 * </tailNodeConnector>
138 * <headNodeConnector>
140 * <id>00:00:00:00:00:00:00:02</id>
141 * <type>OF</type>
143 * <id>2</id>
144 * <type>OF</type>
145 * </headNodeConnector>
149 * <value>1</value>
152 * <value>L2_2-C1_2</value>
155 * <value>1</value>
158 * <value>1377279423564</value>
159 * <name>creation</name>
161 * </properties>
162 * </edgeProperties>
166 * {"edgeProperties":[{"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
167 * "id":"2","type":"OF"},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
168 * "2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},
169 * {"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
170 * "2","type":"OF"}},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
171 * "id":"2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
175 @Path("/{containerName}")
177 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
178 @TypeHint(Topology.class)
179 @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name was not found") })
180 public Topology getTopology(@PathParam("containerName") String containerName) {
182 if (!NorthboundUtils.isAuthorized(
183 getUserName(), containerName, Privilege.READ, this)) {
184 throw new UnauthorizedException(
185 "User is not authorized to perform this operation on container "
188 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
189 .getInstance(ITopologyManager.class, containerName, this);
190 if (topologyManager == null) {
191 throw new ResourceNotFoundException(
192 RestMessages.NOCONTAINER.toString());
195 Map<Edge, Set<Property>> topo = topologyManager.getEdges();
197 List<EdgeProperties> res = new ArrayList<EdgeProperties>();
198 for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
199 EdgeProperties el = new EdgeProperties(entry.getKey(), entry.getValue());
202 return new Topology(res);
209 * Retrieve the user configured links
211 * @param containerName
212 * The container for which we want to retrieve the user links (Eg. 'default')
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(
246 @PathParam("containerName") String containerName) {
248 if (!NorthboundUtils.isAuthorized(
249 getUserName(), containerName, Privilege.READ, this)) {
250 throw new UnauthorizedException(
251 "User is not authorized to perform this operation on container "
254 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
255 .getInstance(ITopologyManager.class, containerName, this);
256 if (topologyManager == null) {
257 throw new ResourceNotFoundException(
258 RestMessages.NOCONTAINER.toString());
261 ConcurrentMap<String, TopologyUserLinkConfig> userLinks = topologyManager
263 if ((userLinks != null) && (userLinks.values() != null)) {
264 List<TopologyUserLinkConfig> res = new ArrayList<TopologyUserLinkConfig>(
266 return new TopologyUserLinks(res);
275 * @param containerName
276 * Name of the Container (Eg. 'default')
278 * Name of the user link
279 * @param TopologyUserLinkConfig
280 * in JSON or XML format
281 * @return Response as dictated by the HTTP Response Status code
288 * http://localhost:8080/controller/nb/v2/topology/default/userLink/link1
291 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
292 * <topologyUserLinks>
293 * <status>Success</status>
294 * <name>link1</name>
295 * <srcNodeConnector>OF|2@OF|00:00:00:00:00:00:00:02</srcNodeConnector>
296 * <dstNodeConnector>OF|2@OF|00:00:00:00:00:00:00:51</dstNodeConnector>
297 * </topologyUserLinks>
300 * {"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"}
304 @Path("/{containerName}/userLink/{name}")
306 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
307 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
309 @ResponseCode(code = 201, condition = "User Link added successfully"),
310 @ResponseCode(code = 404, condition = "The Container Name was not found"),
311 @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"),
312 @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"),
313 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
314 public Response addUserLink(
315 @PathParam(value = "containerName") String containerName,
316 @PathParam(value = "name") String name,
317 @TypeHint(TopologyUserLinkConfig.class) TopologyUserLinkConfig userLinkConfig) {
319 if (!NorthboundUtils.isAuthorized(
320 getUserName(), containerName, Privilege.WRITE, this)) {
321 throw new UnauthorizedException(
322 "User is not authorized to perform this operation on container "
325 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
326 .getInstance(ITopologyManager.class, containerName, this);
327 if (topologyManager == null) {
328 throw new ResourceNotFoundException(
329 RestMessages.NOCONTAINER.toString());
332 Status status = topologyManager.addUserLink(userLinkConfig);
333 if (status.isSuccess()) {
334 NorthboundUtils.auditlog("User Link", username, "added", userLinkConfig.getName(), containerName);
335 return Response.status(Response.Status.CREATED).build();
337 throw new InternalServerErrorException(status.getDescription());
341 * Delete an User Link
343 * @param containerName
344 * Name of the Container (Eg. 'default')
346 * Name of the Link Configuration (Eg. 'config1')
347 * @return Response as dictated by the HTTP Response Status code
354 * http://localhost:8080/controller/nb/v2/topology/default/userLink/config1
358 @Path("/{containerName}/userLink/{name}")
360 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
361 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
363 @ResponseCode(code = 204, condition = "User link removed successfully"),
364 @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"),
365 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
366 public Response deleteUserLink(
367 @PathParam("containerName") String containerName,
368 @PathParam("name") String name) {
370 if (!NorthboundUtils.isAuthorized(
371 getUserName(), containerName, Privilege.WRITE, this)) {
372 throw new UnauthorizedException(
373 "User is not authorized to perform this operation on container "
376 ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
377 .getInstance(ITopologyManager.class, containerName, this);
378 if (topologyManager == null) {
379 throw new ResourceNotFoundException(
380 RestMessages.NOCONTAINER.toString());
383 Status ret = topologyManager.deleteUserLink(name);
384 if (ret.isSuccess()) {
385 NorthboundUtils.auditlog("User Link", username, "removed", name, containerName);
386 return Response.noContent().build();
388 return NorthboundUtils.getResponse(ret);