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.switchmanager.northbound;
11 import java.util.ArrayList;
12 import java.util.HashMap;
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.QueryParam;
27 import javax.ws.rs.core.Context;
28 import javax.ws.rs.core.MediaType;
29 import javax.ws.rs.core.Response;
30 import javax.ws.rs.core.SecurityContext;
31 import javax.ws.rs.core.UriInfo;
32 import javax.ws.rs.ext.ContextResolver;
34 import org.codehaus.enunciate.jaxrs.ResponseCode;
35 import org.codehaus.enunciate.jaxrs.StatusCodes;
36 import org.codehaus.enunciate.jaxrs.TypeHint;
37 import org.opendaylight.controller.containermanager.IContainerManager;
38 import org.opendaylight.controller.northbound.commons.RestMessages;
39 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
40 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
41 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
42 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
43 import org.opendaylight.controller.northbound.commons.query.QueryContext;
44 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
45 import org.opendaylight.controller.sal.authorization.Privilege;
46 import org.opendaylight.controller.sal.core.Node;
47 import org.opendaylight.controller.sal.core.NodeConnector;
48 import org.opendaylight.controller.sal.core.Property;
49 import org.opendaylight.controller.sal.utils.GlobalConstants;
50 import org.opendaylight.controller.sal.utils.ServiceHelper;
51 import org.opendaylight.controller.sal.utils.Status;
52 import org.opendaylight.controller.sal.utils.StatusCode;
53 import org.opendaylight.controller.switchmanager.ISwitchManager;
54 import org.opendaylight.controller.switchmanager.SwitchConfig;
57 * The class provides Northbound REST APIs to access the nodes, node connectors
58 * and their properties.
63 public class SwitchNorthbound {
65 private String username;
66 private QueryContext queryContext;
69 public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
70 if (queryCtxResolver != null) {
71 queryContext = queryCtxResolver.getContext(QueryContext.class);
76 public void setSecurityContext(SecurityContext context) {
77 if (context != null && context.getUserPrincipal() != null) {
78 username = context.getUserPrincipal().getName();
82 protected String getUserName() {
86 private ISwitchManager getIfSwitchManagerService(String containerName) {
87 IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(
88 IContainerManager.class, this);
89 if (containerManager == null) {
90 throw new ServiceUnavailableException("Container " + RestMessages.SERVICEUNAVAILABLE.toString());
93 boolean found = false;
94 List<String> containerNames = containerManager.getContainerNames();
95 for (String cName : containerNames) {
96 if (cName.trim().equalsIgnoreCase(containerName.trim())) {
102 if (found == false) {
103 throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString());
106 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
109 if (switchManager == null) {
110 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
113 return switchManager;
118 * Retrieve a list of all the nodes and their properties in the network
120 * @param containerName
121 * Name of the Container (Eg. 'default')
122 * @return A list of Pair each pair represents a
123 * {@link org.opendaylight.controller.sal.core.Node} and Set of
124 * {@link org.opendaylight.controller.sal.core.Property} attached to
132 * http://localhost:8080/controller/nb/v2/switchmanager/default/nodes
134 * Response body in XML:
135 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
137 *    <nodeProperties>
138 *       <node>
139 *          <id>00:00:00:00:00:00:00:02</id>
140 *          <type>OF</type>
141 *       </node>
142 *       <properties>
143 *          <tables>
144 *             <value>-1</value>
145 *          </tables>
146 *          <description>
147 *             <value>Switch2</value>
148 *          </description>
149 *          <actions>
150 *             <value>4095</value>
151 *          </actions>
152 *          <macAddress>
153 *             <value>00:00:00:00:00:02</value>
154 *          </macAddress>
155 *          <capabilities>
156 *             <value>199</value>
157 *          </capabilities>
158 *          <timeStamp>
159 *             <value>1377291227877</value>
160 *             <name>connectedSince</name>
161 *          </timeStamp>
162 *          <buffers>
163 *             <value>256</value>
164 *          </buffers>
165 *       </properties>
166 *    </nodeProperties>
169 * Response body in JSON:
174 * "id":"00:00:00:00:00:00:00:02",
188 * "value":"00:00:00:00:00:02"
194 * "value":"1377291227877",
195 * "name":"connectedSince"
207 @Path("/{containerName}/nodes")
209 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
210 @TypeHint(Nodes.class)
211 @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
212 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
213 @ResponseCode(code = 404, condition = "The containerName is not found"),
214 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable"),
215 @ResponseCode(code = 400, condition = "Incorrect query syntex") })
216 public Nodes getNodes(@PathParam("containerName") String containerName, @QueryParam("_q") String queryString) {
218 if (!isValidContainer(containerName)) {
219 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
222 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
223 throw new UnauthorizedException("User is not authorized to perform this operation on container "
227 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
228 if (switchManager == null) {
229 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
232 List<NodeProperties> res = new ArrayList<NodeProperties>();
233 Set<Node> nodes = switchManager.getNodes();
235 return new Nodes(res);
238 for (Node node : nodes) {
239 Map<String, Property> propMap = switchManager.getNodeProps(node);
240 if (propMap == null) {
243 Set<Property> props = new HashSet<Property>(propMap.values());
245 NodeProperties nodeProps = new NodeProperties(node, props);
248 Nodes result = new Nodes(res);
249 if (queryString != null) {
250 queryContext.createQuery(queryString, Nodes.class)
251 .filter(result, NodeProperties.class);
257 * Add a Description, Tier and Forwarding mode property to a node. This
258 * method returns a non-successful response if a node by that name already
261 * @param containerName
262 * Name of the Container (Eg. 'default')
264 * Type of the node being programmed (Eg. 'OF')
266 * Node Identifier as specified by
267 * {@link org.opendaylight.controller.sal.core.Node} (Eg.
268 * '00:00:00:00:00:00:00:03')
269 * @param propertyName
270 * Name of the Property. Properties that can be configured are:
271 * description, forwarding(only for default container) and tier
272 * @param propertyValue
273 * Value of the Property. Description can be any string (Eg.
274 * 'Node1'), valid values for tier are non negative numbers, and
275 * valid values for forwarding are 0 for reactive and 1 for
276 * proactive forwarding.
277 * @return Response as dictated by the HTTP Response Status code
284 * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:03/property/description/Switch3
289 @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}/{propertyValue}")
291 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
292 @TypeHint(Response.class)
294 @ResponseCode(code = 201, condition = "Operation successful"),
295 @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
296 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
297 @ResponseCode(code = 404, condition = "The Container Name or node or configuration name is not found"),
298 @ResponseCode(code = 406, condition = "The property cannot be configured in non-default container"),
299 @ResponseCode(code = 409, condition = "Unable to update configuration due to cluster conflict or conflicting description property"),
300 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
301 public Response addNodeProperty(@Context UriInfo uriInfo, @PathParam("containerName") String containerName,
302 @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
303 @PathParam("propertyName") String propertyName, @PathParam("propertyValue") String propertyValue) {
305 if (!isValidContainer(containerName)) {
306 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
308 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
309 throw new UnauthorizedException("User is not authorized to perform this operation on container "
312 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
313 if (switchManager == null) {
314 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
317 handleNodeAvailability(containerName, nodeType, nodeId);
318 Node node = Node.fromString(nodeType, nodeId);
319 Property prop = switchManager.createProperty(propertyName, propertyValue);
321 throw new ResourceNotFoundException("Property with name " + propertyName + " does not exist.");
323 SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
324 Map<String, Property> nodeProperties = (switchConfig == null) ? new HashMap<String, Property>()
325 : new HashMap<String, Property>(switchConfig.getNodeProperties());
326 nodeProperties.put(prop.getName(), prop);
327 SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
328 Status status = switchManager.updateNodeConfig(newSwitchConfig);
329 if (status.isSuccess()) {
330 NorthboundUtils.auditlog("Property " + propertyName, username, "updated",
331 "of Node " + NorthboundUtils.getNodeDesc(node, switchManager), containerName);
333 return Response.created(uriInfo.getRequestUri()).build();
335 return NorthboundUtils.getResponse(status);
339 * Delete a property of a node
341 * @param containerName
342 * Name of the Container (Eg. 'SliceRed')
344 * Type of the node being programmed (Eg. 'OF')
346 * Node Identifier as specified by
347 * {@link org.opendaylight.controller.sal.core.Node} (Eg.
348 * '00:00:00:00:00:03:01:02')
349 * @param propertyName
350 * Name of the Property. Properties that can be deleted are
351 * description, forwarding(only in default container) and tier.
352 * @return Response as dictated by the HTTP Response Status code
359 * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:03/property/forwarding
364 @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}")
366 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
367 @StatusCodes({ @ResponseCode(code = 204, condition = "Property removed successfully"),
368 @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
369 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
370 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
371 @ResponseCode(code = 409, condition = "Unable to delete property due to cluster conflict"),
372 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
373 public Response deleteNodeProperty(@PathParam("containerName") String containerName,
374 @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
375 @PathParam("propertyName") String propertyName) {
377 if (!isValidContainer(containerName)) {
378 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
380 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
381 throw new UnauthorizedException("User is not authorized to perform this operation on container "
384 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
385 if (switchManager == null) {
386 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
389 handleNodeAvailability(containerName, nodeType, nodeId);
390 Node node = Node.fromString(nodeType, nodeId);
392 SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
394 if (switchConfig == null) {
395 status = new Status(StatusCode.NOTFOUND, "Switch Configuration does not exist");
397 Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
398 if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
399 String msg = "Property " + propertyName + " does not exist or not configured for switch " + nodeId;
400 status = new Status(StatusCode.NOTFOUND, msg);
402 nodeProperties.remove(propertyName.toLowerCase());
403 SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
404 status = switchManager.updateNodeConfig(newSwitchConfig);
405 if (status.isSuccess()) {
406 NorthboundUtils.auditlog("Property " + propertyName, username, "removed", "of Node "
407 + NorthboundUtils.getNodeDesc(node, switchManager), containerName);
408 return Response.noContent().build();
412 return NorthboundUtils.getResponse(status);
416 * Get a property of a node
418 * @param containerName
419 * Name of the Container (Eg. 'SliceRed')
421 * Type of the node being programmed (Eg. 'OF')
423 * Node Identifier as specified by
424 * {@link org.opendaylight.controller.sal.core.Node} (Eg.
425 * '00:00:00:00:00:03:01:02')
426 * @param propertyName
427 * Name of the Property. Properties that can be deleted are
428 * description, forwarding(only in default container) and tier.
429 * @return Property value of the property
436 * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:01/property/description
438 * Response body in XML
439 * <description>
440 *   <value>switch1</value>
441 * </description>
443 * Response body in JSON
445 *   "value": "switch1"
450 @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}")
452 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
453 @TypeHint(String.class)
454 @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
455 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
456 @ResponseCode(code = 404, condition = "The containerName is not found"),
457 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
458 public Property getNodeProperty(@PathParam("containerName") String containerName,
459 @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
460 @PathParam("propertyName") String propertyName) {
462 if (!isValidContainer(containerName)) {
463 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
465 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
466 throw new UnauthorizedException("User is not authorized to perform this operation on container "
469 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
470 if (switchManager == null) {
471 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
474 handleNodeAvailability(containerName, nodeType, nodeId);
475 Node node = Node.fromString(nodeType, nodeId);
477 throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString());
479 SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
480 if (switchConfig == null) {
481 throw new ResourceNotFoundException(nodeId + " : " + "Config Not Found" );
483 Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
484 if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
485 String msg = "Property " + propertyName + " does not exist or not "
486 + "configured for switch " + nodeId;
487 throw new ResourceNotFoundException(msg);
489 return nodeProperties.get(propertyName.toLowerCase());
496 * Retrieve a list of all the nodeconnectors and their properties in a given
499 * @param containerName
500 * The container for which we want to retrieve the list (Eg.
503 * Type of the node being programmed (Eg. 'OF')
505 * Node Identifier as specified by
506 * {@link org.opendaylight.controller.sal.core.Node} (Eg.
507 * '00:00:00:00:00:00:00:03')
508 * @return A List of Pair each pair represents a
509 * {@link org.opendaylight.controller.sal.core.NodeConnector} and
511 * {@link org.opendaylight.controller.sal.core.Property} attached to
519 * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:01
521 * Response body in XML:
522 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
524 *    <nodeConnectorProperties>
525 *       <nodeconnector>
526 *          <node>
527 *             <id>00:00:00:00:00:00:00:01</id>
528 *             <type>OF</type>
529 *          </node>
530 *          <id>2</id>
531 *          <type>OF</type>
532 *       </nodeconnector>
533 *       <properties>
534 *          <state>
535 *             <value>1</value>
536 *          </state>
537 *          <config>
538 *             <value>1</value>
539 *          </config>
540 *          <name>
541 *             <value>L1_2-C2_1</value>
542 *          </name>
543 *       </properties>
544 *    </nodeConnectorProperties>
547 * Response body in JSON:
549 * "nodeConnectorProperties":[
553 * "id":"00:00:00:00:00:00:00:01",
567 * "value":"L1_2-C2_1"
576 @Path("/{containerName}/node/{nodeType}/{nodeId}")
578 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
579 @TypeHint(NodeConnectors.class)
580 @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
581 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
582 @ResponseCode(code = 404, condition = "The containerName is not found"),
583 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable"),
584 @ResponseCode(code = 400, condition = "Incorrect query syntex") })
585 public NodeConnectors getNodeConnectors(@PathParam("containerName") String containerName,
586 @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
587 @QueryParam("_q") String queryString) {
589 if (!isValidContainer(containerName)) {
590 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
592 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
593 throw new UnauthorizedException("User is not authorized to perform this operation on container "
597 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
598 if (switchManager == null) {
599 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
602 handleNodeAvailability(containerName, nodeType, nodeId);
603 Node node = Node.fromString(nodeType, nodeId);
604 List<NodeConnectorProperties> res = new ArrayList<NodeConnectorProperties>();
605 Set<NodeConnector> ncs = switchManager.getNodeConnectors(node);
610 for (NodeConnector nc : ncs) {
611 Map<String, Property> propMap = switchManager.getNodeConnectorProps(nc);
612 if (propMap == null) {
615 Set<Property> props = new HashSet<Property>(propMap.values());
616 NodeConnectorProperties ncProps = new NodeConnectorProperties(nc, props);
619 NodeConnectors result = new NodeConnectors(res);
620 if (queryString != null) {
621 queryContext.createQuery(queryString, NodeConnectors.class)
622 .filter(result, NodeConnectorProperties.class);
628 * Add node-connector property to a node connector. This method returns a
629 * non-successful response if a node connector by the given name already
632 * @param containerName
633 * Name of the Container (Eg. 'default')
635 * Type of the node being programmed (Eg. 'OF')
637 * Node Identifier as specified by
638 * {@link org.opendaylight.controller.sal.core.Node} (Eg.
639 * '00:00:00:00:00:00:00:03')
640 * @param nodeConnectorType
641 * Type of the node connector being programmed (Eg. 'OF')
642 * @param nodeConnectorId
643 * NodeConnector Identifier as specified by
644 * {@link org.opendaylight.controller.sal.core.NodeConnector}.
645 * (Eg. '2'). If nodeConnecterId contains forward slash(/),
646 * replace forward slash with underscore(_) in the URL. (Eg. for
647 * Ethernet1/2, use Ethernet1_2)
648 * @param propertyName
649 * Name of the Property specified by
650 * {@link org.opendaylight.controller.sal.core.Property} and its
651 * extended classes Property that can be configured is bandwidth
652 * @param propertyValue
653 * Value of the Property specified by
654 * {@link org.opendaylight.controller.sal.core.Property} and its
656 * @return Response as dictated by the HTTP Response Status code
663 * http://localhost:8080/controller/nb/v2/switchmanager/default/nodeconnector/OF/00:00:00:00:00:00:00:01/OF/2/property/bandwidth/1
668 @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propertyName}/{propertyValue}")
670 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
671 @StatusCodes({ @ResponseCode(code = 201, condition = "Operation successful"),
672 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
673 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
674 @ResponseCode(code = 409, condition = "Unable to add property due to cluster conflict"),
675 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
676 public Response addNodeConnectorProperty(@Context UriInfo uriInfo,
677 @PathParam("containerName") String containerName, @PathParam("nodeType") String nodeType,
678 @PathParam("nodeId") String nodeId, @PathParam("nodeConnectorType") String nodeConnectorType,
679 @PathParam("nodeConnectorId") String nodeConnectorId, @PathParam("propertyName") String propertyName,
680 @PathParam("propertyValue") String propertyValue) {
682 if (!isValidContainer(containerName)) {
683 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
685 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
686 throw new UnauthorizedException("User is not authorized to perform this operation on container "
690 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
691 if (switchManager == null) {
692 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
695 handleNodeAvailability(containerName, nodeType, nodeId);
696 Node node = Node.fromString(nodeType, nodeId);
698 if (nodeConnectorId.contains("_")) {
699 nodeConnectorId = nodeConnectorId.replace("_", "/");
702 handleNodeConnectorAvailability(containerName, node, nodeConnectorType, nodeConnectorId);
703 NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
705 Property prop = switchManager.createProperty(propertyName, propertyValue);
707 throw new ResourceNotFoundException(RestMessages.INVALIDDATA.toString());
710 Status ret = switchManager.addNodeConnectorProp(nc, prop);
711 if (ret.isSuccess()) {
712 NorthboundUtils.auditlog("Property " + propertyName, username, "updated", "of Node Connector "
713 + NorthboundUtils.getPortName(nc, switchManager), containerName);
714 return Response.created(uriInfo.getRequestUri()).build();
716 throw new InternalServerErrorException(ret.getDescription());
720 * Delete a property of a node connector
722 * @param containerName
723 * Name of the Container (Eg. 'default')
725 * Type of the node being programmed (Eg. 'OF')
727 * Node Identifier as specified by
728 * {@link org.opendaylight.controller.sal.core.Node} (Eg.
729 * '00:00:00:00:00:00:00:01')
730 * @param nodeConnectorType
731 * Type of the node connector being programmed (Eg. 'OF')
732 * @param nodeConnectorId
733 * NodeConnector Identifier as specified by
734 * {@link org.opendaylight.controller.sal.core.NodeConnector}
735 * (Eg. '1'). If nodeConnecterId contains forward slash(/),
736 * replace forward slash with underscore(_) in the URL. (Eg. for
737 * Ethernet1/2, use Ethernet1_2)
738 * @param propertyName
739 * Name of the Property specified by
740 * {@link org.opendaylight.controller.sal.core.Property} and its
741 * extended classes. Property that can be deleted is bandwidth
742 * @return Response as dictated by the HTTP Response Status code
749 * http://localhost:8080/controller/nb/v2/switchmanager/default/nodeconnector/OF/00:00:00:00:00:00:00:01/OF/2/property/bandwidth
754 @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propertyName}")
756 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
757 @StatusCodes({ @ResponseCode(code = 204, condition = "Property removed successfully"),
758 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
759 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
760 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
761 public Response deleteNodeConnectorProperty(@PathParam("containerName") String containerName,
762 @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
763 @PathParam("nodeConnectorType") String nodeConnectorType,
764 @PathParam("nodeConnectorId") String nodeConnectorId, @PathParam("propertyName") String propertyName) {
766 if (!isValidContainer(containerName)) {
767 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
769 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
770 throw new UnauthorizedException("User is not authorized to perform this operation on container "
774 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
775 if (switchManager == null) {
776 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
779 handleNodeAvailability(containerName, nodeType, nodeId);
780 Node node = Node.fromString(nodeType, nodeId);
782 if (nodeConnectorId.contains("_")) {
783 nodeConnectorId = nodeConnectorId.replace("_", "/");
786 handleNodeConnectorAvailability(containerName, node, nodeConnectorType, nodeConnectorId);
787 NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
788 Status ret = switchManager.removeNodeConnectorProp(nc, propertyName);
789 if (ret.isSuccess()) {
790 NorthboundUtils.auditlog("Property " + propertyName, username, "removed", "of Node Connector "
791 + NorthboundUtils.getPortName(nc, switchManager), containerName);
792 return Response.noContent().build();
794 throw new ResourceNotFoundException(ret.getDescription());
798 * Save the current switch configurations
800 * @param containerName
801 * Name of the Container (Eg. 'default')
802 * @return Response as dictated by the HTTP Response Status code
809 * http://localhost:8080/controller/nb/v2/switchmanager/default/save
813 @Path("/{containerName}/save")
815 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
817 @ResponseCode(code = 200, condition = "Operation successful"),
818 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
819 @ResponseCode(code = 404, condition = "The containerName is not found"),
820 @ResponseCode(code = 500, condition = "Failed to save switch configuration. Failure Reason included in HTTP Error response"),
821 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
822 public Response saveSwitchConfig(@PathParam("containerName") String containerName) {
824 if (!isValidContainer(containerName)) {
825 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
827 if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
828 throw new UnauthorizedException("User is not authorized to perform this operation on container "
831 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
832 if (switchManager == null) {
833 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
836 Status ret = switchManager.saveSwitchConfig();
837 if (ret.isSuccess()) {
838 return Response.ok().build();
840 throw new InternalServerErrorException(ret.getDescription());
843 private Node handleNodeAvailability(String containerName, String nodeType, String nodeId) {
845 Node node = Node.fromString(nodeType, nodeId);
847 throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString());
850 ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
853 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
856 if (!sm.getNodes().contains(node)) {
857 throw new ResourceNotFoundException(node.toString() + " : " + RestMessages.NONODE.toString());
862 private void handleNodeConnectorAvailability(String containerName, Node node, String nodeConnectorType,
863 String nodeConnectorId) {
865 NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
867 throw new ResourceNotFoundException(nc + " : " + RestMessages.NORESOURCE.toString());
870 ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
873 throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
876 if (!sm.getNodeConnectors(node).contains(nc)) {
877 throw new ResourceNotFoundException(nc.toString() + " : " + RestMessages.NORESOURCE.toString());
881 private boolean isValidContainer(String containerName) {
882 if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
885 IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(
886 IContainerManager.class, this);
887 if (containerManager == null) {
888 throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
890 if (containerManager.getContainerNames().contains(containerName)) {