3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.controller.switchmanager.northbound;
12 import java.util.ArrayList;
13 import java.util.HashSet;
14 import java.util.List;
18 import javax.ws.rs.Consumes;
19 import javax.ws.rs.DELETE;
20 import javax.ws.rs.GET;
21 import javax.ws.rs.POST;
22 import javax.ws.rs.PUT;
23 import javax.ws.rs.Path;
24 import javax.ws.rs.PathParam;
25 import javax.ws.rs.Produces;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28 import org.codehaus.enunciate.jaxrs.ResponseCode;
29 import org.codehaus.enunciate.jaxrs.StatusCodes;
30 import org.codehaus.enunciate.jaxrs.TypeHint;
31 import org.opendaylight.controller.containermanager.IContainerManager;
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.ResourceConflictException;
35 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
36 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
37 import org.opendaylight.controller.sal.core.MacAddress;
38 import org.opendaylight.controller.sal.core.Node;
39 import org.opendaylight.controller.sal.core.NodeConnector;
40 import org.opendaylight.controller.sal.core.Property;
41 import org.opendaylight.controller.sal.utils.GlobalConstants;
42 import org.opendaylight.controller.sal.utils.ServiceHelper;
43 import org.opendaylight.controller.sal.utils.Status;
44 import org.opendaylight.controller.switchmanager.ISwitchManager;
47 * The class provides Northbound REST APIs to access the nodes, node connectors
48 * and their properties.
53 public class SwitchNorthbound {
55 private ISwitchManager getIfSwitchManagerService(String containerName) {
56 IContainerManager containerManager = (IContainerManager) ServiceHelper
57 .getGlobalInstance(IContainerManager.class, this);
58 if (containerManager == null) {
59 throw new ServiceUnavailableException("Container "
60 + RestMessages.SERVICEUNAVAILABLE.toString());
63 boolean found = false;
64 List<String> containerNames = containerManager.getContainerNames();
65 for (String cName : containerNames) {
66 if (cName.trim().equalsIgnoreCase(containerName.trim())) {
72 throw new ResourceNotFoundException(containerName + " "
73 + RestMessages.NOCONTAINER.toString());
76 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(
77 ISwitchManager.class, containerName, this);
79 if (switchManager == null) {
80 throw new ServiceUnavailableException("Switch Manager "
81 + RestMessages.SERVICEUNAVAILABLE.toString());
89 * Retrieve a list of all the nodes and their properties in the network
91 * @param containerName The container for which we want to retrieve the list
92 * @return A list of Pair each pair represents a
93 * {@link org.opendaylight.controller.sal.core.Node} and Set of
94 * {@link org.opendaylight.controller.sal.core.Property} attached to
97 @Path("/{containerName}/nodes")
99 @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
100 @TypeHint(Nodes.class)
102 @ResponseCode(code = 200, condition = "Operation successful"),
103 @ResponseCode(code = 404, condition = "The containerName is not found"),
104 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
105 public Nodes getNodes(
106 @PathParam("containerName") String containerName) {
107 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
108 if (switchManager == null) {
109 throw new ServiceUnavailableException("Switch Manager "
110 + RestMessages.SERVICEUNAVAILABLE.toString());
113 List<NodeProperties> res = new ArrayList<NodeProperties>();
114 Set<Node> nodes = switchManager.getNodes();
119 byte[] controllerMac = switchManager.getControllerMAC();
120 for (Node node : nodes) {
121 Map<String, Property> propMap = switchManager.getNodeProps(node);
122 if (propMap == null) {
125 Set<Property> props = new HashSet<Property>(propMap.values());
127 byte[] nodeMac = switchManager.getNodeMAC(node);
128 Property macAddr = new MacAddress(controllerMac, nodeMac);
131 NodeProperties nodeProps = new NodeProperties(node, props);
135 return new Nodes(res);
139 * Add a Name/Tier property to a node
141 * @param containerName Name of the Container
142 * @param nodeType Type of the node being programmed
143 * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node}
144 * @param propName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes
145 * @param propValue Value of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes
146 * @return Response as dictated by the HTTP Response Status code
149 @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propName}/{propValue}")
151 @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
152 @TypeHint(Response.class)
154 @ResponseCode(code = 200, condition = "Operation successful"),
155 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
156 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
157 public Response addNodeProperty(@PathParam("containerName") String containerName,
158 @PathParam("nodeType") String nodeType,
159 @PathParam("nodeId") String nodeId,
160 @PathParam("propName") String propName,
161 @PathParam("propValue") String propValue) {
163 handleDefaultDisabled(containerName);
165 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
166 if (switchManager == null) {
167 throw new ServiceUnavailableException("Switch Manager "
168 + RestMessages.SERVICEUNAVAILABLE.toString());
171 handleNodeAvailability(containerName, nodeType, nodeId);
172 Node node = Node.fromString(nodeId);
174 Property prop = switchManager.createProperty(propName, propValue);
176 throw new ResourceNotFoundException(
177 RestMessages.INVALIDDATA.toString());
180 switchManager.setNodeProp(node, prop);
181 return Response.status(Response.Status.CREATED).build();
185 * Delete a property of a node
187 * @param containerName Name of the Container
188 * @param nodeType Type of the node being programmed
189 * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node}
190 * @param propertyName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes
191 * @return Response as dictated by the HTTP Response Status code
194 @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}")
196 @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
198 @ResponseCode(code = 200, condition = "Operation successful"),
199 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
200 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
201 public Response deleteNodeProperty(@PathParam("containerName") String containerName,
202 @PathParam("nodeType") String nodeType,
203 @PathParam("nodeId") String nodeId,
204 @PathParam("propertyName") String propertyName) {
206 handleDefaultDisabled(containerName);
208 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
209 if (switchManager == null) {
210 throw new ServiceUnavailableException("Switch Manager "
211 + RestMessages.SERVICEUNAVAILABLE.toString());
214 handleNodeAvailability(containerName, nodeType, nodeId);
215 Node node = Node.fromString(nodeId);
217 Status ret = switchManager.removeNodeProp(node, propertyName);
218 if (ret.isSuccess()) {
219 return Response.ok().build();
221 throw new ResourceNotFoundException(ret.getDescription());
226 * Retrieve a list of all the node connectors and their properties in a given node
228 * @param containerName The container for which we want to retrieve the list
229 * @param nodeType Type of the node being programmed
230 * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node}
231 * @return A List of Pair each pair represents a
232 * {@link org.opendaylight.controller.sal.core.NodeConnector} and
234 * {@link org.opendaylight.controller.sal.core.Property} attached to
237 @Path("/{containerName}/node/{nodeType}/{nodeId}")
239 @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
240 @TypeHint(NodeConnectors.class)
242 @ResponseCode(code = 200, condition = "Operation successful"),
243 @ResponseCode(code = 404, condition = "The containerName is not found"),
244 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
245 public NodeConnectors getNodeConnectors(
246 @PathParam("containerName") String containerName,
247 @PathParam("nodeType") String nodeType,
248 @PathParam("nodeId") String nodeId) {
249 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
250 if (switchManager == null) {
251 throw new ServiceUnavailableException("Switch Manager "
252 + RestMessages.SERVICEUNAVAILABLE.toString());
255 handleNodeAvailability(containerName, nodeType,nodeId);
256 Node node = Node.fromString(nodeId);
258 List<NodeConnectorProperties> res = new ArrayList<NodeConnectorProperties>();
259 Set<NodeConnector> ncs = switchManager.getNodeConnectors(node);
264 for (NodeConnector nc : ncs) {
265 Map<String, Property> propMap = switchManager.getNodeConnectorProps(nc);
266 if (propMap == null) {
269 Set<Property> props = new HashSet<Property>(propMap.values());
270 NodeConnectorProperties ncProps = new NodeConnectorProperties(nc, props);
274 return new NodeConnectors(res);
278 * Add a Name/Bandwidth property to a node connector
280 * @param containerName Name of the Container
281 * @param nodeType Type of the node being programmed
282 * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node}
283 * @param nodeConnectorType Type of the node connector being programmed
284 * @param nodeConnectorId NodeConnector Identifier as specified by {@link org.opendaylight.controller.sal.core.NodeConnector}
285 * @param propName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes
286 * @param propValue Value of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes
287 * @return Response as dictated by the HTTP Response Status code
290 @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propName}/{propValue}")
292 @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
294 @ResponseCode(code = 200, condition = "Operation successful"),
295 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
296 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
297 public Response addNodeConnectorProperty(@PathParam("containerName") String containerName,
298 @PathParam("nodeType") String nodeType,
299 @PathParam("nodeId") String nodeId,
300 @PathParam("nodeConnectorType") String nodeConnectorType,
301 @PathParam("nodeConnectorId") String nodeConnectorId,
302 @PathParam("propName") String propName,
303 @PathParam("propValue") String propValue) {
305 handleDefaultDisabled(containerName);
307 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
308 if (switchManager == null) {
309 throw new ServiceUnavailableException("Switch Manager "
310 + RestMessages.SERVICEUNAVAILABLE.toString());
313 handleNodeAvailability(containerName, nodeType, nodeId);
314 Node node = Node.fromString(nodeId);
316 handleNodeConnectorAvailability(containerName, node, nodeConnectorType, nodeConnectorId);
317 NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorId, node);
319 Property prop = switchManager.createProperty(propName, propValue);
321 throw new ResourceNotFoundException(
322 RestMessages.INVALIDDATA.toString());
325 Status ret = switchManager.addNodeConnectorProp(nc, prop);
326 if (ret.isSuccess()) {
327 return Response.status(Response.Status.CREATED).build();
329 throw new InternalServerErrorException(ret.getDescription());
333 * Delete a property of a node connector
335 * @param containerName Name of the Container
336 * @param nodeType Type of the node being programmed
337 * @param nodeId Node Identifier as specified by {@link org.opendaylight.controller.sal.core.Node}
338 * @param nodeConnectorType Type of the node connector being programmed
339 * @param nodeConnectorId NodeConnector Identifier as specified by {@link org.opendaylight.controller.sal.core.NodeConnector}
340 * @param propertyName Name of the Property specified by {@link org.opendaylight.controller.sal.core.Property} and its extended classes
341 * @return Response as dictated by the HTTP Response Status code
344 @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propertyName}")
346 @Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
348 @ResponseCode(code = 200, condition = "Operation successful"),
349 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
350 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
351 public Response deleteNodeConnectorProperty(@PathParam("containerName") String containerName,
352 @PathParam("nodeType") String nodeType,
353 @PathParam("nodeId") String nodeId,
354 @PathParam("nodeConnectorType") String nodeConnectorType,
355 @PathParam("nodeConnectorId") String nodeConnectorId,
356 @PathParam("propertyName") String propertyName) {
358 handleDefaultDisabled(containerName);
360 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
361 if (switchManager == null) {
362 throw new ServiceUnavailableException("Switch Manager "
363 + RestMessages.SERVICEUNAVAILABLE.toString());
366 handleNodeAvailability(containerName, nodeType, nodeId);
367 Node node = Node.fromString(nodeId);
369 handleNodeConnectorAvailability(containerName, node, nodeConnectorType, nodeConnectorId);
370 NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorId, node);
372 Status ret = switchManager.removeNodeConnectorProp(nc, propertyName);
373 if (ret.isSuccess()) {
374 return Response.ok().build();
376 throw new ResourceNotFoundException(ret.getDescription());
380 * Retrieve a list of Span ports that were configured previously.
382 * @param containerName Name of the Container
383 * @return list of {@link org.opendaylight.controller.switchmanager.SpanConfig} resources
385 @Path("/span-config/{containerName}")
387 @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
389 @ResponseCode(code = 200, condition = "Operation successful"),
390 @ResponseCode(code = 404, condition = "The containerName is not found"),
391 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
392 public List<SpanConfig> getSpanConfigList(@PathParam("containerName") String containerName) {
393 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
394 if (switchManager == null) {
395 throw new ServiceUnavailableException("Switch Manager "
396 + RestMessages.SERVICEUNAVAILABLE.toString());
399 return switchManager.getSpanConfigList();
403 * Add a span configuration
405 * @param containerName Name of the Container
406 * @param config {@link org.opendaylight.controller.switchmanager.SpanConfig} in JSON or XML format
407 * @return Response as dictated by the HTTP Response Status code
409 @Path("/span-config/{containerName}")
411 @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
413 @ResponseCode(code = 200, condition = "Operation successful"),
414 @ResponseCode(code = 404, condition = "The containerName is not found"),
415 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
416 public Response addSpanConfig(@PathParam("containerName") String containerName,
417 @TypeHint(SubnetConfig.class) JAXBElement<SpanConfig> config) {
418 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
419 if (switchManager == null) {
420 throw new ServiceUnavailableException("Switch Manager "
421 + RestMessages.SERVICEUNAVAILABLE.toString());
424 String ret = switchManager.addSpanConfig(config.getValue());
425 if (ret.equals(ReturnString.SUCCESS.toString())) {
426 return Response.status(Response.Status.CREATED).build();
428 throw new InternalServerErrorException(ret);
432 * Delete a span configuration
434 * @param containerName Name of the Container
435 * @param config {@link org.opendaylight.controller.switchmanager.SpanConfig} in JSON or XML format
436 * @return Response as dictated by the HTTP Response Status code
438 @Path("/span-config/{containerName}")
440 @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
442 @ResponseCode(code = 200, condition = "Operation successful"),
443 @ResponseCode(code = 404, condition = "The containerName is not found"),
444 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
445 public Response deleteSpanConfig(@PathParam("containerName") String containerName,
446 @TypeHint(SubnetConfig.class) JAXBElement<SpanConfig> config) {
447 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
448 if (switchManager == null) {
449 throw new ServiceUnavailableException("Switch Manager "
450 + RestMessages.SERVICEUNAVAILABLE.toString());
453 String ret = switchManager.removeSpanConfig(config.getValue());
454 if (ret.equals(ReturnString.SUCCESS.toString())) {
455 return Response.ok().build();
457 throw new ResourceNotFoundException(ret);
462 * Save the current switch configurations
464 * @param containerName Name of the Container
465 * @return Response as dictated by the HTTP Response Status code
467 @Path("/{containerName}/switch-config")
469 @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
471 @ResponseCode(code = 200, condition = "Operation successful"),
472 @ResponseCode(code = 404, condition = "The containerName is not found"),
473 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
474 public Response saveSwitchConfig(@PathParam("containerName") String containerName) {
475 ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
476 if (switchManager == null) {
477 throw new ServiceUnavailableException("Switch Manager "
478 + RestMessages.SERVICEUNAVAILABLE.toString());
481 Status ret = switchManager.saveSwitchConfig();
482 if (ret.isSuccess()) {
483 return Response.ok().build();
485 throw new InternalServerErrorException(ret.getDescription());
488 private void handleDefaultDisabled(String containerName) {
489 IContainerManager containerManager = (IContainerManager) ServiceHelper
490 .getGlobalInstance(IContainerManager.class, this);
491 if (containerManager == null) {
492 throw new InternalServerErrorException(RestMessages.INTERNALERROR
495 if (containerName.equals(GlobalConstants.DEFAULT.toString())
496 && containerManager.hasNonDefaultContainer()) {
497 throw new ResourceConflictException(RestMessages.DEFAULTDISABLED
502 private Node handleNodeAvailability(String containerName, String nodeType,
505 Node node = Node.fromString(nodeType, nodeId);
507 throw new ResourceNotFoundException(nodeId + " : "
508 + RestMessages.NONODE.toString());
511 ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
512 ISwitchManager.class, containerName, this);
515 throw new ServiceUnavailableException("Switch Manager "
516 + RestMessages.SERVICEUNAVAILABLE.toString());
519 if (!sm.getNodes().contains(node)) {
520 throw new ResourceNotFoundException(node.toString() + " : "
521 + RestMessages.NONODE.toString());
526 private void handleNodeConnectorAvailability(String containerName,
527 Node node, String nodeConnectorType, String nodeConnectorId) {
529 NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType,
530 nodeConnectorId, node);
532 throw new ResourceNotFoundException(nc + " : "
533 + RestMessages.NORESOURCE.toString());
536 ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
537 ISwitchManager.class, containerName, this);
540 throw new ServiceUnavailableException("Switch Manager "
541 + RestMessages.SERVICEUNAVAILABLE.toString());
544 if (!sm.getNodeConnectors(node).contains(nc)) {
545 throw new ResourceNotFoundException(nc.toString() + " : "
546 + RestMessages.NORESOURCE.toString());