Log all configuration(add/modify/delete) changes to a new log file audit.log
[controller.git] / opendaylight / northbound / switchmanager / src / main / java / org / opendaylight / controller / switchmanager / northbound / SwitchNorthbound.java
index 7bdd3f322b4ab5d85dceb896f0d19dbca772f20f..e67d1b75686934b48fb15cb409bf0cdf5cd3d123 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.switchmanager.northbound;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -33,25 +34,25 @@ import org.codehaus.enunciate.jaxrs.TypeHint;
 import org.opendaylight.controller.containermanager.IContainerManager;
 import org.opendaylight.controller.northbound.commons.RestMessages;
 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
-import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
-import org.opendaylight.controller.sal.core.MacAddress;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.core.Property;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.controller.switchmanager.SwitchConfig;
 
 /**
  * The class provides Northbound REST APIs to access the nodes, node connectors
  * and their properties.
- * 
+ *
  */
 
 @Path("/")
@@ -102,9 +103,9 @@ public class SwitchNorthbound {
     }
 
     /**
-     * 
+     *
      * Retrieve a list of all the nodes and their properties in the network
-     * 
+     *
      * @param containerName
      *            The container for which we want to retrieve the list
      * @return A list of Pair each pair represents a
@@ -122,6 +123,10 @@ public class SwitchNorthbound {
             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public Nodes getNodes(@PathParam("containerName") String containerName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
+
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException(
@@ -129,7 +134,7 @@ public class SwitchNorthbound {
                             + containerName);
         }
 
-        ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
@@ -141,7 +146,6 @@ public class SwitchNorthbound {
             return null;
         }
 
-        byte[] controllerMac = switchManager.getControllerMAC();
         for (Node node : nodes) {
             Map<String, Property> propMap = switchManager.getNodeProps(node);
             if (propMap == null) {
@@ -149,10 +153,6 @@ public class SwitchNorthbound {
             }
             Set<Property> props = new HashSet<Property>(propMap.values());
 
-            byte[] nodeMac = switchManager.getNodeMAC(node);
-            Property macAddr = new MacAddress(controllerMac, nodeMac);
-            props.add(macAddr);
-
             NodeProperties nodeProps = new NodeProperties(node, props);
             res.add(nodeProps);
         }
@@ -161,8 +161,14 @@ public class SwitchNorthbound {
     }
 
     /**
-     * Add a Name/Tier property to a node
-     * 
+     * Add a Name, Tier and Forwarding mode property to a node.
+     *
+     * <pre>
+     * Example Request:
+     *  http://localhost:8080/controller/nb/v2/switch/red/node/OF/00:00:00:00:00:03/property/description/Switch3
+     *  (Valid properties that can be configured are: description, forwarding(only for default container) and tier)
+     * </pre>
+     *
      * @param containerName
      *            Name of the Container
      * @param nodeType
@@ -187,7 +193,10 @@ public class SwitchNorthbound {
     @TypeHint(Response.class)
     @StatusCodes({
             @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
+            @ResponseCode(code = 404, condition = "The Container Name or node or configuration name is not found"),
+            @ResponseCode(code = 406, condition = "The property cannot be configured in non-default container"),
+            @ResponseCode(code = 409, condition = "Unable to update configuration due to cluster conflict"),
             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
     public Response addNodeProperty(
             @PathParam("containerName") String containerName,
@@ -196,36 +205,44 @@ public class SwitchNorthbound {
             @PathParam("propName") String propName,
             @PathParam("propValue") String propValue) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
                     "User is not authorized to perform this operation on container "
                             + containerName);
         }
-        handleDefaultDisabled(containerName);
-
-        ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
         }
 
         handleNodeAvailability(containerName, nodeType, nodeId);
-        Node node = Node.fromString(nodeId);
-
+        Node node = Node.fromString(nodeType, nodeId);
         Property prop = switchManager.createProperty(propName, propValue);
         if (prop == null) {
-            throw new ResourceNotFoundException(
-                    RestMessages.INVALIDDATA.toString());
-        }
-
-        switchManager.setNodeProp(node, prop);
-        return Response.status(Response.Status.CREATED).build();
+            throw new ResourceNotFoundException("Property with name " + propName + " does not exist.");
+        }
+        SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
+        Map<String, Property> nodeProperties = (switchConfig == null) ? new HashMap<String, Property>()
+                : new HashMap<String, Property>(switchConfig.getNodeProperties());
+        nodeProperties.put(prop.getName(), prop);
+        SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
+        Status status = switchManager.updateNodeConfig(newSwitchConfig);
+        return NorthboundUtils.getResponse(status);
     }
 
     /**
      * Delete a property of a node
-     * 
+     *
+     * <pre>
+     * Example Request:
+     *  http://localhost:8080/controller/nb/v2/switch/default/node/OF/00:00:00:00:00:03/property/forwarding
+     * </pre>
+     *
      * @param containerName
      *            Name of the Container
      * @param nodeType
@@ -245,7 +262,9 @@ public class SwitchNorthbound {
     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @StatusCodes({
             @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 409, condition = "Unable to delete property due to cluster conflict"),
             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
     public Response deleteNodeProperty(
             @PathParam("containerName") String containerName,
@@ -253,35 +272,50 @@ public class SwitchNorthbound {
             @PathParam("nodeId") String nodeId,
             @PathParam("propertyName") String propertyName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
                     "User is not authorized to perform this operation on container "
                             + containerName);
         }
-        handleDefaultDisabled(containerName);
-
-        ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
         }
 
         handleNodeAvailability(containerName, nodeType, nodeId);
-        Node node = Node.fromString(nodeId);
+        Node node = Node.fromString(nodeType, nodeId);
 
-        Status ret = switchManager.removeNodeProp(node, propertyName);
-        if (ret.isSuccess()) {
-            return Response.ok().build();
+        SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
+        Status status;
+        if (switchConfig == null) {
+            status = new Status(StatusCode.NOTFOUND, "Switch Configuration does not exist");
+        } else {
+            Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
+            if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
+                String msg = "Property " + propertyName + " does not exist or not configured for switch " + nodeId;
+                status = new Status(StatusCode.NOTFOUND, msg);
+            } else {
+                nodeProperties.remove(propertyName.toLowerCase());
+                SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
+                status = switchManager.updateNodeConfig(newSwitchConfig);
+                if(status.isSuccess()){
+                    NorthboundUtils.auditlog("Static Route", username, "updated", nodeId, containerName);
+                }
+            }
         }
-        throw new ResourceNotFoundException(ret.getDescription());
+        return NorthboundUtils.getResponse(status);
     }
 
     /**
-     * 
+     *
      * Retrieve a list of all the node connectors and their properties in a
      * given node
-     * 
+     *
      * @param containerName
      *            The container for which we want to retrieve the list
      * @param nodeType
@@ -308,6 +342,9 @@ public class SwitchNorthbound {
             @PathParam("nodeType") String nodeType,
             @PathParam("nodeId") String nodeId) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException(
@@ -315,15 +352,14 @@ public class SwitchNorthbound {
                             + containerName);
         }
 
-        ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
         }
 
         handleNodeAvailability(containerName, nodeType, nodeId);
-        Node node = Node.fromString(nodeId);
-
+        Node node = Node.fromString(nodeType, nodeId);
         List<NodeConnectorProperties> res = new ArrayList<NodeConnectorProperties>();
         Set<NodeConnector> ncs = switchManager.getNodeConnectors(node);
         if (ncs == null) {
@@ -347,7 +383,7 @@ public class SwitchNorthbound {
 
     /**
      * Add a Name/Bandwidth property to a node connector
-     * 
+     *
      * @param containerName
      *            Name of the Container
      * @param nodeType
@@ -387,6 +423,9 @@ public class SwitchNorthbound {
             @PathParam("propName") String propName,
             @PathParam("propValue") String propValue) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
@@ -394,21 +433,19 @@ public class SwitchNorthbound {
                             + containerName);
         }
 
-        handleDefaultDisabled(containerName);
-
-        ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
         }
 
         handleNodeAvailability(containerName, nodeType, nodeId);
-        Node node = Node.fromString(nodeId);
+        Node node = Node.fromString(nodeType, nodeId);
 
         handleNodeConnectorAvailability(containerName, node, nodeConnectorType,
                 nodeConnectorId);
         NodeConnector nc = NodeConnector
-                .fromStringNoNode(nodeConnectorId, node);
+                .fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
 
         Property prop = switchManager.createProperty(propName, propValue);
         if (prop == null) {
@@ -425,7 +462,7 @@ public class SwitchNorthbound {
 
     /**
      * Delete a property of a node connector
-     * 
+     *
      * @param containerName
      *            Name of the Container
      * @param nodeType
@@ -460,6 +497,9 @@ public class SwitchNorthbound {
             @PathParam("nodeConnectorId") String nodeConnectorId,
             @PathParam("propertyName") String propertyName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
@@ -467,24 +507,22 @@ public class SwitchNorthbound {
                             + containerName);
         }
 
-        handleDefaultDisabled(containerName);
-
-        ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
         }
 
         handleNodeAvailability(containerName, nodeType, nodeId);
-        Node node = Node.fromString(nodeId);
+        Node node = Node.fromString(nodeType, nodeId);
 
         handleNodeConnectorAvailability(containerName, node, nodeConnectorType,
                 nodeConnectorId);
         NodeConnector nc = NodeConnector
-                .fromStringNoNode(nodeConnectorId, node);
-
+                .fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
         Status ret = switchManager.removeNodeConnectorProp(nc, propertyName);
         if (ret.isSuccess()) {
+            NorthboundUtils.auditlog("Node Connector Property", username, "removed", nc + " from " + nodeConnectorId, containerName);
             return Response.ok().build();
         }
         throw new ResourceNotFoundException(ret.getDescription());
@@ -492,7 +530,7 @@ public class SwitchNorthbound {
 
     /*    *//**
      * Retrieve a list of Span ports that were configured previously.
-     * 
+     *
      * @param containerName
      *            Name of the Container
      * @return list of
@@ -501,17 +539,17 @@ public class SwitchNorthbound {
      */
     /*
      * @Path("/span-config/{containerName}")
-     * 
+     *
      * @GET
-     * 
+     *
      * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-     * 
+     *
      * @StatusCodes( {
-     * 
+     *
      * @ResponseCode(code = 200, condition = "Operation successful"),
-     * 
+     *
      * @ResponseCode(code = 404, condition = "The containerName is not found"),
-     * 
+     *
      * @ResponseCode(code = 503, condition =
      * "One or more of Controller Services are unavailable") }) public
      * List<SpanConfig> getSpanConfigList(@PathParam("containerName") String
@@ -519,11 +557,11 @@ public class SwitchNorthbound {
      * getIfSwitchManagerService(containerName); if (switchManager == null) {
      * throw new ServiceUnavailableException("Switch Manager " +
      * RestMessages.SERVICEUNAVAILABLE.toString()); }
-     * 
+     *
      * return switchManager.getSpanConfigList(); }
      *//**
      * Add a span configuration
-     * 
+     *
      * @param containerName
      *            Name of the Container
      * @param config
@@ -533,34 +571,34 @@ public class SwitchNorthbound {
      */
     /*
      * @Path("/span-config/{containerName}")
-     * 
+     *
      * @PUT
-     * 
+     *
      * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-     * 
+     *
      * @StatusCodes( {
-     * 
+     *
      * @ResponseCode(code = 200, condition = "Operation successful"),
-     * 
+     *
      * @ResponseCode(code = 404, condition = "The containerName is not found"),
-     * 
+     *
      * @ResponseCode(code = 503, condition =
      * "One or more of Controller Services are unavailable") }) public Response
      * addSpanConfig(@PathParam("containerName") String containerName,
-     * 
+     *
      * @TypeHint(SubnetConfig.class) JAXBElement<SpanConfig> config) {
      * ISwitchManager switchManager = (ISwitchManager)
      * getIfSwitchManagerService(containerName); if (switchManager == null) {
      * throw new ServiceUnavailableException("Switch Manager " +
      * RestMessages.SERVICEUNAVAILABLE.toString()); }
-     * 
+     *
      * String ret = switchManager.addSpanConfig(config.getValue()); if
      * (ret.equals(ReturnString.SUCCESS.toString())) { return
      * Response.status(Response.Status.CREATED).build(); } throw new
      * InternalServerErrorException(ret); }
      *//**
      * Delete a span configuration
-     * 
+     *
      * @param containerName
      *            Name of the Container
      * @param config
@@ -570,27 +608,27 @@ public class SwitchNorthbound {
      */
     /*
      * @Path("/span-config/{containerName}")
-     * 
+     *
      * @DELETE
-     * 
+     *
      * @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-     * 
+     *
      * @StatusCodes( {
-     * 
+     *
      * @ResponseCode(code = 200, condition = "Operation successful"),
-     * 
+     *
      * @ResponseCode(code = 404, condition = "The containerName is not found"),
-     * 
+     *
      * @ResponseCode(code = 503, condition =
      * "One or more of Controller Services are unavailable") }) public Response
      * deleteSpanConfig(@PathParam("containerName") String containerName,
-     * 
+     *
      * @TypeHint(SubnetConfig.class) JAXBElement<SpanConfig> config) {
      * ISwitchManager switchManager = (ISwitchManager)
      * getIfSwitchManagerService(containerName); if (switchManager == null) {
      * throw new ServiceUnavailableException("Switch Manager " +
      * RestMessages.SERVICEUNAVAILABLE.toString()); }
-     * 
+     *
      * String ret = switchManager.removeSpanConfig(config.getValue()); if
      * (ret.equals(ReturnString.SUCCESS.toString())) { return
      * Response.ok().build(); } throw new ResourceNotFoundException(ret); }
@@ -598,7 +636,7 @@ public class SwitchNorthbound {
 
     /**
      * Save the current switch configurations
-     * 
+     *
      * @param containerName
      *            Name of the Container
      * @return Response as dictated by the HTTP Response Status code
@@ -613,13 +651,16 @@ public class SwitchNorthbound {
     public Response saveSwitchConfig(
             @PathParam("containerName") String containerName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
                     "User is not authorized to perform this operation on container "
                             + containerName);
         }
-        ISwitchManager switchManager = (ISwitchManager) getIfSwitchManagerService(containerName);
+        ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
@@ -632,20 +673,6 @@ public class SwitchNorthbound {
         throw new InternalServerErrorException(ret.getDescription());
     }
 
-    private void handleDefaultDisabled(String containerName) {
-        IContainerManager containerManager = (IContainerManager) ServiceHelper
-                .getGlobalInstance(IContainerManager.class, this);
-        if (containerManager == null) {
-            throw new InternalServerErrorException(
-                    RestMessages.INTERNALERROR.toString());
-        }
-        if (containerName.equals(GlobalConstants.DEFAULT.toString())
-                && containerManager.hasNonDefaultContainer()) {
-            throw new ResourceConflictException(
-                    RestMessages.DEFAULTDISABLED.toString());
-        }
-    }
-
     private Node handleNodeAvailability(String containerName, String nodeType,
             String nodeId) {
 
@@ -694,4 +721,20 @@ public class SwitchNorthbound {
         }
     }
 
+    private boolean isValidContainer(String containerName) {
+        if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
+            return true;
+        }
+        IContainerManager containerManager = (IContainerManager) ServiceHelper
+                .getGlobalInstance(IContainerManager.class, this);
+        if (containerManager == null) {
+            throw new InternalServerErrorException(
+                    RestMessages.INTERNALERROR.toString());
+        }
+        if (containerManager.getContainerNames().contains(containerName)) {
+            return true;
+       }
+        return false;
+    }
+
 }