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.core.Context;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
29 import javax.ws.rs.core.SecurityContext;
30 import javax.ws.rs.core.UriInfo;
32 import org.codehaus.enunciate.jaxrs.ResponseCode;
33 import org.codehaus.enunciate.jaxrs.StatusCodes;
34 import org.codehaus.enunciate.jaxrs.TypeHint;
35 import org.opendaylight.controller.containermanager.IContainerManager;
36 import org.opendaylight.controller.northbound.commons.RestMessages;
37 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
38 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
39 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
40 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
41 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
42 import org.opendaylight.controller.sal.authorization.Privilege;
43 import org.opendaylight.controller.sal.core.Node;
44 import org.opendaylight.controller.sal.core.NodeConnector;
45 import org.opendaylight.controller.sal.core.Property;
46 import org.opendaylight.controller.sal.utils.GlobalConstants;
47 import org.opendaylight.controller.sal.utils.ServiceHelper;
48 import org.opendaylight.controller.sal.utils.Status;
49 import org.opendaylight.controller.sal.utils.StatusCode;
50 import org.opendaylight.controller.switchmanager.ISwitchManager;
51 import org.opendaylight.controller.switchmanager.SwitchConfig;
54 * The class provides Northbound REST APIs to access the nodes, node connectors
55 * and their properties.
60 public class SwitchNorthbound {
62 private String username;
65 public void setSecurityContext(SecurityContext context) {
66 if (context != null && context.getUserPrincipal() != null) username = context.getUserPrincipal().getName();
69 protected String getUserName() {
73 private ISwitchManager getIfSwitchManagerService(String containerName) {
74 IContainerManager containerManager = (IContainerManager) ServiceHelper
75 .getGlobalInstance(IContainerManager.class, this);
76 if (containerManager == null) {
77 throw new ServiceUnavailableException("Container "
78 + RestMessages.SERVICEUNAVAILABLE.toString());
81 boolean found = false;
82 List<String> containerNames = containerManager.getContainerNames();
83 for (String cName : containerNames) {
84 if (cName.trim().equalsIgnoreCase(containerName.trim())) {
91 throw new ResourceNotFoundException(containerName + " "
92 + RestMessages.NOCONTAINER.toString());
95 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
96 .getInstance(ISwitchManager.class, containerName, this);
98 if (switchManager == null) {
99 throw new ServiceUnavailableException("Switch Manager "
100 + RestMessages.SERVICEUNAVAILABLE.toString());
103 return switchManager;
108 * Retrieve a list of all the nodes and their properties in the network
110 * @param containerName
111 * Name of the Container (Eg. 'default')
112 * @return A list of Pair each pair represents a
113 * {@link org.opendaylight.controller.sal.core.Node} and Set of
114 * {@link org.opendaylight.controller.sal.core.Property} attached to
122 * http://localhost:8080/controller/nb/v2/switchmanager/default/nodes
125 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
127 *    <nodeProperties>
128 *       <node>
129 *          <id>00:00:00:00:00:00:00:02</id>
130 *          <type>OF</type>
131 *       </node>
132 *       <properties>
133 *          <tables>
134 *             <value>-1</value>
135 *          </tables>
136 *          <description>
137 *             <value>Switch2</value>
138 *          </description>
139 *          <actions>
140 *             <value>4095</value>
141 *          </actions>
142 *          <macAddress>
143 *             <value>00:00:00:00:00:02</value>
144 *          </macAddress>
145 *          <capabilities>
146 *             <value>199</value>
147 *          </capabilities>
148 *          <timeStamp>
149 *             <value>1377291227877</value>
150 *             <name>connectedSince</name>
151 *          </timeStamp>
152 *          <buffers>
153 *             <value>256</value>
154 *          </buffers>
155 *       </properties>
156 *    </nodeProperties>
160 * {"nodeProperties":[{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},"properties":{"tables":{"value":"-1"},
161 * "description":{"value":"None"},"actions":{"value":"4095"},"macAddress":{"value":"00:00:00:00:00:02"},"capabilities"
162 * :{"value":"199"},"timeStamp":{"value":"1377291227877","name":"connectedSince"},"buffers":{"value":"256"}}}]}
166 @Path("/{containerName}/nodes")
168 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
169 @TypeHint(Nodes.class)
171 @ResponseCode(code = 200, condition = "Operation successful"),
172 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
173 @ResponseCode(code = 404, condition = "The containerName is not found"),
174 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
175 public Nodes getNodes(@PathParam("containerName") String containerName) {
177 if (!isValidContainer(containerName)) {
178 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
181 if (!NorthboundUtils.isAuthorized(
182 getUserName(), containerName, Privilege.READ, this)) {
183 throw new UnauthorizedException(
184 "User is not authorized to perform this operation on container "
188 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
189 if (switchManager == null) {
190 throw new ServiceUnavailableException("Switch Manager "
191 + RestMessages.SERVICEUNAVAILABLE.toString());
194 List<NodeProperties> res = new ArrayList<NodeProperties>();
195 Set<Node> nodes = switchManager.getNodes();
197 return new Nodes(res);
200 for (Node node : nodes) {
201 Map<String, Property> propMap = switchManager.getNodeProps(node);
202 if (propMap == null) {
205 Set<Property> props = new HashSet<Property>(propMap.values());
207 NodeProperties nodeProps = new NodeProperties(node, props);
211 return new Nodes(res);
215 * Add a Description, Tier and Forwarding mode property to a node. This
216 * method returns a non-successful response if a node by that name already
219 * @param containerName
220 * Name of the Container (Eg. 'default')
222 * Type of the node being programmed (Eg. 'OF')
224 * Node Identifier as specified by
225 * {@link org.opendaylight.controller.sal.core.Node}
226 * (Eg. '00:00:00:00:00:00:00:03')
227 * @param propertyName
228 * Name of the Property. Properties that can be
229 * configured are: description, forwarding(only for default
230 * container) and tier
231 * @param propertyValue
232 * Value of the Property. Description can be any string (Eg. 'Node1'),
233 * valid values for tier are 0, 1 and 2, and valid values for forwarding are 0 for
234 * reactive and 1 for proactive forwarding.
235 * @return Response as dictated by the HTTP Response Status code
242 * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:03/property/description/Switch3
247 @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}/{propertyValue}")
249 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
250 @TypeHint(Response.class)
252 @ResponseCode(code = 201, condition = "Operation successful"),
253 @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
254 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
255 @ResponseCode(code = 404, condition = "The Container Name or node or configuration name is not found"),
256 @ResponseCode(code = 406, condition = "The property cannot be configured in non-default container"),
257 @ResponseCode(code = 409, condition = "Unable to update configuration due to cluster conflict or conflicting description property"),
258 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
259 public Response addNodeProperty(
260 @Context UriInfo uriInfo,
261 @PathParam("containerName") String containerName,
262 @PathParam("nodeType") String nodeType,
263 @PathParam("nodeId") String nodeId,
264 @PathParam("propertyName") String propertyName,
265 @PathParam("propertyValue") String propertyValue) {
267 if (!isValidContainer(containerName)) {
268 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
270 if (!NorthboundUtils.isAuthorized(
271 getUserName(), containerName, Privilege.WRITE, this)) {
272 throw new UnauthorizedException(
273 "User is not authorized to perform this operation on container "
276 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
277 if (switchManager == null) {
278 throw new ServiceUnavailableException("Switch Manager "
279 + RestMessages.SERVICEUNAVAILABLE.toString());
282 handleNodeAvailability(containerName, nodeType, nodeId);
283 Node node = Node.fromString(nodeType, nodeId);
284 Property prop = switchManager.createProperty(propertyName, propertyValue);
286 throw new ResourceNotFoundException("Property with name " + propertyName + " does not exist.");
288 SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
289 Map<String, Property> nodeProperties = (switchConfig == null) ? new HashMap<String, Property>()
290 : new HashMap<String, Property>(switchConfig.getNodeProperties());
291 nodeProperties.put(prop.getName(), prop);
292 SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
293 Status status = switchManager.updateNodeConfig(newSwitchConfig);
294 if (status.isSuccess()) {
295 return Response.created(uriInfo.getRequestUri()).build();
297 return NorthboundUtils.getResponse(status);
301 * Delete a property of a node
303 * @param containerName
304 * Name of the Container (Eg. 'SliceRed')
306 * Type of the node being programmed (Eg. 'OF')
308 * Node Identifier as specified by
309 * {@link org.opendaylight.controller.sal.core.Node}
310 * (Eg. '00:00:00:00:00:03:01:02')
311 * @param propertyName
312 * Name of the Property. Properties that can be deleted are
313 * description, forwarding(only in default container) and tier.
314 * @return Response as dictated by the HTTP Response Status code
321 * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:03/property/forwarding
326 @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}")
328 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
330 @ResponseCode(code = 204, condition = "Property removed successfully"),
331 @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
332 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
333 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
334 @ResponseCode(code = 409, condition = "Unable to delete property due to cluster conflict"),
335 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
336 public Response deleteNodeProperty(
337 @PathParam("containerName") String containerName,
338 @PathParam("nodeType") String nodeType,
339 @PathParam("nodeId") String nodeId,
340 @PathParam("propertyName") String propertyName) {
342 if (!isValidContainer(containerName)) {
343 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
345 if (!NorthboundUtils.isAuthorized(
346 getUserName(), containerName, Privilege.WRITE, this)) {
347 throw new UnauthorizedException(
348 "User is not authorized to perform this operation on container "
351 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
352 if (switchManager == null) {
353 throw new ServiceUnavailableException("Switch Manager "
354 + RestMessages.SERVICEUNAVAILABLE.toString());
357 handleNodeAvailability(containerName, nodeType, nodeId);
358 Node node = Node.fromString(nodeType, nodeId);
360 SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
362 if (switchConfig == null) {
363 status = new Status(StatusCode.NOTFOUND, "Switch Configuration does not exist");
365 Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
366 if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
367 String msg = "Property " + propertyName + " does not exist or not configured for switch " + nodeId;
368 status = new Status(StatusCode.NOTFOUND, msg);
370 nodeProperties.remove(propertyName.toLowerCase());
371 SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
372 status = switchManager.updateNodeConfig(newSwitchConfig);
373 if(status.isSuccess()){
374 NorthboundUtils.auditlog("Node Property", username, "removed", propertyName + " from " + nodeId, containerName);
375 return Response.noContent().build();
379 return NorthboundUtils.getResponse(status);
384 * Retrieve a list of all the nodeconnectors and their properties in a given
387 * @param containerName
388 * The container for which we want to retrieve the list (Eg.
391 * Type of the node being programmed (Eg. 'OF')
393 * Node Identifier as specified by
394 * {@link org.opendaylight.controller.sal.core.Node} (Eg.
395 * '00:00:00:00:00:00:00:03')
396 * @return A List of Pair each pair represents a
397 * {@link org.opendaylight.controller.sal.core.NodeConnector} and
399 * {@link org.opendaylight.controller.sal.core.Property} attached to
407 * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:01
410 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
412 *    <nodeConnectorProperties>
413 *       <nodeconnector>
414 *          <node>
415 *             <id>00:00:00:00:00:00:00:01</id>
416 *             <type>OF</type>
417 *          </node>
418 *          <id>2</id>
419 *          <type>OF</type>
420 *       </nodeconnector>
421 *       <properties>
422 *          <state>
423 *             <value>1</value>
424 *          </state>
425 *          <config>
426 *             <value>1</value>
427 *          </config>
428 *          <name>
429 *             <value>L1_2-C2_1</value>
430 *          </name>
431 *       </properties>
432 *    </nodeConnectorProperties>
436 * {"nodeConnectorProperties":[{"nodeconnector":{"node":{"id":"00:00:00:00:00:00:00:01","type":"OF"},"id":"2","type":"OF"},
437 * "properties":{"state":{"value":"1"},"config":{"value":"1"},"name":{"value":"L1_2-C2_1"}}}]}
441 @Path("/{containerName}/node/{nodeType}/{nodeId}")
443 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
444 @TypeHint(NodeConnectors.class)
446 @ResponseCode(code = 200, condition = "Operation successful"),
447 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
448 @ResponseCode(code = 404, condition = "The containerName is not found"),
449 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
450 public NodeConnectors getNodeConnectors(
451 @PathParam("containerName") String containerName,
452 @PathParam("nodeType") String nodeType,
453 @PathParam("nodeId") String nodeId) {
455 if (!isValidContainer(containerName)) {
456 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
458 if (!NorthboundUtils.isAuthorized(
459 getUserName(), containerName, Privilege.READ, this)) {
460 throw new UnauthorizedException(
461 "User is not authorized to perform this operation on container "
465 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
466 if (switchManager == null) {
467 throw new ServiceUnavailableException("Switch Manager "
468 + RestMessages.SERVICEUNAVAILABLE.toString());
471 handleNodeAvailability(containerName, nodeType, nodeId);
472 Node node = Node.fromString(nodeType, nodeId);
473 List<NodeConnectorProperties> res = new ArrayList<NodeConnectorProperties>();
474 Set<NodeConnector> ncs = switchManager.getNodeConnectors(node);
479 for (NodeConnector nc : ncs) {
480 Map<String, Property> propMap = switchManager
481 .getNodeConnectorProps(nc);
482 if (propMap == null) {
485 Set<Property> props = new HashSet<Property>(propMap.values());
486 NodeConnectorProperties ncProps = new NodeConnectorProperties(nc,
491 return new NodeConnectors(res);
495 * Add node-connector property to a node connector. This method returns a
496 * non-successful response if a node connector by the given name already
499 * @param containerName
500 * Name of the Container (Eg. 'default')
502 * Type of the node being programmed (Eg. 'OF')
504 * Node Identifier as specified by
505 * {@link org.opendaylight.controller.sal.core.Node}
506 * (Eg. '00:00:00:00:00:00:00:03')
507 * @param nodeConnectorType
508 * Type of the node connector being programmed (Eg. 'OF')
509 * @param nodeConnectorId
510 * NodeConnector Identifier as specified by
511 * {@link org.opendaylight.controller.sal.core.NodeConnector}
513 * @param propertyName
514 * Name of the Property specified by
515 * {@link org.opendaylight.controller.sal.core.Property} and its
517 * Property that can be configured is bandwidth
518 * @param propertyValue
519 * Value of the Property specified by
520 * {@link org.opendaylight.controller.sal.core.Property} and its
522 * @return Response as dictated by the HTTP Response Status code
529 * http://localhost:8080/controller/nb/v2/switchmanager/default/nodeconnector/OF/00:00:00:00:00:00:00:01/OF/2/property/bandwidth/1
534 @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propertyName}/{propertyValue}")
536 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
538 @ResponseCode(code = 201, condition = "Operation successful"),
539 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
540 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
541 @ResponseCode(code = 409, condition = "Unable to add property due to cluster conflict"),
542 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
543 public Response addNodeConnectorProperty(
544 @Context UriInfo uriInfo,
545 @PathParam("containerName") String containerName,
546 @PathParam("nodeType") String nodeType,
547 @PathParam("nodeId") String nodeId,
548 @PathParam("nodeConnectorType") String nodeConnectorType,
549 @PathParam("nodeConnectorId") String nodeConnectorId,
550 @PathParam("propertyName") String propertyName,
551 @PathParam("propertyValue") String propertyValue) {
553 if (!isValidContainer(containerName)) {
554 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
556 if (!NorthboundUtils.isAuthorized(
557 getUserName(), containerName, Privilege.WRITE, this)) {
558 throw new UnauthorizedException(
559 "User is not authorized to perform this operation on container "
563 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
564 if (switchManager == null) {
565 throw new ServiceUnavailableException("Switch Manager "
566 + RestMessages.SERVICEUNAVAILABLE.toString());
569 handleNodeAvailability(containerName, nodeType, nodeId);
570 Node node = Node.fromString(nodeType, nodeId);
572 handleNodeConnectorAvailability(containerName, node, nodeConnectorType,
574 NodeConnector nc = NodeConnector
575 .fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
577 Property prop = switchManager.createProperty(propertyName, propertyValue);
579 throw new ResourceNotFoundException(
580 RestMessages.INVALIDDATA.toString());
583 Status ret = switchManager.addNodeConnectorProp(nc, prop);
584 if (ret.isSuccess()) {
585 return Response.created(uriInfo.getRequestUri()).build();
587 throw new InternalServerErrorException(ret.getDescription());
591 * Delete a property of a node connector
593 * @param containerName
594 * Name of the Container (Eg. 'default')
596 * Type of the node being programmed (Eg. 'OF')
598 * Node Identifier as specified by
599 * {@link org.opendaylight.controller.sal.core.Node}
600 * (Eg. '00:00:00:00:00:00:00:01')
601 * @param nodeConnectorType
602 * Type of the node connector being programmed (Eg. 'OF')
603 * @param nodeConnectorId
604 * NodeConnector Identifier as specified by
605 * {@link org.opendaylight.controller.sal.core.NodeConnector}
607 * @param propertyName
608 * Name of the Property specified by
609 * {@link org.opendaylight.controller.sal.core.Property} and its
610 * extended classes. Property that can be deleted is bandwidth
611 * @return Response as dictated by the HTTP Response Status code
618 * http://localhost:8080/controller/nb/v2/switchmanager/default/nodeconnector/OF/00:00:00:00:00:00:00:01/OF/2/property/bandwidth
623 @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propertyName}")
625 @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
627 @ResponseCode(code = 204, condition = "Property removed successfully"),
628 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
629 @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
630 @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
631 public Response deleteNodeConnectorProperty(
632 @PathParam("containerName") String containerName,
633 @PathParam("nodeType") String nodeType,
634 @PathParam("nodeId") String nodeId,
635 @PathParam("nodeConnectorType") String nodeConnectorType,
636 @PathParam("nodeConnectorId") String nodeConnectorId,
637 @PathParam("propertyName") String propertyName) {
639 if (!isValidContainer(containerName)) {
640 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
642 if (!NorthboundUtils.isAuthorized(
643 getUserName(), containerName, Privilege.WRITE, this)) {
644 throw new UnauthorizedException(
645 "User is not authorized to perform this operation on container "
649 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
650 if (switchManager == null) {
651 throw new ServiceUnavailableException("Switch Manager "
652 + RestMessages.SERVICEUNAVAILABLE.toString());
655 handleNodeAvailability(containerName, nodeType, nodeId);
656 Node node = Node.fromString(nodeType, nodeId);
658 handleNodeConnectorAvailability(containerName, node, nodeConnectorType,
660 NodeConnector nc = NodeConnector
661 .fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
662 Status ret = switchManager.removeNodeConnectorProp(nc, propertyName);
663 if (ret.isSuccess()) {
664 NorthboundUtils.auditlog("Node Connector Property", username, "removed", nc + " from " + nodeConnectorId, containerName);
665 return Response.noContent().build();
667 throw new ResourceNotFoundException(ret.getDescription());
671 * Save the current switch configurations
673 * @param containerName
674 * Name of the Container (Eg. 'default')
675 * @return Response as dictated by the HTTP Response Status code
682 * http://localhost:8080/controller/nb/v2/switchmanager/default/save
686 @Path("/{containerName}/save")
688 @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
690 @ResponseCode(code = 200, condition = "Operation successful"),
691 @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
692 @ResponseCode(code = 404, condition = "The containerName is not found"),
693 @ResponseCode(code = 500, condition = "Failed to save switch configuration. Failure Reason included in HTTP Error response"),
694 @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
695 public Response saveSwitchConfig(
696 @PathParam("containerName") String containerName) {
698 if (!isValidContainer(containerName)) {
699 throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
701 if (!NorthboundUtils.isAuthorized(
702 getUserName(), containerName, Privilege.WRITE, this)) {
703 throw new UnauthorizedException(
704 "User is not authorized to perform this operation on container "
707 ISwitchManager switchManager = getIfSwitchManagerService(containerName);
708 if (switchManager == null) {
709 throw new ServiceUnavailableException("Switch Manager "
710 + RestMessages.SERVICEUNAVAILABLE.toString());
713 Status ret = switchManager.saveSwitchConfig();
714 if (ret.isSuccess()) {
715 return Response.ok().build();
717 throw new InternalServerErrorException(ret.getDescription());
720 private Node handleNodeAvailability(String containerName, String nodeType,
723 Node node = Node.fromString(nodeType, nodeId);
725 throw new ResourceNotFoundException(nodeId + " : "
726 + RestMessages.NONODE.toString());
729 ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
730 ISwitchManager.class, containerName, this);
733 throw new ServiceUnavailableException("Switch Manager "
734 + RestMessages.SERVICEUNAVAILABLE.toString());
737 if (!sm.getNodes().contains(node)) {
738 throw new ResourceNotFoundException(node.toString() + " : "
739 + RestMessages.NONODE.toString());
744 private void handleNodeConnectorAvailability(String containerName,
745 Node node, String nodeConnectorType, String nodeConnectorId) {
747 NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType,
748 nodeConnectorId, node);
750 throw new ResourceNotFoundException(nc + " : "
751 + RestMessages.NORESOURCE.toString());
754 ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
755 ISwitchManager.class, containerName, this);
758 throw new ServiceUnavailableException("Switch Manager "
759 + RestMessages.SERVICEUNAVAILABLE.toString());
762 if (!sm.getNodeConnectors(node).contains(nc)) {
763 throw new ResourceNotFoundException(nc.toString() + " : "
764 + RestMessages.NORESOURCE.toString());
768 private boolean isValidContainer(String containerName) {
769 if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
772 IContainerManager containerManager = (IContainerManager) ServiceHelper
773 .getGlobalInstance(IContainerManager.class, this);
774 if (containerManager == null) {
775 throw new InternalServerErrorException(
776 RestMessages.INTERNALERROR.toString());
778 if (containerManager.getContainerNames().contains(containerName)) {