Fix to set/delete Switch Configuration using Northbound API
[controller.git] / opendaylight / northbound / switchmanager / src / main / java / org / opendaylight / controller / switchmanager / northbound / SwitchNorthbound.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.controller.switchmanager.northbound;
10
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
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
31 import org.codehaus.enunciate.jaxrs.ResponseCode;
32 import org.codehaus.enunciate.jaxrs.StatusCodes;
33 import org.codehaus.enunciate.jaxrs.TypeHint;
34 import org.opendaylight.controller.containermanager.IContainerManager;
35 import org.opendaylight.controller.northbound.commons.RestMessages;
36 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
37 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
38 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
39 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
40 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
41 import org.opendaylight.controller.sal.authorization.Privilege;
42 import org.opendaylight.controller.sal.core.Node;
43 import org.opendaylight.controller.sal.core.NodeConnector;
44 import org.opendaylight.controller.sal.core.Property;
45 import org.opendaylight.controller.sal.utils.GlobalConstants;
46 import org.opendaylight.controller.sal.utils.ServiceHelper;
47 import org.opendaylight.controller.sal.utils.Status;
48 import org.opendaylight.controller.sal.utils.StatusCode;
49 import org.opendaylight.controller.switchmanager.ISwitchManager;
50 import org.opendaylight.controller.switchmanager.SwitchConfig;
51
52 /**
53  * The class provides Northbound REST APIs to access the nodes, node connectors
54  * and their properties.
55  *
56  */
57
58 @Path("/")
59 public class SwitchNorthbound {
60
61     private String username;
62
63     @Context
64     public void setSecurityContext(SecurityContext context) {
65         username = context.getUserPrincipal().getName();
66     }
67
68     protected String getUserName() {
69         return username;
70     }
71
72     private ISwitchManager getIfSwitchManagerService(String containerName) {
73         IContainerManager containerManager = (IContainerManager) ServiceHelper
74                 .getGlobalInstance(IContainerManager.class, this);
75         if (containerManager == null) {
76             throw new ServiceUnavailableException("Container "
77                     + RestMessages.SERVICEUNAVAILABLE.toString());
78         }
79
80         boolean found = false;
81         List<String> containerNames = containerManager.getContainerNames();
82         for (String cName : containerNames) {
83             if (cName.trim().equalsIgnoreCase(containerName.trim())) {
84                 found = true;
85                 break;
86             }
87         }
88
89         if (found == false) {
90             throw new ResourceNotFoundException(containerName + " "
91                     + RestMessages.NOCONTAINER.toString());
92         }
93
94         ISwitchManager switchManager = (ISwitchManager) ServiceHelper
95                 .getInstance(ISwitchManager.class, containerName, this);
96
97         if (switchManager == null) {
98             throw new ServiceUnavailableException("Switch Manager "
99                     + RestMessages.SERVICEUNAVAILABLE.toString());
100         }
101
102         return switchManager;
103     }
104
105     /**
106      *
107      * Retrieve a list of all the nodes and their properties in the network
108      *
109      * @param containerName
110      *            The container for which we want to retrieve the list
111      * @return A list of Pair each pair represents a
112      *         {@link org.opendaylight.controller.sal.core.Node} and Set of
113      *         {@link org.opendaylight.controller.sal.core.Property} attached to
114      *         it.
115      */
116     @Path("/{containerName}/nodes")
117     @GET
118     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
119     @TypeHint(Nodes.class)
120     @StatusCodes({
121             @ResponseCode(code = 200, condition = "Operation successful"),
122             @ResponseCode(code = 404, condition = "The containerName is not found"),
123             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
124     public Nodes getNodes(@PathParam("containerName") String containerName) {
125
126         if (!isValidContainer(containerName)) {
127             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
128         }
129
130         if (!NorthboundUtils.isAuthorized(
131                 getUserName(), containerName, Privilege.READ, this)) {
132             throw new UnauthorizedException(
133                     "User is not authorized to perform this operation on container "
134                             + containerName);
135         }
136
137         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
138         if (switchManager == null) {
139             throw new ServiceUnavailableException("Switch Manager "
140                     + RestMessages.SERVICEUNAVAILABLE.toString());
141         }
142
143         List<NodeProperties> res = new ArrayList<NodeProperties>();
144         Set<Node> nodes = switchManager.getNodes();
145         if (nodes == null) {
146             return null;
147         }
148
149         for (Node node : nodes) {
150             Map<String, Property> propMap = switchManager.getNodeProps(node);
151             if (propMap == null) {
152                 continue;
153             }
154             Set<Property> props = new HashSet<Property>(propMap.values());
155
156             NodeProperties nodeProps = new NodeProperties(node, props);
157             res.add(nodeProps);
158         }
159
160         return new Nodes(res);
161     }
162
163     /**
164      * Add a Name, Tier and Forwarding mode property to a node.
165      *
166      * <pre>
167      * Example Request:
168      *  http://localhost:8080/controller/nb/v2/switch/red/node/OF/00:00:00:00:00:03/property/description/Switch3
169      *  (Valid properties that can be configured are: description, forwarding(only for default container) and tier)
170      * </pre>
171      *
172      * @param containerName
173      *            Name of the Container
174      * @param nodeType
175      *            Type of the node being programmed
176      * @param nodeId
177      *            Node Identifier as specified by
178      *            {@link org.opendaylight.controller.sal.core.Node}
179      * @param propName
180      *            Name of the Property specified by
181      *            {@link org.opendaylight.controller.sal.core.Property} and its
182      *            extended classes
183      * @param propValue
184      *            Value of the Property specified by
185      *            {@link org.opendaylight.controller.sal.core.Property} and its
186      *            extended classes
187      * @return Response as dictated by the HTTP Response Status code
188      */
189
190     @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propName}/{propValue}")
191     @PUT
192     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
193     @TypeHint(Response.class)
194     @StatusCodes({
195             @ResponseCode(code = 200, condition = "Operation successful"),
196             @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
197             @ResponseCode(code = 404, condition = "The Container Name or node or configuration name is not found"),
198             @ResponseCode(code = 406, condition = "The property cannot be configured in non-default container"),
199             @ResponseCode(code = 409, condition = "Unable to update configuration due to cluster conflict"),
200             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
201     public Response addNodeProperty(
202             @PathParam("containerName") String containerName,
203             @PathParam("nodeType") String nodeType,
204             @PathParam("nodeId") String nodeId,
205             @PathParam("propName") String propName,
206             @PathParam("propValue") String propValue) {
207
208         if (!isValidContainer(containerName)) {
209             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
210         }
211         if (!NorthboundUtils.isAuthorized(
212                 getUserName(), containerName, Privilege.WRITE, this)) {
213             throw new UnauthorizedException(
214                     "User is not authorized to perform this operation on container "
215                             + containerName);
216         }
217         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
218         if (switchManager == null) {
219             throw new ServiceUnavailableException("Switch Manager "
220                     + RestMessages.SERVICEUNAVAILABLE.toString());
221         }
222
223         handleNodeAvailability(containerName, nodeType, nodeId);
224         Node node = Node.fromString(nodeType, nodeId);
225         Property prop = switchManager.createProperty(propName, propValue);
226         if (prop == null) {
227             throw new ResourceNotFoundException("Property with name " + propName + " does not exist.");
228         }
229         SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
230         Map<String, Property> nodeProperties = (switchConfig == null) ? new HashMap<String, Property>()
231                 : new HashMap<String, Property>(switchConfig.getNodeProperties());
232         nodeProperties.put(prop.getName(), prop);
233         SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
234         Status status = switchManager.updateNodeConfig(newSwitchConfig);
235         return NorthboundUtils.getResponse(status);
236     }
237
238     /**
239      * Delete a property of a node
240      *
241      * <pre>
242      * Example Request:
243      *  http://localhost:8080/controller/nb/v2/switch/default/node/OF/00:00:00:00:00:03/property/forwarding
244      * </pre>
245      *
246      * @param containerName
247      *            Name of the Container
248      * @param nodeType
249      *            Type of the node being programmed
250      * @param nodeId
251      *            Node Identifier as specified by
252      *            {@link org.opendaylight.controller.sal.core.Node}
253      * @param propertyName
254      *            Name of the Property specified by
255      *            {@link org.opendaylight.controller.sal.core.Property} and its
256      *            extended classes
257      * @return Response as dictated by the HTTP Response Status code
258      */
259
260     @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}")
261     @DELETE
262     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
263     @StatusCodes({
264             @ResponseCode(code = 200, condition = "Operation successful"),
265             @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
266             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
267             @ResponseCode(code = 409, condition = "Unable to delete property due to cluster conflict"),
268             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
269     public Response deleteNodeProperty(
270             @PathParam("containerName") String containerName,
271             @PathParam("nodeType") String nodeType,
272             @PathParam("nodeId") String nodeId,
273             @PathParam("propertyName") String propertyName) {
274
275         if (!isValidContainer(containerName)) {
276             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
277         }
278         if (!NorthboundUtils.isAuthorized(
279                 getUserName(), containerName, Privilege.WRITE, this)) {
280             throw new UnauthorizedException(
281                     "User is not authorized to perform this operation on container "
282                             + containerName);
283         }
284         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
285         if (switchManager == null) {
286             throw new ServiceUnavailableException("Switch Manager "
287                     + RestMessages.SERVICEUNAVAILABLE.toString());
288         }
289
290         handleNodeAvailability(containerName, nodeType, nodeId);
291         Node node = Node.fromString(nodeType, nodeId);
292
293         SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
294         Status status;
295         if (switchConfig == null) {
296             status = new Status(StatusCode.NOTFOUND, "Switch Configuration does not exist");
297         } else {
298             Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
299             if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
300                 String msg = "Property " + propertyName + " does not exist or not configured for switch " + nodeId;
301                 status = new Status(StatusCode.NOTFOUND, msg);
302             } else {
303                 nodeProperties.remove(propertyName.toLowerCase());
304                 SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
305                 status = switchManager.updateNodeConfig(newSwitchConfig);
306             }
307         }
308         return NorthboundUtils.getResponse(status);
309     }
310
311     /**
312      *
313      * Retrieve a list of all the node connectors and their properties in a
314      * given node
315      *
316      * @param containerName
317      *            The container for which we want to retrieve the list
318      * @param nodeType
319      *            Type of the node being programmed
320      * @param nodeId
321      *            Node Identifier as specified by
322      *            {@link org.opendaylight.controller.sal.core.Node}
323      * @return A List of Pair each pair represents a
324      *         {@link org.opendaylight.controller.sal.core.NodeConnector} and
325      *         its corresponding
326      *         {@link org.opendaylight.controller.sal.core.Property} attached to
327      *         it.
328      */
329     @Path("/{containerName}/node/{nodeType}/{nodeId}")
330     @GET
331     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
332     @TypeHint(NodeConnectors.class)
333     @StatusCodes({
334             @ResponseCode(code = 200, condition = "Operation successful"),
335             @ResponseCode(code = 404, condition = "The containerName is not found"),
336             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
337     public NodeConnectors getNodeConnectors(
338             @PathParam("containerName") String containerName,
339             @PathParam("nodeType") String nodeType,
340             @PathParam("nodeId") String nodeId) {
341
342         if (!isValidContainer(containerName)) {
343             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
344         }
345         if (!NorthboundUtils.isAuthorized(
346                 getUserName(), containerName, Privilege.READ, this)) {
347             throw new UnauthorizedException(
348                     "User is not authorized to perform this operation on container "
349                             + containerName);
350         }
351
352         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
353         if (switchManager == null) {
354             throw new ServiceUnavailableException("Switch Manager "
355                     + RestMessages.SERVICEUNAVAILABLE.toString());
356         }
357
358         handleNodeAvailability(containerName, nodeType, nodeId);
359         Node node = Node.fromString(nodeType, nodeId);
360         List<NodeConnectorProperties> res = new ArrayList<NodeConnectorProperties>();
361         Set<NodeConnector> ncs = switchManager.getNodeConnectors(node);
362         if (ncs == null) {
363             return null;
364         }
365
366         for (NodeConnector nc : ncs) {
367             Map<String, Property> propMap = switchManager
368                     .getNodeConnectorProps(nc);
369             if (propMap == null) {
370                 continue;
371             }
372             Set<Property> props = new HashSet<Property>(propMap.values());
373             NodeConnectorProperties ncProps = new NodeConnectorProperties(nc,
374                     props);
375             res.add(ncProps);
376         }
377
378         return new NodeConnectors(res);
379     }
380
381     /**
382      * Add a Name/Bandwidth property to a node connector
383      *
384      * @param containerName
385      *            Name of the Container
386      * @param nodeType
387      *            Type of the node being programmed
388      * @param nodeId
389      *            Node Identifier as specified by
390      *            {@link org.opendaylight.controller.sal.core.Node}
391      * @param nodeConnectorType
392      *            Type of the node connector being programmed
393      * @param nodeConnectorId
394      *            NodeConnector Identifier as specified by
395      *            {@link org.opendaylight.controller.sal.core.NodeConnector}
396      * @param propName
397      *            Name of the Property specified by
398      *            {@link org.opendaylight.controller.sal.core.Property} and its
399      *            extended classes
400      * @param propValue
401      *            Value of the Property specified by
402      *            {@link org.opendaylight.controller.sal.core.Property} and its
403      *            extended classes
404      * @return Response as dictated by the HTTP Response Status code
405      */
406
407     @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propName}/{propValue}")
408     @PUT
409     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
410     @StatusCodes({
411             @ResponseCode(code = 200, condition = "Operation successful"),
412             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
413             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
414     public Response addNodeConnectorProperty(
415             @PathParam("containerName") String containerName,
416             @PathParam("nodeType") String nodeType,
417             @PathParam("nodeId") String nodeId,
418             @PathParam("nodeConnectorType") String nodeConnectorType,
419             @PathParam("nodeConnectorId") String nodeConnectorId,
420             @PathParam("propName") String propName,
421             @PathParam("propValue") String propValue) {
422
423         if (!isValidContainer(containerName)) {
424             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
425         }
426         if (!NorthboundUtils.isAuthorized(
427                 getUserName(), containerName, Privilege.WRITE, this)) {
428             throw new UnauthorizedException(
429                     "User is not authorized to perform this operation on container "
430                             + containerName);
431         }
432
433         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
434         if (switchManager == null) {
435             throw new ServiceUnavailableException("Switch Manager "
436                     + RestMessages.SERVICEUNAVAILABLE.toString());
437         }
438
439         handleNodeAvailability(containerName, nodeType, nodeId);
440         Node node = Node.fromString(nodeType, nodeId);
441
442         handleNodeConnectorAvailability(containerName, node, nodeConnectorType,
443                 nodeConnectorId);
444         NodeConnector nc = NodeConnector
445                 .fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
446
447         Property prop = switchManager.createProperty(propName, propValue);
448         if (prop == null) {
449             throw new ResourceNotFoundException(
450                     RestMessages.INVALIDDATA.toString());
451         }
452
453         Status ret = switchManager.addNodeConnectorProp(nc, prop);
454         if (ret.isSuccess()) {
455             return Response.status(Response.Status.CREATED).build();
456         }
457         throw new InternalServerErrorException(ret.getDescription());
458     }
459
460     /**
461      * Delete a property of a node connector
462      *
463      * @param containerName
464      *            Name of the Container
465      * @param nodeType
466      *            Type of the node being programmed
467      * @param nodeId
468      *            Node Identifier as specified by
469      *            {@link org.opendaylight.controller.sal.core.Node}
470      * @param nodeConnectorType
471      *            Type of the node connector being programmed
472      * @param nodeConnectorId
473      *            NodeConnector Identifier as specified by
474      *            {@link org.opendaylight.controller.sal.core.NodeConnector}
475      * @param propertyName
476      *            Name of the Property specified by
477      *            {@link org.opendaylight.controller.sal.core.Property} and its
478      *            extended classes
479      * @return Response as dictated by the HTTP Response Status code
480      */
481
482     @Path("/{containerName}/nodeconnector/{nodeType}/{nodeId}/{nodeConnectorType}/{nodeConnectorId}/property/{propertyName}")
483     @DELETE
484     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
485     @StatusCodes({
486             @ResponseCode(code = 200, condition = "Operation successful"),
487             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
488             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
489     public Response deleteNodeConnectorProperty(
490             @PathParam("containerName") String containerName,
491             @PathParam("nodeType") String nodeType,
492             @PathParam("nodeId") String nodeId,
493             @PathParam("nodeConnectorType") String nodeConnectorType,
494             @PathParam("nodeConnectorId") String nodeConnectorId,
495             @PathParam("propertyName") String propertyName) {
496
497         if (!isValidContainer(containerName)) {
498             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
499         }
500         if (!NorthboundUtils.isAuthorized(
501                 getUserName(), containerName, Privilege.WRITE, this)) {
502             throw new UnauthorizedException(
503                     "User is not authorized to perform this operation on container "
504                             + containerName);
505         }
506
507         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
508         if (switchManager == null) {
509             throw new ServiceUnavailableException("Switch Manager "
510                     + RestMessages.SERVICEUNAVAILABLE.toString());
511         }
512
513         handleNodeAvailability(containerName, nodeType, nodeId);
514         Node node = Node.fromString(nodeType, nodeId);
515
516         handleNodeConnectorAvailability(containerName, node, nodeConnectorType,
517                 nodeConnectorId);
518         NodeConnector nc = NodeConnector
519                 .fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
520         Status ret = switchManager.removeNodeConnectorProp(nc, propertyName);
521         if (ret.isSuccess()) {
522             return Response.ok().build();
523         }
524         throw new ResourceNotFoundException(ret.getDescription());
525     }
526
527     /*    *//**
528      * Retrieve a list of Span ports that were configured previously.
529      *
530      * @param containerName
531      *            Name of the Container
532      * @return list of
533      *         {@link org.opendaylight.controller.switchmanager.SpanConfig}
534      *         resources
535      */
536     /*
537      * @Path("/span-config/{containerName}")
538      *
539      * @GET
540      *
541      * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
542      *
543      * @StatusCodes( {
544      *
545      * @ResponseCode(code = 200, condition = "Operation successful"),
546      *
547      * @ResponseCode(code = 404, condition = "The containerName is not found"),
548      *
549      * @ResponseCode(code = 503, condition =
550      * "One or more of Controller Services are unavailable") }) public
551      * List<SpanConfig> getSpanConfigList(@PathParam("containerName") String
552      * containerName) { ISwitchManager switchManager = (ISwitchManager)
553      * getIfSwitchManagerService(containerName); if (switchManager == null) {
554      * throw new ServiceUnavailableException("Switch Manager " +
555      * RestMessages.SERVICEUNAVAILABLE.toString()); }
556      *
557      * return switchManager.getSpanConfigList(); }
558      *//**
559      * Add a span configuration
560      *
561      * @param containerName
562      *            Name of the Container
563      * @param config
564      *            {@link org.opendaylight.controller.switchmanager.SpanConfig}
565      *            in JSON or XML format
566      * @return Response as dictated by the HTTP Response Status code
567      */
568     /*
569      * @Path("/span-config/{containerName}")
570      *
571      * @PUT
572      *
573      * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
574      *
575      * @StatusCodes( {
576      *
577      * @ResponseCode(code = 200, condition = "Operation successful"),
578      *
579      * @ResponseCode(code = 404, condition = "The containerName is not found"),
580      *
581      * @ResponseCode(code = 503, condition =
582      * "One or more of Controller Services are unavailable") }) public Response
583      * addSpanConfig(@PathParam("containerName") String containerName,
584      *
585      * @TypeHint(SubnetConfig.class) JAXBElement<SpanConfig> config) {
586      * ISwitchManager switchManager = (ISwitchManager)
587      * getIfSwitchManagerService(containerName); if (switchManager == null) {
588      * throw new ServiceUnavailableException("Switch Manager " +
589      * RestMessages.SERVICEUNAVAILABLE.toString()); }
590      *
591      * String ret = switchManager.addSpanConfig(config.getValue()); if
592      * (ret.equals(ReturnString.SUCCESS.toString())) { return
593      * Response.status(Response.Status.CREATED).build(); } throw new
594      * InternalServerErrorException(ret); }
595      *//**
596      * Delete a span configuration
597      *
598      * @param containerName
599      *            Name of the Container
600      * @param config
601      *            {@link org.opendaylight.controller.switchmanager.SpanConfig}
602      *            in JSON or XML format
603      * @return Response as dictated by the HTTP Response Status code
604      */
605     /*
606      * @Path("/span-config/{containerName}")
607      *
608      * @DELETE
609      *
610      * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
611      *
612      * @StatusCodes( {
613      *
614      * @ResponseCode(code = 200, condition = "Operation successful"),
615      *
616      * @ResponseCode(code = 404, condition = "The containerName is not found"),
617      *
618      * @ResponseCode(code = 503, condition =
619      * "One or more of Controller Services are unavailable") }) public Response
620      * deleteSpanConfig(@PathParam("containerName") String containerName,
621      *
622      * @TypeHint(SubnetConfig.class) JAXBElement<SpanConfig> config) {
623      * ISwitchManager switchManager = (ISwitchManager)
624      * getIfSwitchManagerService(containerName); if (switchManager == null) {
625      * throw new ServiceUnavailableException("Switch Manager " +
626      * RestMessages.SERVICEUNAVAILABLE.toString()); }
627      *
628      * String ret = switchManager.removeSpanConfig(config.getValue()); if
629      * (ret.equals(ReturnString.SUCCESS.toString())) { return
630      * Response.ok().build(); } throw new ResourceNotFoundException(ret); }
631      */
632
633     /**
634      * Save the current switch configurations
635      *
636      * @param containerName
637      *            Name of the Container
638      * @return Response as dictated by the HTTP Response Status code
639      */
640     @Path("/{containerName}/switch-config")
641     @POST
642     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
643     @StatusCodes({
644             @ResponseCode(code = 200, condition = "Operation successful"),
645             @ResponseCode(code = 404, condition = "The containerName is not found"),
646             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
647     public Response saveSwitchConfig(
648             @PathParam("containerName") String containerName) {
649
650         if (!isValidContainer(containerName)) {
651             throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
652         }
653         if (!NorthboundUtils.isAuthorized(
654                 getUserName(), containerName, Privilege.WRITE, this)) {
655             throw new UnauthorizedException(
656                     "User is not authorized to perform this operation on container "
657                             + containerName);
658         }
659         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
660         if (switchManager == null) {
661             throw new ServiceUnavailableException("Switch Manager "
662                     + RestMessages.SERVICEUNAVAILABLE.toString());
663         }
664
665         Status ret = switchManager.saveSwitchConfig();
666         if (ret.isSuccess()) {
667             return Response.ok().build();
668         }
669         throw new InternalServerErrorException(ret.getDescription());
670     }
671
672     private Node handleNodeAvailability(String containerName, String nodeType,
673             String nodeId) {
674
675         Node node = Node.fromString(nodeType, nodeId);
676         if (node == null) {
677             throw new ResourceNotFoundException(nodeId + " : "
678                     + RestMessages.NONODE.toString());
679         }
680
681         ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
682                 ISwitchManager.class, containerName, this);
683
684         if (sm == null) {
685             throw new ServiceUnavailableException("Switch Manager "
686                     + RestMessages.SERVICEUNAVAILABLE.toString());
687         }
688
689         if (!sm.getNodes().contains(node)) {
690             throw new ResourceNotFoundException(node.toString() + " : "
691                     + RestMessages.NONODE.toString());
692         }
693         return node;
694     }
695
696     private void handleNodeConnectorAvailability(String containerName,
697             Node node, String nodeConnectorType, String nodeConnectorId) {
698
699         NodeConnector nc = NodeConnector.fromStringNoNode(nodeConnectorType,
700                 nodeConnectorId, node);
701         if (nc == null) {
702             throw new ResourceNotFoundException(nc + " : "
703                     + RestMessages.NORESOURCE.toString());
704         }
705
706         ISwitchManager sm = (ISwitchManager) ServiceHelper.getInstance(
707                 ISwitchManager.class, containerName, this);
708
709         if (sm == null) {
710             throw new ServiceUnavailableException("Switch Manager "
711                     + RestMessages.SERVICEUNAVAILABLE.toString());
712         }
713
714         if (!sm.getNodeConnectors(node).contains(nc)) {
715             throw new ResourceNotFoundException(nc.toString() + " : "
716                     + RestMessages.NORESOURCE.toString());
717         }
718     }
719
720     private boolean isValidContainer(String containerName) {
721         if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
722             return true;
723         }
724         IContainerManager containerManager = (IContainerManager) ServiceHelper
725                 .getGlobalInstance(IContainerManager.class, this);
726         if (containerManager == null) {
727             throw new InternalServerErrorException(
728                     RestMessages.INTERNALERROR.toString());
729         }
730         if (containerManager.getContainerNames().contains(containerName)) {
731             return true;
732        }
733         return false;
734     }
735
736 }