Merge "Fix for Bug 144"
authorEd Warnicke <eaw@cisco.com>
Thu, 14 Nov 2013 21:21:22 +0000 (21:21 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 14 Nov 2013 21:21:22 +0000 (21:21 +0000)
29 files changed:
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java
opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/MeterConsumerImpl.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend
opendaylight/md-sal/model/model-flow-base/src/main/yang/flow-types.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-service.yang
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/NoficationTest.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToXmlProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/pom.xml [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java [new file with mode: 0644]
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java

index e998bebe27b00be5a9d14291595d9eb573315fde..6277f6a0e6fa6acd28d6aa52dc0fa7c87d7195f5 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.util.jolokia;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -144,7 +145,13 @@ abstract class ListableJolokiaClient {
         J4pResponse<J4pListRequest> response = execute(req);
         JSONObject listJSONResponse = response.getValue();
         JSONObject attributes = (JSONObject) listJSONResponse.get("attr");
-        Map<String, JSONObject> listMap = new HashMap<String, JSONObject>();
+
+        // Empty attributes list
+        if(attributes == null)
+            return Collections.emptyMap();
+
+        Map<String, JSONObject> listMap = new HashMap<>();
+
         for (Object entryObject : attributes.entrySet()) {
             Entry<String, Object> entry = (Entry<String, Object>) entryObject;
             JSONObject entryVal = (JSONObject) entry.getValue();
index dcf119930b782af8eb4004f162410932acc897c5..11f2305b10b4d51cc93e6cc2455ebe2bf6ecfd1f 100644 (file)
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Import-Package>
-              org.opendaylight.controller.sal.binding.api,
-              org.opendaylight.controller.sal.binding.api.data,
-              org.opendaylight.controller.md.sal.common.api.data, 
-              org.opendaylight.controller.sal.utils, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket,
-              org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
-              org.opendaylight.controller.clustering.services, org.opendaylight.controller.sal.core, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction,
-              org.opendaylight.controller.switchmanager, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024,
-              org.opendaylight.yangtools.concepts,              
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819,
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819,
-              org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes,
-              org.opendaylight.controller.sal.common.util, 
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows, 
-              org.opendaylight.yangtools.yang.common,
-              org.opendaylight.yangtools.yang.binding,
-              org.apache.commons.lang3.builder,
-              org.apache.commons.lang3.tuple,
-              org.apache.felix.dm,
-              org.slf4j,
-              org.eclipse.osgi.framework.console,
-              org.osgi.framework,
-              javax.net.ssl
-            </Import-Package>
-            
-           
             <Embed-Transitive>
               false
             </Embed-Transitive>
     <dependency>
       <groupId>equinoxSDK381</groupId>
       <artifactId>org.eclipse.osgi</artifactId>
-    </dependency>    
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-api</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flow-management-compatibility</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
     <dependency>
-         <groupId>org.opendaylight.controller</groupId>
-               <artifactId>sal-binding-api</artifactId>
-               <version>1.0-SNAPSHOT</version>
-       </dependency>           
-       <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-service</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
-   <dependency>
+    <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-flow-management</artifactId>
       <version>1.0-SNAPSHOT</version>
       <version>1.0-SNAPSHOT</version>
       <scope>provided</scope>
     </dependency>
-     <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>clustering.services</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
-    </dependency>    
-     <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
-    </dependency>
   </dependencies>
 </project>
index e48e03867c89025fc62babeab7548a8947a27712..e26e98e4d79601b0a6ac811391caa2c7ce8092aa 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2013 Ericsson , Inc. and others.  All rights reserved.
  *
@@ -9,7 +8,6 @@
 
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
-
 import org.eclipse.osgi.framework.console.CommandProvider;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
@@ -19,90 +17,74 @@ import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.core.IContainer;
 import org.opendaylight.controller.sal.utils.ServiceHelper;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
-public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider{
-       protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class);
-       private static ProviderContext p_session;
-    private static DataBrokerService dataBrokerService;         
-    private static NotificationService notificationService;    
+public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider {
+    protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class);
+    private static ProviderContext p_session;
+    private static DataBrokerService dataBrokerService;
+    private static NotificationService notificationService;
     private FlowConsumerImpl flowImplRef;
-       private GroupConsumerImpl groupImplRef;
-       private static DataProviderService dataProviderService;  
+    private GroupConsumerImpl groupImplRef;
+    private static DataProviderService dataProviderService;
 
        private static IClusterContainerServices clusterContainerService = null;
-       private static ISwitchManager switchManager;
        private static IContainer container;
        
        @Override
     public void onSessionInitiated(ProviderContext session) {
-       
+
         FRMConsumerImpl.p_session = session;
-        
+
         if (!getDependentModule()) {
             logger.error("Unable to fetch handlers for dependent modules");
             System.out.println("Unable to fetch handlers for dependent modules");
             return;
         }
-        
+
         if (null != session) {
-               notificationService = session.getSALService(NotificationService.class);
-               
-               if (null != notificationService) {
-                       dataBrokerService = session.getSALService(DataBrokerService.class);
-                       
-                       if (null != dataBrokerService) {
-                               dataProviderService = session.getSALService(DataProviderService.class);
-                               
-                               if (null != dataProviderService) {
-                                       flowImplRef = new FlowConsumerImpl();
-                       //              groupImplRef = new GroupConsumerImpl();
-                                       registerWithOSGIConsole();
-                               }
-                               else {
-                                       logger.error("Data Provider Service is down or NULL. " +
-                                                       "Accessing data from configuration data store will not be possible");
-                       System.out.println("Data Broker Service is down or NULL.");
-                               }
-                                       
-                       }
-                       else {
-                               logger.error("Data Broker Service is down or NULL.");
-                       System.out.println("Data Broker Service is down or NULL.");
-                       }
-               }
-               else {
-                       logger.error("Notification Service is down or NULL.");
-               System.out.println("Notification Service is down or NULL.");
-               }                       
+            notificationService = session.getSALService(NotificationService.class);
+
+            if (null != notificationService) {
+                dataBrokerService = session.getSALService(DataBrokerService.class);
+
+                if (null != dataBrokerService) {
+                    dataProviderService = session.getSALService(DataProviderService.class);
+
+                    if (null != dataProviderService) {
+                        flowImplRef = new FlowConsumerImpl();
+                        // groupImplRef = new GroupConsumerImpl();
+                        registerWithOSGIConsole();
+                    } else {
+                        logger.error("Data Provider Service is down or NULL. "
+                                + "Accessing data from configuration data store will not be possible");
+                        System.out.println("Data Broker Service is down or NULL.");
+                    }
+
+                } else {
+                    logger.error("Data Broker Service is down or NULL.");
+                    System.out.println("Data Broker Service is down or NULL.");
+                }
+            } else {
+                logger.error("Notification Service is down or NULL.");
+                System.out.println("Notification Service is down or NULL.");
+            }
+        } else {
+            logger.error("Consumer session is NULL. Please check if provider is registered");
+            System.out.println("Consumer session is NULL. Please check if provider is registered");
         }
-        else {
-               logger.error("Consumer session is NULL. Please check if provider is registered");
-               System.out.println("Consumer session is NULL. Please check if provider is registered");
-        }
-  
-    }
-       
-       public static IClusterContainerServices getClusterContainerService() {
-        return clusterContainerService;
-    }
 
-    public static void setClusterContainerService(
-            IClusterContainerServices clusterContainerService) {
-        FRMConsumerImpl.clusterContainerService = clusterContainerService;
     }
 
-    public static ISwitchManager getSwitchManager() {
-        return switchManager;
+    public static IClusterContainerServices getClusterContainerService() {
+        return clusterContainerService;
     }
 
-    public static void setSwitchManager(ISwitchManager switchManager) {
-        FRMConsumerImpl.switchManager = switchManager;
+    public static void setClusterContainerService(IClusterContainerServices clusterContainerService) {
+        FRMConsumerImpl.clusterContainerService = clusterContainerService;
     }
 
     public static IContainer getContainer() {
@@ -141,45 +123,38 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider implements Com
         }
            } while (container == null);
            
-           do {
-               switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, container.getName(), this);
-               try {
-                   Thread.sleep(5);
-               } catch (InterruptedException e) {
-                   // TODO Auto-generated catch block
-                   e.printStackTrace();
-               }
-           } while(null == switchManager);
+          
         return true;
        }
 
        
 
     public static DataProviderService getDataProviderService() {
-               return dataProviderService;
-       }
+        return dataProviderService;
+    }
 
-       public FlowConsumerImpl getFlowImplRef() {
-           return flowImplRef;
-       }
+    public FlowConsumerImpl getFlowImplRef() {
+        return flowImplRef;
+    }
 
-       public GroupConsumerImpl getGroupImplRef() {
-           return groupImplRef;
-       }
-        
-       public static ProviderContext getProviderSession() {
-               return p_session;
-       }       
+    public GroupConsumerImpl getGroupImplRef() {
+       return groupImplRef;
+    }
+               
 
-       public static NotificationService getNotificationService() {
-               return notificationService;
-       }
+    public static ProviderContext getProviderSession() {
+        return p_session;
+    }
 
-       public static DataBrokerService getDataBrokerService() {
-               return dataBrokerService;
-       }
-       
-       /*
+    public static NotificationService getNotificationService() {
+        return notificationService;
+    }
+
+    public static DataBrokerService getDataBrokerService() {
+        return dataBrokerService;
+    }
+
+    /*
      * OSGI COMMANDS
      */
     @Override
@@ -189,4 +164,3 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider implements Com
     }
 
 }
-       
index df34d19b23f8b218802d5d72606540c981f35f6f..4acaf7b26e8179e2152b01e8b0ffcdfc6b329cf3 100644 (file)
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket.Actions;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.opendaylight.controller.sal.utils.IPProtocols;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 
 public class FRMUtil {
+    protected static final Logger logger = LoggerFactory.getLogger(FRMUtil.class);
     private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
-    public enum operation {ADD, DELETE, UPDATE, GET};
-    
-    
+
+    public static enum operation {
+        ADD, DELETE, UPDATE, GET
+    };
+
     public static boolean isNameValid(String name) {
-    
-        //  Name validation 
+
+        // Name validation
         if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
             return false;
         }
         return true;
-        
+
+    }
+
+    public static boolean validateMatch(NodeFlow flow) {
+        Match match = flow.getMatch();
+        if (match != null) {
+            EthernetMatch ethernetmatch = match.getEthernetMatch();
+            IpMatch ipmatch = match.getIpMatch();
+            VlanMatch vlanmatch = match.getVlanMatch();
+            match.getIcmpv4Match();
+
+            if (ethernetmatch != null) {
+                if ((ethernetmatch.getEthernetSource() != null)
+                        && !isL2AddressValid(ethernetmatch.getEthernetSource().toString())) {
+
+                    logger.error("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
+                            ethernetmatch.getEthernetSource());
+                    return false;
+                }
+
+                if ((ethernetmatch.getEthernetDestination() != null)
+                        && !isL2AddressValid(ethernetmatch.getEthernetDestination().toString())) {
+                    logger.error("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
+                            ethernetmatch.getEthernetDestination());
+                    return false;
+                }
+
+                if (ethernetmatch.getEthernetType() != null) {
+                    int type = Integer.decode(ethernetmatch.getEthernetType().toString());
+                    if ((type < 0) || (type > 0xffff)) {
+                        logger.error("Ethernet type is not valid");
+                        return false;
+                    }
+                }
+            } else if (ipmatch != null) {
+                if (ipmatch.getIpProtocol() != null && isProtocolValid(ipmatch.getIpProtocol().toString())) {
+                    logger.error("Protocol is not valid");
+                    return false;
+                }
+            } else if (vlanmatch != null) {
+                if (vlanmatch.getVlanId() != null && isVlanIdValid(vlanmatch.getVlanId().toString())) {
+                    logger.error("Vlan ID is not in the range 0 - 4095");
+                    return false;
+                }
+
+                if (vlanmatch.getVlanPcp() != null && isVlanPriorityValid(vlanmatch.getVlanPcp().toString())) {
+                    logger.error("Vlan priority is not in the range 0 - 7");
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    public static boolean validateActions(List<Action> actions) {
+
+        if (actions == null || actions.isEmpty()) {
+            logger.error("Actions value is null or empty");
+            return false;
+        }
+
+        for (Action curaction : actions) {
+            org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action = curaction
+                    .getAction();
+            if (action instanceof ControllerAction) {
+                Integer length = ((ControllerAction) action).getMaxLength();
+                if (length < 0 || length > 65294) {
+                    logger.error("Controller: MaxLength is not valid");
+                    return false;
+                }
+            } else if (action instanceof OutputAction) {
+                Integer length = ((OutputAction) action).getMaxLength();
+                List<Uri> outputnodeconnector = ((OutputAction) action).getOutputNodeConnector();
+                if (length < 0 || length > 65294) {
+                    logger.error("OutputAction: MaxLength is not valid");
+                    return false;
+                }
+                if (outputnodeconnector != null) {
+                    // TODO
+                }
+            } else if (action instanceof PushMplsAction) {
+                Integer ethertype = ((PushMplsAction) action).getEthernetType();
+                if (ethertype != null && ethertype != 0x8847 && ethertype != 0x8848) {
+                    logger.error("Ether Type is not valid for PushMplsAction");
+                    return false;
+                }
+            } else if (action instanceof PushPbbAction) {
+                Integer ethertype = ((PushPbbAction) action).getEthernetType();
+                if (ethertype != null && ethertype != 0x88E7) {
+                    logger.error("Ether type is not valid for PushPbbAction");
+                    return false;
+                }
+            } else if (action instanceof PushVlanAction) {
+                Integer ethertype = ((PushVlanAction) action).getEthernetType();
+                if (ethertype != null && ethertype != 0x8100 && ethertype != 0x88a8) {
+                    logger.error("Ether Type is not valid for PushVlanAction");
+                    return false;
+                }
+            } else if (action instanceof SetDlDstAction || action instanceof SetDlSrcAction) {
+                MacAddress address = ((SetDlDstAction) action).getAddress();
+                if (address != null && !isL2AddressValid(address.toString())) {
+                    logger.error("SetDlDstAction: Address not valid");
+                    return false;
+                }
+            } else if (action instanceof SetDlSrcAction) {
+                MacAddress address = ((SetDlSrcAction) action).getAddress();
+                if (address != null && !isL2AddressValid(address.toString())) {
+                    logger.error("SetDlSrcAction: Address not valid");
+                    return false;
+                }
+            } else if (action instanceof SetQueueAction) {
+                String queue = ((SetQueueAction) action).getQueue();
+                if (queue != null && !isQueueValid(queue)) {
+                    logger.error("Queue Id not valid");
+                    return false;
+                }
+            } else if (action instanceof SetTpDstAction) {
+                PortNumber port = ((SetTpDstAction) action).getPort();
+                if (port != null && !isPortValid(port)) {
+                    logger.error("Port not valid");
+                }
+            } else if (action instanceof SetTpSrcAction) {
+                PortNumber port = ((SetTpSrcAction) action).getPort();
+                if (port != null && !isPortValid(port)) {
+                    logger.error("Port not valid");
+                }
+            } else if (action instanceof SetVlanIdAction) {
+                VlanId vlanid = ((SetVlanIdAction) action).getVlanId();
+                if (vlanid != null && !isVlanIdValid(vlanid.toString())) {
+                    logger.error("Vlan ID %s is not in the range 0 - 4095");
+                    return false;
+                }
+            } else if (action instanceof SetVlanPcpAction) {
+                VlanPcp vlanpcp = ((SetVlanPcpAction) action).getVlanPcp();
+                if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.toString())) {
+                    logger.error("Vlan priority %s is not in the range 0 - 7");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public static boolean validateInstructions(NodeFlow flow) {
+        List<Instruction> instructionsList = new ArrayList<>();
+        Instructions instructions = flow.getInstructions();
+        instructionsList = instructions.getInstruction();
+
+        for (Instruction instruction : instructionsList) {
+            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
+                    .getInstruction();
+            if (curInstruction instanceof GoToTable) {
+
+                Short tableid = ((GoToTable) curInstruction).getTableId();
+                if (tableid < 0) {
+                    logger.error("table id is not valid");
+                    return false;
+                }
+            }
+
+            else if (curInstruction instanceof WriteActions) {
+
+                List<Action> action = ((WriteActions) curInstruction).getAction();
+                validateActions(action);
+
+            }
+
+            else if (curInstruction instanceof ApplyActions) {
+                List<Action> action = ((ApplyActions) curInstruction).getAction();
+                validateActions(action);
+            }
+
+            else if (curInstruction instanceof ClearActions) {
+                List<Action> action = ((ClearActions) curInstruction).getAction();
+                validateActions(action);
+            }
+
+            else if (curInstruction instanceof Meter) {
+
+                String meter = ((Meter) curInstruction).getMeter();
+                if (meter != null && !isValidMeter(meter)) {
+                    logger.error("Meter Id is not valid");
+                    return false;
+                }
+            }
+
+        }
+
+        return true;
+    }
+
+    public static boolean isValidMeter(String meter) {
+        // TODO
+        return true;
+    }
+
+    public static boolean isQueueValid(String queue) {
+        // TODO
+        return true;
     }
-    
-    public static boolean areActionsValid(Actions actions) {
-     //   List<Action> actionList;
-       // Action actionRef;
-      //  if (null != actions && null != actions.getAction()) {
-       //     actionList = actions.getAction();
-            
 
-               
-       // }
-        
+    public static boolean isPortValid(PortNumber port) {
+        // TODO
         return true;
     }
+
+    public static boolean isL2AddressValid(String mac) {
+        if (mac == null) {
+            return false;
+        }
+
+        Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
+        Matcher mm = macPattern.matcher(mac);
+        if (!mm.matches()) {
+            logger.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean isProtocolValid(String protocol) {
+        IPProtocols proto = IPProtocols.fromString(protocol);
+        return (proto != null);
+    }
+
+    public static boolean isVlanIdValid(String vlanId) {
+        int vlan = Integer.decode(vlanId);
+        return ((vlan >= 0) && (vlan < 4096));
+    }
+
+    public static boolean isVlanPriorityValid(String vlanPriority) {
+        int pri = Integer.decode(vlanPriority);
+        return ((pri >= 0) && (pri < 8));
+    }
 }
index 59c7e043de823a83a4f6b0318c2d25650bd4b384..372573853cb0bd600f61fe4e10abd93e9c0f6e17 100644 (file)
@@ -1,40 +1,51 @@
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
 import java.util.ArrayList;
-import java.util.Collection;
+import java.util.EnumSet;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Future;
 
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.IContainer;
+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.Switch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -44,76 +55,126 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class FlowConsumerImpl {
-       protected static final Logger logger = LoggerFactory.getLogger(FlowConsumerImpl.class);
-       private FlowEventListener flowEventListener = new FlowEventListener();
+    protected static final Logger logger = LoggerFactory.getLogger(FlowConsumerImpl.class);
+    private FlowEventListener flowEventListener = new FlowEventListener();
     private Registration<NotificationListener> listener1Reg;
-       private SalFlowService flowService;
-       private FlowDataListener listener;
-       private FlowDataCommitHandler commitHandler;
-       private ConcurrentHashMap<FlowKey, Flow> originalSwView;
-       
-    public FlowConsumerImpl() {        
-               InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Flows.class).toInstance();
-       flowService = FRMConsumerImpl.getProviderSession().getRpcService(SalFlowService.class);
-               
-               if (null == flowService) {
-                       logger.error("Consumer SAL Service is down or NULL. FRM may not function as intended");
-               System.out.println("Consumer SAL Service is down or NULL.");
-               return;
-               }
-               
-               listener = new FlowDataListener();
-               
-               if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) {
-                       logger.error("Failed to listen on flow data modifcation events");
-               System.out.println("Consumer SAL Service is down or NULL.");
-               return;
-               }       
-                       
-               // For switch events
-               listener1Reg = FRMConsumerImpl.getNotificationService().registerNotificationListener(flowEventListener);
-               
-               if (null == listener1Reg) {
-                       logger.error("Listener to listen on flow data modifcation events");
-               System.out.println("Consumer SAL Service is down or NULL.");
-               return;
-               }
-               //addFlowTest();
-               System.out.println("-------------------------------------------------------------------");
-               allocateCaches();
-               commitHandler = new FlowDataCommitHandler();
-               FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
+    private SalFlowService flowService;
+    // private FlowDataListener listener;
+    private FlowDataCommitHandler commitHandler;
+    private static ConcurrentHashMap<FlowKey, Flow> originalSwView;
+    private static ConcurrentMap<FlowKey, Flow> installedSwView;
+    private IClusterContainerServices clusterContainerService = null;
+    private IContainer container;
+    private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+    private static ConcurrentMap<Integer, Flow> staticFlows;
+    private static ConcurrentMap<Integer, Integer> staticFlowsOrdinal;
+    /*
+     * Inactive flow list. This is for the global instance of FRM It will
+     * contain all the flow entries which were installed on the global container
+     * when the first container is created.
+     */
+    private static ConcurrentMap<FlowKey, Flow> inactiveFlows;
+
+    /*
+     * /* Per node indexing
+     */
+    private static ConcurrentMap<Node, List<Flow>> nodeFlows;
+    private boolean inContainerMode; // being used by global instance only
+
+    public FlowConsumerImpl() {
+        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Flows.class).toInstance();
+        flowService = FRMConsumerImpl.getProviderSession().getRpcService(SalFlowService.class);
+
+        if (null == flowService) {
+            logger.error("Consumer SAL Service is down or NULL. FRM may not function as intended");
+            System.out.println("Consumer SAL Service is down or NULL.");
+            return;
+        }
+
+        // listener = new FlowDataListener();
+
+        // if (null ==
+        // FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path,
+        // listener)) {
+        // logger.error("Failed to listen on flow data modifcation events");
+        // System.out.println("Consumer SAL Service is down or NULL.");
+        // return;
+        // }
+
+        // For switch events
+        listener1Reg = FRMConsumerImpl.getNotificationService().registerNotificationListener(flowEventListener);
+
+        if (null == listener1Reg) {
+            logger.error("Listener to listen on flow data modifcation events");
+            System.out.println("Consumer SAL Service is down or NULL.");
+            return;
+        }
+        // addFlowTest();
+        System.out.println("-------------------------------------------------------------------");
+        allocateCaches();
+        commitHandler = new FlowDataCommitHandler();
+        FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
+        clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(
+                IClusterContainerServices.class, this);
+        container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+        /*
+         * If we are not the first cluster node to come up, do not initialize
+         * the static flow entries ordinal
+         */
+        if (staticFlowsOrdinal.size() == 0) {
+            staticFlowsOrdinal.put(0, Integer.valueOf(0));
+        }
     }
-    
+
     private void allocateCaches() {
-       originalSwView = new ConcurrentHashMap<FlowKey, Flow>();
+
+        if (this.clusterContainerService == null) {
+            logger.warn("Un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+
+        try {
+            clusterContainerService.createCache("frm.originalSwView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            clusterContainerService.createCache("frm.installedSwView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            clusterContainerService
+                    .createCache("frm.staticFlows", EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            clusterContainerService.createCache("frm.staticFlowsOrdinal",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            clusterContainerService.createCache("frm.inactiveFlows",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            clusterContainerService.createCache("frm.nodeFlows", EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            clusterContainerService.createCache("frm.groupFlows", EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+        } catch (CacheConfigException cce) {
+            logger.error("CacheConfigException");
+        } catch (CacheExistException cce) {
+            logger.error("CacheExistException");
+        }
     }
-    
-    private void addFlowTest()
-    {
-       try {
-                       NodeRef nodeOne = createNodeRef("foo:node:1");
-                       AddFlowInputBuilder input1 = new AddFlowInputBuilder();
-                       
-                       input1.setNode(nodeOne);
-                       AddFlowInput firstMsg = input1.build();
-                       
-                       if(null != flowService) {
-                               System.out.println(flowService.toString());
-                       }
-                       else
-                       {
-                               System.out.println("ConsumerFlowService is NULL");
-                       }
-                       @SuppressWarnings("unused")
-                       Future<RpcResult<java.lang.Void>> result1 = flowService.addFlow(firstMsg);
-                       
-                       
-               } catch (Exception e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               }
+
+    private void addFlowTest() {
+        try {
+            NodeRef nodeOne = createNodeRef("foo:node:1");
+            AddFlowInputBuilder input1 = new AddFlowInputBuilder();
+
+            input1.setNode(nodeOne);
+            AddFlowInput firstMsg = input1.build();
+
+            if (null != flowService) {
+                System.out.println(flowService.toString());
+            } else {
+                System.out.println("ConsumerFlowService is NULL");
+            }
+            @SuppressWarnings("unused")
+            Future<RpcResult<AddFlowOutput>> result1 = flowService.addFlow(firstMsg);
+
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
     }
+
     /**
      * Adds flow to the southbound plugin and our internal database
      *
@@ -129,44 +190,87 @@ public class FlowConsumerImpl {
         input.setMatch((dataObject).getMatch());
         input.setCookie((dataObject).getCookie());
         input.setInstructions((dataObject).getInstructions());
-        dataObject.getMatch().getLayer3Match()
-        for (int i=0;i<inst.size();i++) {
-            System.out.println("i = "+ i + inst.get(i).getInstruction().toString());
-            System.out.println("i = "+ i + inst.get(i).toString());
+        dataObject.getMatch().getLayer3Match();
+        for (int i = 0; i < inst.size(); i++) {
+            System.out.println("i = " + i + inst.get(i).getInstruction().toString());
+            System.out.println("i = " + i + inst.get(i).toString());
         }
-        
+
         System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
 
+        // updating the staticflow cache
+        Integer ordinal = staticFlowsOrdinal.get(0);
+        staticFlowsOrdinal.put(0, ++ordinal);
+        staticFlows.put(ordinal, (Flow) dataObject);
+
         // We send flow to the sounthbound plugin
         flowService.addFlow(input.build());
+        updateLocalDatabase((NodeFlow) dataObject, true);
     }
-    
+
+    /**
+     * Removes flow to the southbound plugin and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private void removeFlow(InstanceIdentifier<?> path, Flow dataObject) {
+
+        RemoveFlowInputBuilder input = new RemoveFlowInputBuilder();
+        List<Instruction> inst = (dataObject).getInstructions().getInstruction();
+        input.setNode((dataObject).getNode());
+        input.setPriority((dataObject).getPriority());
+        input.setMatch((dataObject).getMatch());
+        input.setCookie((dataObject).getCookie());
+        input.setInstructions((dataObject).getInstructions());
+        dataObject.getMatch().getLayer3Match();
+        for (int i = 0; i < inst.size(); i++) {
+            System.out.println("i = " + i + inst.get(i).getInstruction().toString());
+            System.out.println("i = " + i + inst.get(i).toString());
+        }
+
+        System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
+
+        // updating the staticflow cache
+        Integer ordinal = staticFlowsOrdinal.get(0);
+        staticFlowsOrdinal.put(0, ++ordinal);
+        staticFlows.put(ordinal, dataObject);
+
+        // We send flow to the sounthbound plugin
+        flowService.removeFlow(input.build());
+        updateLocalDatabase((NodeFlow) dataObject, false);
+    }
+
+    @SuppressWarnings("unchecked")
     private void commitToPlugin(internalTransaction transaction) {
-        for(Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+        for (Entry<InstanceIdentifier<?>, Flow> entry : transaction.additions.entrySet()) {
             System.out.println("Coming add cc in FlowDatacommitHandler");
-            addFlow(entry.getKey(),entry.getValue());
+            addFlow(entry.getKey(), entry.getValue());
         }
-        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.updates.entrySet()) {
+        for (@SuppressWarnings("unused")
+        Entry<InstanceIdentifier<?>, Flow> entry : transaction.updates.entrySet()) {
             System.out.println("Coming update cc in FlowDatacommitHandler");
-           // updateFlow(entry.getKey(),entry.getValue());
+            // updateFlow(entry.getKey(),entry.getValue());
         }
-        
-        for(@SuppressWarnings("unused") InstanceIdentifier<?> removal : transaction.removals) {
-           // removeFlow(removal);
+
+        for (Entry<InstanceIdentifier<?>, Flow> entry : transaction.removals.entrySet()) {
+            System.out.println("Coming remove cc in FlowDatacommitHandler");
+            removeFlow(entry.getKey(), entry.getValue());
         }
+
     }
-    
+
     private final class FlowDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
 
-        @SuppressWarnings("unchecked")
-               @Override
-         public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
-             // We should verify transaction
-                System.out.println("Coming in FlowDatacommitHandler");
-             internalTransaction transaction = new internalTransaction(modification);
-             transaction.prepareUpdate();
-             return transaction;
-         }
+        @SuppressWarnings("unchecked")
+        @Override
+        public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+            // We should verify transaction
+            System.out.println("Coming in FlowDatacommitHandler");
+            internalTransaction transaction = new internalTransaction(modification);
+            transaction.prepareUpdate();
+            return transaction;
+        }
     }
 
     private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
@@ -184,17 +288,47 @@ public class FlowConsumerImpl {
 
         Map<InstanceIdentifier<?>, Flow> additions = new HashMap<>();
         Map<InstanceIdentifier<?>, Flow> updates = new HashMap<>();
-        Set<InstanceIdentifier<?>> removals = new HashSet<>();
+        Map<InstanceIdentifier<?>, Flow> removals = new HashMap<>();
 
         /**
          * We create a plan which flows will be added, which will be updated and
          * which will be removed based on our internal state.
-         * 
+         *
          */
         void prepareUpdate() {
 
             Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
             for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+
+                // validating the DataObject
+
+                Status status = validate(container, (NodeFlow) entry);
+                if (!status.isSuccess()) {
+                    logger.warn("Invalid Configuration for flow {}. The failure is {}", entry, status.getDescription());
+                    String error = "Invalid Configuration (" + status.getDescription() + ")";
+                    logger.error(error);
+                    return;
+                }
+                // Presence check
+                if (flowEntryExists((NodeFlow) entry)) {
+                    String error = "Entry with this name on specified table already exists";
+                    logger.warn("Entry with this name on specified table already exists: {}", entry);
+                    logger.error(error);
+                    return;
+                }
+                if (originalSwView.containsKey((FlowKey) entry)) {
+                    logger.warn("Operation Rejected: A flow with same match and priority exists on the target node");
+                    logger.trace("Aborting to install {}", entry);
+                    continue;
+                }
+                if (!FRMUtil.validateMatch((NodeFlow) entry)) {
+                    logger.error("Not a valid Match");
+                    return;
+                }
+                if (!FRMUtil.validateInstructions((NodeFlow) entry)) {
+                    logger.error("Not a valid Instruction");
+                    return;
+                }
                 if (entry.getValue() instanceof Flow) {
                     Flow flow = (Flow) entry.getValue();
                     preparePutEntry(entry.getKey(), flow);
@@ -202,7 +336,15 @@ public class FlowConsumerImpl {
 
             }
 
-            removals = modification.getRemovedConfigurationData();
+            // removals = modification.getRemovedConfigurationData();
+            Set<InstanceIdentifier<?>> removedData = modification.getRemovedConfigurationData();
+            for (InstanceIdentifier<?> removal : removedData) {
+                DataObject value = modification.getOriginalConfigurationData().get(removal);
+                if (value instanceof Flow) {
+                    removals.put(removal, (Flow) value);
+                }
+            }
+
         }
 
         private void preparePutEntry(InstanceIdentifier<?> key, Flow flow) {
@@ -220,93 +362,205 @@ public class FlowConsumerImpl {
 
         /**
          * We are OK to go with execution of plan
-         * 
+         *
          */
         @Override
         public RpcResult<Void> finish() throws IllegalStateException {
-            
+
             commitToPlugin(this);
             // We return true if internal transaction is successful.
-          //  return Rpcs.getRpcResult(true, null, Collections.emptySet());
-               return Rpcs.getRpcResult(true, null, null);
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return Rpcs.getRpcResult(true, null, null);
         }
 
         /**
-         * 
+         *
          * We should rollback our preparation
-         * 
+         *
          */
         @Override
         public RpcResult<Void> rollback() throws IllegalStateException {
             // NOOP - we did not modified any internal state during
             // requestCommit phase
-           // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
             return Rpcs.getRpcResult(true, null, null);
-               
+
+        }
+
+        public Status validate(IContainer container, NodeFlow dataObject) {
+
+            // container validation
+            Switch sw = null;
+            Node node = null;
+            String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
+            ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class,
+                    containerName, this);
+            // flow Name validation
+            if (dataObject.getFlowName() == null || dataObject.getFlowName().trim().isEmpty()
+                    || !dataObject.getFlowName().matches(NAMEREGEX)) {
+                return new Status(StatusCode.BADREQUEST, "Invalid Flow name");
+            }
+            // Node Validation
+            if (dataObject.getNode() == null) {
+                return new Status(StatusCode.BADREQUEST, "Node is null");
+            }
+
+            if (switchManager != null) {
+                for (Switch device : switchManager.getNetworkDevices()) {
+                    node = (Node) device.getNode();
+                    if (device.getNode().equals(dataObject.getNode())) {
+                        sw = device;
+                        break;
+                    }
+                }
+                if (sw == null) {
+                    return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
+                }
+            } else {
+                logger.debug("switchmanager is not set yet");
+            }
+
+            if (dataObject.getPriority() != null) {
+                if (dataObject.getPriority() < 0 || dataObject.getPriority() > 65535) {
+                    return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
+                            dataObject.getPriority()));
+                }
+            }
+
+            return new Status(StatusCode.SUCCESS);
         }
 
+        private boolean flowEntryExists(NodeFlow config) {
+            // Flow name has to be unique on per table id basis
+            for (ConcurrentMap.Entry<FlowKey, Flow> entry : originalSwView.entrySet()) {
+                if (entry.getValue().getFlowName().equals(config.getFlowName())
+                        && entry.getValue().getTableId().equals(config.getTableId())) {
+                    return true;
+                }
+            }
+            return false;
+        }
     }
-    
-       final class FlowEventListener implements SalFlowListener {
-       
+
+    final class FlowEventListener implements SalFlowListener {
+
         List<FlowAdded> addedFlows = new ArrayList<>();
         List<FlowRemoved> removedFlows = new ArrayList<>();
         List<FlowUpdated> updatedFlows = new ArrayList<>();
-       
+
         @Override
         public void onFlowAdded(FlowAdded notification) {
-               System.out.println("added flow..........................");
-        addedFlows.add(notification);
-           }
-       
-           @Override
-           public void onFlowRemoved(FlowRemoved notification) {
-               removedFlows.add(notification);
-           };
-       
-           @Override
-           public void onFlowUpdated(FlowUpdated notification) {
-               updatedFlows.add(notification);
-           }
-       
-       }
-       
-       final class FlowDataListener implements DataChangeListener {
-               private SalFlowService flowService;
-               
-               public FlowDataListener() {
-                       
-               }
-               
-               @Override
-               public void onDataChanged(
-                               DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {                    
-                       System.out.println("Coming in onDataChange..............");
-                       @SuppressWarnings("unchecked")
-                       Collection<DataObject> additions = (Collection<DataObject>) change.getCreatedConfigurationData();
-                       // we can check for getCreated, getDeleted or getUpdated from DataChange Event class
-                       for (DataObject dataObject : additions) {
-                           if (dataObject instanceof NodeFlow) {
-                               NodeRef nodeOne = createNodeRef("foo:node:1");
-                                       // validating the dataObject here                               
-                                   AddFlowInputBuilder input = new AddFlowInputBuilder();
-                                   input.setNode(((NodeFlow) dataObject).getNode());
-                                   input.setNode(nodeOne);
-                                         //  input.setPriority(((NodeFlow) dataObject).getPriority());
-                                       //input.setMatch(((NodeFlow) dataObject).getMatch());
-                                       //input.setFlowTable(((NodeFlow) dataObject).getFlowTable());
-                                       //input.setCookie(((NodeFlow) dataObject).getCookie());
-                                       //input.setAction(((NodeFlow) dataObject).getAction());
-       
-                               @SuppressWarnings("unused")
-                                       Future<RpcResult<java.lang.Void>> result = flowService.addFlow(input.build());
-                   }
-                       }       
-               } 
-       }
-                               
-           
-           
+            System.out.println("added flow..........................");
+            addedFlows.add(notification);
+        }
+
+        @Override
+        public void onFlowRemoved(FlowRemoved notification) {
+            removedFlows.add(notification);
+        };
+
+        @Override
+        public void onFlowUpdated(FlowUpdated notification) {
+            updatedFlows.add(notification);
+        }
+        
+        @Override
+        public void onSwitchFlowRemoved(SwitchFlowRemoved notification) {
+            //TODO
+        };
+
+    }
+
+    // Commented out DataChangeListene - to be used by Stats
+
+    // final class FlowDataListener implements DataChangeListener {
+    // private SalFlowService flowService;
+    //
+    // public FlowDataListener() {
+    //
+    // }
+    //
+    // @Override
+    // public void onDataChanged(
+    // DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    // System.out.println("Coming in onDataChange..............");
+    // @SuppressWarnings("unchecked")
+    // Collection<DataObject> additions = (Collection<DataObject>)
+    // change.getCreatedConfigurationData();
+    // // we can check for getCreated, getDeleted or getUpdated from DataChange
+    // Event class
+    // for (DataObject dataObject : additions) {
+    // if (dataObject instanceof NodeFlow) {
+    // NodeRef nodeOne = createNodeRef("foo:node:1");
+    // // validating the dataObject here
+    // AddFlowInputBuilder input = new AddFlowInputBuilder();
+    // input.setNode(((NodeFlow) dataObject).getNode());
+    // input.setNode(nodeOne);
+    // // input.setPriority(((NodeFlow) dataObject).getPriority());
+    // //input.setMatch(((NodeFlow) dataObject).getMatch());
+    // //input.setFlowTable(((NodeFlow) dataObject).getFlowTable());
+    // //input.setCookie(((NodeFlow) dataObject).getCookie());
+    // //input.setAction(((NodeFlow) dataObject).getAction());
+    //
+    // @SuppressWarnings("unused")
+    // Future<RpcResult<java.lang.Void>> result =
+    // flowService.addFlow(input.build());
+    // }
+    // }
+    // }
+    // }
+
+    private static void updateLocalDatabase(NodeFlow entry, boolean add) {
+
+        updateSwViewes(entry, add);
+
+        updateNodeFlowsDB(entry, add);
+
+    }
+
+    /*
+     * Update the node mapped flows database
+     */
+    private static void updateSwViewes(NodeFlow entry, boolean add) {
+        if (add) {
+            FlowConsumerImpl.originalSwView.put((FlowKey) entry, (Flow) entry);
+            installedSwView.put((FlowKey) entry, (Flow) entry);
+        } else {
+            originalSwView.remove((Flow) entry);
+            installedSwView.remove((FlowKey) entry);
+
+        }
+    }
+
+    /*
+     * Update the node mapped flows database
+     */
+    private static void updateNodeFlowsDB(NodeFlow entry, boolean add) {
+        Node node = (Node) entry.getNode();
+
+        List<Flow> nodeIndeces = nodeFlows.get(node);
+        if (nodeIndeces == null) {
+            if (!add) {
+                return;
+            } else {
+                nodeIndeces = new ArrayList<Flow>();
+            }
+        }
+
+        if (add) {
+            nodeIndeces.add((Flow) entry);
+        } else {
+            nodeIndeces.remove((Flow) entry);
+        }
+
+        // Update cache across cluster
+        if (nodeIndeces.isEmpty()) {
+            nodeFlows.remove(node);
+        } else {
+            nodeFlows.put(node, nodeIndeces);
+        }
+    }
+
     private static NodeRef createNodeRef(String string) {
         NodeKey key = new NodeKey(new NodeId(string));
         InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
@@ -314,7 +568,4 @@ public class FlowConsumerImpl {
 
         return new NodeRef(path);
     }
-           
-       
-
 }
index 73295cc1e79a204575f6ffd72e00c2c7edf018a9..ce8ee5aaf3564c8a9fb9a7a06d8cce61076670ee 100644 (file)
@@ -25,7 +25,6 @@ import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey;
@@ -36,9 +35,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.Gro
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -49,58 +52,59 @@ import org.slf4j.LoggerFactory;
 
 @SuppressWarnings("unused")
 public class GroupConsumerImpl {
-    
+
     protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
     private GroupEventListener groupEventListener = new GroupEventListener();
     private Registration<NotificationListener> groupListener;
-    private SalGroupService groupService;    
+    private SalGroupService groupService;
     private GroupDataCommitHandler commitHandler;
-    
+
     private ConcurrentMap<GroupKey, Group> originalSwGroupView;
     private ConcurrentMap<GroupKey, Group> installedSwGroupView;
-    
+
     private ConcurrentMap<Node, List<Group>> nodeGroups;
     private ConcurrentMap<GroupKey, Group> inactiveGroups;
-    
-    private IClusterContainerServices clusterGroupContainerService = null;   
+
+    private IClusterContainerServices clusterGroupContainerService = null;
     private IContainer container;
-    
+
     public GroupConsumerImpl() {
+        
            InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class).node(Group.class).toInstance();
         groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
-        
-        clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();        
+
+        clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
         container = FRMConsumerImpl.getContainer();
-        
+
         if (!(cacheStartup())) {
             logger.error("Unanle to allocate/retrieve group cache");
             System.out.println("Unable to allocate/retrieve group cache");
         }
-        
+
         if (null == groupService) {
             logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended");
             System.out.println("Consumer SAL Group Service is down or NULL.");
             return;
-        }     
-        
+        }
+
         // For switch events
         groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener);
-        
+
         if (null == groupListener) {
             logger.error("Listener to listen on group data modifcation events");
             System.out.println("Listener to listen on group data modifcation events.");
             return;
-        }       
-        
+        }
+
         commitHandler = new GroupDataCommitHandler();
         FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
-       }
-       
+    }
+
     private boolean allocateGroupCaches() {
         if (this.clusterGroupContainerService == null) {
             logger.warn("Group: Un-initialized clusterGroupContainerService, can't create cache");
             return false;
-        }       
+        }
 
         try {
             clusterGroupContainerService.createCache("frm.originalSwGroupView",
@@ -181,51 +185,49 @@ public class GroupConsumerImpl {
             logger.error("Retrieval of cache(nodeGroup) failed");
             return false;
         }
-        
+
         return true;
     }
-       
+
     private boolean cacheStartup() {
         if (allocateGroupCaches()) {
             if (retrieveGroupCaches()) {
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     public Status validateGroup(Group group, FRMUtil.operation operation) {
         String containerName;
         String groupName;
         Iterator<Bucket> bucketIterator;
         boolean returnResult;
         Buckets groupBuckets;
-        
+
         if (null != group) {
             containerName = group.getContainerName();
-            
+
             if (null == containerName) {
                 containerName = GlobalConstants.DEFAULT.toString();
-            }
-            else if (!FRMUtil.isNameValid(containerName)) {
+            } else if (!FRMUtil.isNameValid(containerName)) {
                 logger.error("Container Name is invalid %s" + containerName);
                 return new Status(StatusCode.BADREQUEST, "Container Name is invalid");
             }
-            
+
             groupName = group.getGroupName();
             if (!FRMUtil.isNameValid(groupName)) {
                 logger.error("Group Name is invalid %s" + groupName);
                 return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
             }
-            
+
             returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
-            
+
             if (FRMUtil.operation.ADD == operation && returnResult) {
                 logger.error("Record with same Group Name exists");
                 return new Status(StatusCode.BADREQUEST, "Group record exists");
-            }
-            else if (!returnResult) {
+            } else if (!returnResult) {
                 logger.error("Group record does not exist");
                 return new Status(StatusCode.BADREQUEST, "Group record does not exist");
             }
@@ -235,30 +237,30 @@ public class GroupConsumerImpl {
                 logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
                 return new Status(StatusCode.BADREQUEST, "Invalid Group type");                
             }
-            
+
             groupBuckets = group.getBuckets();
-                    
+
             if (null != groupBuckets && null != groupBuckets.getBucket()) {
                 bucketIterator = groupBuckets.getBucket().iterator();
-                
+
                 while (bucketIterator.hasNext()) {
-                    if(!(FRMUtil.areActionsValid(bucketIterator.next().getActions()))) {
+                    if (!(FRMUtil.validateActions(bucketIterator.next().getAction()))) {
                         logger.error("Error in action bucket");
                         return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents");
-                    }                                
+                    }
                 }
-            }                
+            }
         }
-        
+
         return new Status(StatusCode.SUCCESS);
-        
+
     }
-    
+
     private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
-        if (! originalSwGroupView.containsKey(key)) {
+        if (!originalSwGroupView.containsKey(key)) {
             return false;
         }
-        
+
         for (ConcurrentMap.Entry<GroupKey, Group> entry : originalSwGroupView.entrySet()) {
             if (entry.getValue().getGroupName().equals(groupName)) {
                 if (entry.getValue().getContainerName().equals(containerName)) {
@@ -269,34 +271,41 @@ public class GroupConsumerImpl {
         return false;
     }
 
-    
     /**
-     * Update Group entries to the southbound plugin/inventory and our internal database
+     * Update Group entries to the southbound plugin/inventory and our internal
+     * database
      *
      * @param path
      * @param dataObject
      */
     private Status updateGroup(InstanceIdentifier<?> path, Group groupUpdateDataObject) {
         GroupKey groupKey = groupUpdateDataObject.getKey();        
+        UpdatedGroupBuilder updateGroupBuilder = null;
+        
         Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE);
         
         if (!groupOperationStatus.isSuccess()) {
             logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
             return groupOperationStatus;
         }
-            
-        originalSwGroupView.remove(groupKey);
-        originalSwGroupView.put(groupKey, groupUpdateDataObject);
+         
+        if (originalSwGroupView.containsKey(groupKey)) {
+            originalSwGroupView.remove(groupKey);
+            originalSwGroupView.put(groupKey, groupUpdateDataObject);
+        }
         
         if (groupUpdateDataObject.isInstall()) {
             UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
+            updateGroupBuilder = new UpdatedGroupBuilder();
+            updateGroupBuilder.fieldsFrom(groupUpdateDataObject);
+            groupData.setUpdatedGroup(updateGroupBuilder.build());
             //TODO how to get original group and modified group. 
             
             if (installedSwGroupView.containsKey(groupKey)) {
                 installedSwGroupView.remove(groupKey);
+                installedSwGroupView.put(groupKey, groupUpdateDataObject);
             }
             
-            installedSwGroupView.put(groupKey, groupUpdateDataObject);
             groupService.updateGroup(groupData.build());
         }
         
@@ -312,25 +321,25 @@ public class GroupConsumerImpl {
     private Status addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
         GroupKey groupKey = groupAddDataObject.getKey();
         Status groupOperationStatus = validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
-        
+
         if (!groupOperationStatus.isSuccess()) {
             logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
             return groupOperationStatus;
         }
-        
+
         originalSwGroupView.put(groupKey, groupAddDataObject);
-        
+
         if (groupAddDataObject.isInstall()) {
             AddGroupInputBuilder groupData = new AddGroupInputBuilder();
             groupData.setBuckets(groupAddDataObject.getBuckets());
             groupData.setContainerName(groupAddDataObject.getContainerName());
             groupData.setGroupId(groupAddDataObject.getGroupId());
             groupData.setGroupType(groupAddDataObject.getGroupType());
-            groupData.setNode(groupAddDataObject.getNode());  
+            groupData.setNode(groupAddDataObject.getNode());
             installedSwGroupView.put(groupKey, groupAddDataObject);
             groupService.addGroup(groupData.build());
         }
-        
+
         return groupOperationStatus;
     }
     
@@ -338,12 +347,15 @@ public class GroupConsumerImpl {
         for(Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
             
             if (!addGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+                transaction.additions.remove(entry.getKey());
                 return Rpcs.getRpcResult(false, null, null);
             }
         }
-        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+        
+        for(Entry<InstanceIdentifier<?>, Group> entry :transaction.updates.entrySet()) {
            
             if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+                transaction.updates.remove(entry.getKey());
                 return Rpcs.getRpcResult(false, null, null);
             }
         }
@@ -351,21 +363,21 @@ public class GroupConsumerImpl {
         for(InstanceIdentifier<?> removal : transaction.removals) {
            // removeFlow(removal);
         }
-        
+
         return Rpcs.getRpcResult(true, null, null);
     }
-    
+
     private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
 
-         @SuppressWarnings("unchecked")
+        @SuppressWarnings("unchecked")
         @Override
-         public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
-             // We should verify transaction
-             System.out.println("Coming in GroupDatacommitHandler");
-             internalTransaction transaction = new internalTransaction(modification);
-             transaction.prepareUpdate();
-             return transaction;
-         }
+        public DataCommitTransaction<InstanceIdentifier<?>, DataObject> requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+            // We should verify transaction
+            System.out.println("Coming in GroupDatacommitHandler");
+            internalTransaction transaction = new internalTransaction(modification);
+            transaction.prepareUpdate();
+            return transaction;
+        }
     }
 
     private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
@@ -388,14 +400,14 @@ public class GroupConsumerImpl {
         /**
          * We create a plan which flows will be added, which will be updated and
          * which will be removed based on our internal state.
-         * 
+         *
          */
         void prepareUpdate() {
 
             Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
             for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
-                if (entry.getValue() instanceof Group) {                    
-                    Group group = (Group) entry.getValue();                    
+                if (entry.getValue() instanceof Group) {
+                    Group group = (Group) entry.getValue();
                     preparePutEntry(entry.getKey(), group);
                 }
 
@@ -405,72 +417,70 @@ public class GroupConsumerImpl {
         }
 
         private void preparePutEntry(InstanceIdentifier<?> key, Group group) {
-            
+
             Group original = originalSwGroupView.get(key);
             if (original != null) {
                 // It is update for us
-                
-                updates.put(key, group);               
+
+                updates.put(key, group);
             } else {
                 // It is addition for us
-                
+
                 additions.put(key, group);
             }
         }
 
         /**
          * We are OK to go with execution of plan
-         * 
+         *
          */
         @Override
         public RpcResult<Void> finish() throws IllegalStateException {
-            
+
             RpcResult<Void> rpcStatus = commitToPlugin(this);
             // We return true if internal transaction is successful.
-          //  return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
             return rpcStatus;
         }
 
         /**
-         * 
+         *
          * We should rollback our preparation
-         * 
+         *
          */
         @Override
         public RpcResult<Void> rollback() throws IllegalStateException {
             // NOOP - we did not modified any internal state during
             // requestCommit phase
-           // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
             return Rpcs.getRpcResult(true, null, null);
-            
+
         }
-        
+
     }
-    
-       
-       final class GroupEventListener implements SalGroupListener {
-           
+
+    final class GroupEventListener implements SalGroupListener {
+
         List<GroupAdded> addedGroups = new ArrayList<>();
         List<GroupRemoved> removedGroups = new ArrayList<>();
         List<GroupUpdated> updatedGroups = new ArrayList<>();
-       
 
         @Override
         public void onGroupAdded(GroupAdded notification) {
             System.out.println("added Group..........................");
-            addedGroups.add(notification);            
+            addedGroups.add(notification);
         }
 
         @Override
         public void onGroupRemoved(GroupRemoved notification) {
             // TODO Auto-generated method stub
-            
+
         }
 
         @Override
         public void onGroupUpdated(GroupUpdated notification) {
             // TODO Auto-generated method stub
-            
-        }    
+
+        }
     }
 }
index 5eb971ed912e56f8f85cafa41962e3494a4b2064..c69b60bb62f91b3cbb866032b5ede29232145120 100644 (file)
@@ -24,7 +24,6 @@ import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.Meters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.meters.MeterKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
@@ -34,6 +33,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.Met
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.BandType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Drop;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemark;
@@ -51,56 +51,54 @@ public class MeterConsumerImpl {
     protected static final Logger logger = LoggerFactory.getLogger(MeterConsumerImpl.class);
     private MeterEventListener meterEventListener = new MeterEventListener();
     private Registration<NotificationListener> meterListener;
-    private SalMeterService meterService;    
+    private SalMeterService meterService;
     private MeterDataCommitHandler commitHandler;
-    
+
     private ConcurrentMap<MeterKey, Meter> originalSwMeterView;
     private ConcurrentMap<MeterKey, Meter> installedSwMeterView;
-    
+
     private ConcurrentMap<Node, List<Meter>> nodeMeters;
     private ConcurrentMap<MeterKey, Meter> inactiveMeters;
-    
-    private IClusterContainerServices clusterMeterContainerService = null; 
+
+    private IClusterContainerServices clusterMeterContainerService = null;
     private IContainer container;
-    
+
     public MeterConsumerImpl() {
         InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Meters.class).node(Meter.class).toInstance();
         meterService = FRMConsumerImpl.getProviderSession().getRpcService(SalMeterService.class);        
         clusterMeterContainerService = FRMConsumerImpl.getClusterContainerService();
-        
+
         container = FRMConsumerImpl.getContainer();
-        
+
         if (!(cacheStartup())) {
             logger.error("Unable to allocate/retrieve meter cache");
             System.out.println("Unable to allocate/retrieve meter cache");
         }
-        
+
         if (null == meterService) {
             logger.error("Consumer SAL Meter Service is down or NULL. FRM may not function as intended");
             System.out.println("Consumer SAL Meter Service is down or NULL.");
             return;
-        } 
-        
+        }
+
         // For switch/plugin events
         meterListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(meterEventListener);
-        
+
         if (null == meterListener) {
             logger.error("Listener to listen on meter data modifcation events");
             System.out.println("Listener to listen on meter data modifcation events.");
             return;
-        }       
-        
+        }
+
         commitHandler = new MeterDataCommitHandler();
         FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
     }
-    
-    
-    
+
     private boolean allocateMeterCaches() {
         if (this.clusterMeterContainerService == null) {
             logger.warn("Meter: Un-initialized clusterMeterContainerService, can't create cache");
             return false;
-        }       
+        }
 
         try {
             clusterMeterContainerService.createCache("frm.originalSwMeterView",
@@ -114,32 +112,36 @@ public class MeterConsumerImpl {
 
             clusterMeterContainerService.createCache("frm.nodeMeters",
                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-            
-//TODO for cluster mode
-           /* clusterMeterContainerService.createCache(WORK_STATUS_CACHE,
-                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
 
-            clusterMeterContainerService.createCache(WORK_ORDER_CACHE,
-                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/
-            
-        } catch (CacheConfigException cce) {            
+            // TODO for cluster mode
+            /*
+             * clusterMeterContainerService.createCache(WORK_STATUS_CACHE,
+             * EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL,
+             * IClusterServices.cacheMode.ASYNC));
+             *
+             * clusterMeterContainerService.createCache(WORK_ORDER_CACHE,
+             * EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL,
+             * IClusterServices.cacheMode.ASYNC));
+             */
+
+        } catch (CacheConfigException cce) {
             logger.error("Meter CacheConfigException");
             return false;
-            
+
         } catch (CacheExistException cce) {
-            logger.error(" Meter CacheExistException");           
+            logger.error(" Meter CacheExistException");
         }
-        
+
         return true;
     }
-    
+
     private void nonClusterMeterObjectCreate() {
         originalSwMeterView = new ConcurrentHashMap<MeterKey, Meter>();
         installedSwMeterView = new ConcurrentHashMap<MeterKey, Meter>();
-        nodeMeters = new ConcurrentHashMap<Node, List<Meter>>();        
+        nodeMeters = new ConcurrentHashMap<Node, List<Meter>>();
         inactiveMeters = new ConcurrentHashMap<MeterKey, Meter>();
     }
-    
+
     @SuppressWarnings({ "unchecked" })
     private boolean retrieveMeterCaches() {
         ConcurrentMap<?, ?> map;
@@ -148,7 +150,7 @@ public class MeterConsumerImpl {
             logger.warn("Meter: un-initialized clusterMeterContainerService, can't retrieve cache");
             nonClusterMeterObjectCreate();
             return false;
-        }       
+        }
 
         map = clusterMeterContainerService.getCache("frm.originalSwMeterView");
         if (map != null) {
@@ -181,34 +183,33 @@ public class MeterConsumerImpl {
             logger.error("Retrieval of cache(nodeMeter) failed");
             return false;
         }
-        
+
         return true;
     }
-    
+
     private boolean cacheStartup() {
         if (allocateMeterCaches()) {
             if (retrieveMeterCaches()) {
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     /**
      * Adds Meter to the southbound plugin and our internal database
      *
      * @param path
      * @param dataObject
      */
-    private Status addMeter(InstanceIdentifier<?> path, Meter meterAddDataObject) {        
+    private Status addMeter(InstanceIdentifier<?> path, Meter meterAddDataObject) {
         MeterKey meterKey = meterAddDataObject.getKey();
-        
-        if (null != meterKey && 
-                validateMeter(meterAddDataObject, FRMUtil.operation.ADD).isSuccess()) {
+
+        if (null != meterKey && validateMeter(meterAddDataObject, FRMUtil.operation.ADD).isSuccess()) {
             if (meterAddDataObject.isInstall()) {
                 AddMeterInputBuilder meterBuilder = new AddMeterInputBuilder();
-                
+
                 meterBuilder.setContainerName(meterAddDataObject.getContainerName());
                 meterBuilder.setFlags(meterAddDataObject.getFlags());
                 meterBuilder.setMeterBandHeaders(meterAddDataObject.getMeterBandHeaders());
@@ -223,41 +224,57 @@ public class MeterConsumerImpl {
         else {
             return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
         }
-      
+
         return new Status(StatusCode.SUCCESS);
     }
-    
+
     /*
      * Update Meter to the southbound plugin and our internal database
      *
      * @param path
+     *
      * @param dataObject
      */
     private Status updateMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {        
         MeterKey meterKey = meterUpdateDataObject.getKey();
+        UpdatedMeterBuilder updateMeterBuilder = null;
+        
         
         if (null != meterKey && 
-                validateMeter(meterUpdateDataObject, FRMUtil.operation.ADD).isSuccess()) {
-            if (meterUpdateDataObject.isInstall()) {
-                UpdateMeterInputBuilder updateMeterBuilder = new UpdateMeterInputBuilder();  
-                
+                validateMeter(meterUpdateDataObject, FRMUtil.operation.UPDATE).isSuccess()) {
+            
+            if (originalSwMeterView.containsKey(meterKey)) {
+                originalSwMeterView.remove(meterKey);
                 originalSwMeterView.put(meterKey, meterUpdateDataObject);
-                meterService.updateMeter(updateMeterBuilder.build());
             }
             
-            originalSwMeterView.put(meterKey, meterUpdateDataObject);            
+            if (meterUpdateDataObject.isInstall()) {
+                UpdateMeterInputBuilder updateMeterInputBuilder = new UpdateMeterInputBuilder(); 
+                updateMeterBuilder = new UpdatedMeterBuilder();
+                updateMeterBuilder.fieldsFrom(meterUpdateDataObject);
+                updateMeterInputBuilder.setUpdatedMeter(updateMeterBuilder.build());
+                
+                if (installedSwMeterView.containsKey(meterKey)) {
+                    installedSwMeterView.remove(meterKey);
+                    installedSwMeterView.put(meterKey, meterUpdateDataObject);
+                }
+                
+                meterService.updateMeter(updateMeterInputBuilder.build());
+            }
+                        
         }
         else {
             return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
         }
-      
+
         return new Status(StatusCode.SUCCESS);
     }
-    
+
     /*
      * Remove Meter to the southbound plugin and our internal database
      *
      * @param path
+     *
      * @param dataObject
      */
     private Status RemoveMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {        
@@ -268,7 +285,7 @@ public class MeterConsumerImpl {
             if (meterUpdateDataObject.isInstall()) {
                 UpdateMeterInputBuilder updateMeterBuilder = new UpdateMeterInputBuilder();                
                 
-                originalSwMeterView.put(meterKey, meterUpdateDataObject);
+                installedSwMeterView.put(meterKey, meterUpdateDataObject);
                 meterService.updateMeter(updateMeterBuilder.build());
             }
             
@@ -277,91 +294,87 @@ public class MeterConsumerImpl {
         else {
             return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
         }
-      
+
         return new Status(StatusCode.SUCCESS);
     }
-    
+
     public Status validateMeter(Meter meter, FRMUtil.operation operation) {
         String containerName;
         String meterName;
         Status returnStatus = null;
         boolean returnResult;
-        
+
         if (null != meter) {
             containerName = meter.getContainerName();
-            
+
             if (null == containerName) {
                 containerName = GlobalConstants.DEFAULT.toString();
-            }
-            else if (!FRMUtil.isNameValid(containerName)) {
+            } else if (!FRMUtil.isNameValid(containerName)) {
                 logger.error("Container Name is invalid %s" + containerName);
                 returnStatus = new Status(StatusCode.BADREQUEST, "Container Name is invalid");
                 return returnStatus;
             }
-            
+
             meterName = meter.getMeterName();
             if (!FRMUtil.isNameValid(meterName)) {
                 logger.error("Meter Name is invalid %s" + meterName);
                 returnStatus = new Status(StatusCode.BADREQUEST, "Meter Name is invalid");
                 return returnStatus;
             }
-            
+
             returnResult = doesMeterEntryExists(meter.getKey(), meterName, containerName);
-            
+
             if (FRMUtil.operation.ADD == operation && returnResult) {
                 logger.error("Record with same Meter Name exists");
                 returnStatus = new Status(StatusCode.BADREQUEST, "Meter record exists");
                 return returnStatus;
-            }
-            else if (!returnResult) {
+            } else if (!returnResult) {
                 logger.error("Group record does not exist");
                 returnStatus = new Status(StatusCode.BADREQUEST, "Meter record does not exist");
                 return returnStatus;
             }
-          
+
             for (int i = 0; i < meter.getMeterBandHeaders().getMeterBandHeader().size(); i++) {
                 if (!meter.getFlags().isMeterBurst()) {
                     if (0 < meter.getMeterBandHeaders().getMeterBandHeader().get(i).getBurstSize()) {
                         logger.error("Burst size should only be associated when Burst FLAG is set");
-                        returnStatus = new Status(StatusCode.BADREQUEST, "Burst size should only be associated when Burst FLAG is set");
+                        returnStatus = new Status(StatusCode.BADREQUEST,
+                                "Burst size should only be associated when Burst FLAG is set");
                         break;
                     }
                 }
             }
-            
+
             if (null != returnStatus && !returnStatus.isSuccess()) {
                 return returnStatus;
-            }
-            else {
+            } else {
                 BandType setBandType = null;
                 DscpRemark dscpRemark = null;
                 for (int i = 0; i < meter.getMeterBandHeaders().getMeterBandHeader().size(); i++) {
                     setBandType = meter.getMeterBandHeaders().getMeterBandHeader().get(i).getBandType();
-                    if ( setBandType instanceof DscpRemark) {   
-                        dscpRemark = (DscpRemark)setBandType;
+                    if (setBandType instanceof DscpRemark) {
+                        dscpRemark = (DscpRemark) setBandType;
                         if (0 > dscpRemark.getRate()) {
-                           
+
                         }
-                    }
-                    else if (setBandType instanceof Drop) {
+                    } else if (setBandType instanceof Drop) {
                         if (0 < dscpRemark.getPercLevel()) {
                             logger.error("Number of drop Precedence level");
-                        }                        
-                    }
-                    else if (setBandType instanceof Experimenter) {
-                        
+                        }
+                    } else if (setBandType instanceof Experimenter) {
+
                     }
-                }                
+                }
             }
         }
         return new Status(StatusCode.SUCCESS);
     }
-    
+
     private boolean doesMeterEntryExists(MeterKey key, String meterName, String containerName) {
-        if (! originalSwMeterView.containsKey(key)) {
+        if (!originalSwMeterView.containsKey(key)) {
             return false;
         }
-        
+
         for (Entry<MeterKey, Meter> entry : originalSwMeterView.entrySet()) {
             if (entry.getValue().getMeterName().equals(meterName)) {
                 if (entry.getValue().getContainerName().equals(containerName)) {
@@ -372,30 +385,31 @@ public class MeterConsumerImpl {
         return false;
     }
 
-    
     private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
-        for(Entry<InstanceIdentifier<?>, Meter> entry :transaction.additions.entrySet()) {
-            
-            if (!addMeter(entry.getKey(),entry.getValue()).isSuccess()) {
+        for (Entry<InstanceIdentifier<?>, Meter> entry : transaction.additions.entrySet()) {
+
+            if (!addMeter(entry.getKey(), entry.getValue()).isSuccess()) {
                 return Rpcs.getRpcResult(false, null, null);
             }
         }
-        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Meter> entry :transaction.updates.entrySet()) {
-           
-            if (!updateMeter(entry.getKey(),entry.getValue()).isSuccess()) {
+        for (@SuppressWarnings("unused")
+        Entry<InstanceIdentifier<?>, Meter> entry : transaction.updates.entrySet()) {
+
+            if (!updateMeter(entry.getKey(), entry.getValue()).isSuccess()) {
                 return Rpcs.getRpcResult(false, null, null);
             }
         }
-        
-        for(InstanceIdentifier<?> removal : transaction.removals) {
-           /* if (!removeMeter(entry.getKey(),entry.getValue()).isSuccess()) {
-                return Rpcs.getRpcResult(false, null, null);
-            }*/
+
+        for (InstanceIdentifier<?> removal : transaction.removals) {
+            /*
+             * if (!removeMeter(entry.getKey(),entry.getValue()).isSuccess()) {
+             * return Rpcs.getRpcResult(false, null, null); }
+             */
         }
-        
+
         return Rpcs.getRpcResult(true, null, null);
     }
-    
+
     private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
 
         private final DataModification<InstanceIdentifier<?>, DataObject> modification;
@@ -416,14 +430,14 @@ public class MeterConsumerImpl {
         /**
          * We create a plan which flows will be added, which will be updated and
          * which will be removed based on our internal state.
-         * 
+         *
          */
         void prepareUpdate() {
 
             Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
             for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
-                if (entry.getValue() instanceof Meter) {                    
-                    Meter Meter = (Meter) entry.getValue();                    
+                if (entry.getValue() instanceof Meter) {
+                    Meter Meter = (Meter) entry.getValue();
                     preparePutEntry(entry.getKey(), Meter);
                 }
 
@@ -433,46 +447,46 @@ public class MeterConsumerImpl {
         }
 
         private void preparePutEntry(InstanceIdentifier<?> key, Meter meter) {
-            
+
             Meter original = originalSwMeterView.get(key);
             if (original != null) {
                 // It is update for us
-                
-                updates.put(key, meter);               
+
+                updates.put(key, meter);
             } else {
                 // It is addition for us
-                
+
                 additions.put(key, meter);
             }
         }
 
         /**
          * We are OK to go with execution of plan
-         * 
+         *
          */
         @Override
         public RpcResult<Void> finish() throws IllegalStateException {
-            
+
             RpcResult<Void> rpcStatus = commitToPlugin(this);
             // We return true if internal transaction is successful.
-          //  return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
             return rpcStatus;
         }
 
         /**
-         * 
+         *
          * We should rollback our preparation
-         * 
+         *
          */
         @Override
         public RpcResult<Void> rollback() throws IllegalStateException {
             // NOOP - we did not modified any internal state during
             // requestCommit phase
-           // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
             return Rpcs.getRpcResult(true, null, null);
-            
+
         }
-        
+
     }
 
     private final class MeterDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
@@ -486,9 +500,9 @@ public class MeterConsumerImpl {
             return transaction;
         }
     }
-    
+
     final class MeterEventListener implements SalMeterListener {
-        
+
         List<MeterAdded> addedMeter = new ArrayList<>();
         List<MeterRemoved> removeMeter = new ArrayList<>();
         List<MeterUpdated> updatedMeter = new ArrayList<>();
@@ -496,19 +510,19 @@ public class MeterConsumerImpl {
         @Override
         public void onMeterAdded(MeterAdded notification) {
             // TODO Auto-generated method stub
-            
+
         }
 
         @Override
         public void onMeterRemoved(MeterRemoved notification) {
             // TODO Auto-generated method stub
-            
+
         }
 
         @Override
         public void onMeterUpdated(MeterUpdated notification) {
             // TODO Auto-generated method stub
-            
-        }    
+
+        }
     }
 }
index 7d9c93908ec8484d502d6ab91d1bd26080c631cb..15f0685819d0921cdf81f730499ac842271cd59e 100644 (file)
@@ -9,6 +9,7 @@ import org.opendaylight.controller.sal.utils.Status
 import org.opendaylight.controller.sal.utils.StatusCode
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
@@ -132,4 +133,8 @@ class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowLi
         // NOOP : Not supported by AD SAL
     }
     
+    override onSwitchFlowRemoved(SwitchFlowRemoved notification) {
+        // NOOP : Not supported by AD SAL
+    }
+    
 }
index 4145977f635c2cb59b2d9564712d087aad6a378b..b5a70ccfe5357a3dec6b91d1ea04aac559a0ec1a 100644 (file)
@@ -69,15 +69,7 @@ module opendaylight-flow-types {
         }
     }
     
-    grouping flow {
-        container match {
-            uses match:match;
-        }
-        
-        container instructions {
-            uses instruction-list;
-        }
-                
+    grouping generic_flow_attributes {
         leaf priority {
             type uint16;
         }
@@ -94,16 +86,28 @@ module opendaylight-flow-types {
             type uint64;
         }
         
+        leaf table_id {
+            type uint8;
+        }
+    }
+    
+    grouping flow {
+        container match {
+            uses match:match;
+        }
+        
+        container instructions {
+            uses instruction-list;
+        }          
+         
+        uses generic_flow_attributes;
+        
         leaf container-name {
             type string; 
         }
         
         leaf cookie_mask {
-            type uint8;
-        }
-        
-        leaf table_id {
-            type uint8;
+            type uint64;
         }
         
         leaf buffer_id {
@@ -118,11 +122,11 @@ module opendaylight-flow-types {
             type uint32;
         }
         
-        leaf flags{
+        leaf flags {
             type flow-mod-flags;
         }
         
-        leaf flow-name{
+        leaf flow-name {
             type string;
         }
         
@@ -173,4 +177,35 @@ module opendaylight-flow-types {
             type yang:counter64;   
         }
     }
+    
+    grouping flow-mod-removed {
+        uses generic_flow_attributes;
+        
+        leaf duration_nsec {
+            type uint32;
+        }
+        
+        leaf duration_sec {
+            type uint32;
+        }
+        
+        leaf idle_timeout {
+            type uint16;
+        }
+        
+        leaf hard_timeout {
+            type uint16;
+        }
+        
+        leaf packet_count {
+            type uint64;
+        }
+        
+        leaf byte_count {
+            type uint64;
+        }
+        container match {
+            uses match:match;
+        }
+    }
 }
\ No newline at end of file
index 5a1b0070777d6afbe672c14ec27209d454761a8f..f8589193d7cba41d76789782619c700243fceae9 100644 (file)
@@ -16,6 +16,17 @@ module sal-flow {
         type instance-identifier;
     }
     
+    grouping node-flow-removed {
+        leaf node {
+            ext:context-reference "inv:node-context";
+            type inv:node-ref;
+        }
+        leaf flow-table {
+            type flow-table-ref;
+        }
+        uses types:flow-mod-removed;
+    }
+    
     grouping node-flow {
         uses "inv:node-context-ref";
 
@@ -78,4 +89,8 @@ module sal-flow {
     notification flow-removed {
         uses node-flow;
     }
+    
+    notification switch-flow-removed {
+        uses node-flow-removed;
+    }
 }
\ No newline at end of file
index 99ce4933b5483a8f2eaccd0c09332ea63b1d2ae8..3198109bc4f0d97268b3a79b559b5182ea4c7996 100644 (file)
@@ -45,6 +45,7 @@
         <module>clustered-data-store/implementation</module>
 
         <module>inventory-manager</module>
+        <module>statistics-manager</module>
         <!-- Compability Packages -->
         <module>compatibility</module>
 
index 851826a3ba100871e639edabb5a7f3dfccb0ed95..1627243267dd5a774cf54f5456c428ff8f09248c 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
 
@@ -191,12 +192,18 @@ public class NoficationTest extends AbstractTest {
         @Override
         public void onFlowRemoved(FlowRemoved notification) {
             removedFlows.add(notification);
-        };
+        }; 
 
         @Override
         public void onFlowUpdated(FlowUpdated notification) {
             updatedFlows.add(notification);
         }
 
+        @Override
+        public void onSwitchFlowRemoved(SwitchFlowRemoved notification) {
+            // TODO Auto-generated method stub
+            
+        }
+
     }
 }
index 04556bbe547a8d22acd9d8584be1ff4386c1ed5f..5a1b42fd8009d074613407088c94359bac5dc6d9 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefi
 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
 
+import com.google.common.base.Preconditions;
 import com.google.gson.stream.JsonWriter;
 
 class JsonMapper {
@@ -34,12 +35,16 @@ class JsonMapper {
     private final Set<ListSchemaNode> foundLists = new HashSet<>();
     
     public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
+        Preconditions.checkNotNull(writer);
+        Preconditions.checkNotNull(data);
+        Preconditions.checkNotNull(schema);
+
         writer.beginObject();
         
         if (schema instanceof ContainerSchemaNode) {
-            writeContainer(writer, (CompositeNode) data, (ContainerSchemaNode) schema);
+            writeContainer(writer, data, (ContainerSchemaNode) schema);
         } else if (schema instanceof ListSchemaNode) {
-            writeList(writer, (CompositeNode) data, (ListSchemaNode) schema);
+            writeList(writer, data, (ListSchemaNode) schema);
         } else {
             throw new UnsupportedDataTypeException(
                     "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
@@ -56,25 +61,33 @@ class JsonMapper {
         checkNotNull(parentSchema);
         
         for (Node<?> child : parent.getChildren()) {
-            DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
+            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
             if (childSchema == null) {
                 throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
                         + "\" is not conform to schema");
             }
             
             if (childSchema instanceof ContainerSchemaNode) {
+                Preconditions.checkState(child instanceof CompositeNode,
+                        "Data representation of Container should be CompositeNode - " + child.getNodeType());
                 writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
             } else if (childSchema instanceof ListSchemaNode) {
                 if (!foundLists.contains(childSchema)) {
+                    Preconditions.checkState(child instanceof CompositeNode,
+                            "Data representation of List should be CompositeNode - " + child.getNodeType());
                     foundLists.add((ListSchemaNode) childSchema);
                     writeList(writer, (CompositeNode) child, (ListSchemaNode) childSchema);
                 }
             } else if (childSchema instanceof LeafListSchemaNode) {
                 if (!foundLeafLists.contains(childSchema)) {
+                    Preconditions.checkState(child instanceof SimpleNode<?>,
+                            "Data representation of LeafList should be SimpleNode - " + child.getNodeType());
                     foundLeafLists.add((LeafListSchemaNode) childSchema);
                     writeLeafList(writer, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
                 }
             } else if (childSchema instanceof LeafSchemaNode) {
+                Preconditions.checkState(child instanceof SimpleNode<?>,
+                        "Data representation of LeafList should be SimpleNode - " + child.getNodeType());
                 writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
             } else {
                 throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, "
@@ -83,7 +96,7 @@ class JsonMapper {
         }
         
         for (Node<?> child : parent.getChildren()) {
-            DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
+            DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
             if (childSchema instanceof LeafListSchemaNode) {
                 foundLeafLists.remove((LeafListSchemaNode) childSchema);
             } else if (childSchema instanceof ListSchemaNode) {
@@ -92,7 +105,7 @@ class JsonMapper {
         }
     }
     
-    private DataSchemaNode findSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
+    private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
         for (DataSchemaNode dsn : dataSchemaNode) {
             if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
                 return dsn;
@@ -169,7 +182,7 @@ class JsonMapper {
             writer.nullValue();
             writer.endArray();
         } else {
-            writer.value(value);
+            writer.value(value != null ? value : "");
         }
     }
     
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java
new file mode 100644 (file)
index 0000000..fa00908
--- /dev/null
@@ -0,0 +1,81 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+
+class JsonReader {
+
+    public CompositeNodeWrapper read(InputStream entityStream) throws UnsupportedJsonFormatException {
+        JsonParser parser = new JsonParser();
+        
+        JsonElement rootElement = parser.parse(new InputStreamReader(entityStream));
+        if (!rootElement.isJsonObject()) {
+            throw new UnsupportedJsonFormatException("Root element of Json has to be Object");
+        }
+        
+        Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
+        if (entrySetsOfRootJsonObject.size() != 1) {
+            throw new UnsupportedJsonFormatException("Json Object should contain one element");
+        } else {
+            Entry<String, JsonElement> childEntry = Lists.newArrayList(entrySetsOfRootJsonObject).get(0);
+            String firstElementName = childEntry.getKey();
+            JsonElement firstElementType = childEntry.getValue();
+            if (firstElementType.isJsonObject()) { // container in yang
+                return createStructureWithRoot(firstElementName, firstElementType.getAsJsonObject());
+            }
+            if (firstElementType.isJsonArray()) { // list in yang
+                if (firstElementType.getAsJsonArray().size() == 1) {
+                    JsonElement firstElementInArray = firstElementType.getAsJsonArray().get(0);
+                    if (firstElementInArray.isJsonObject()) {
+                        return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
+                    }
+                    throw new UnsupportedJsonFormatException("Array as the first element in Json Object can have only Object element");
+                }
+            }
+            throw new UnsupportedJsonFormatException("First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
+        }
+    }
+    
+    private CompositeNodeWrapper createStructureWithRoot(String rootObjectName, JsonObject rootObject) {
+        CompositeNodeWrapper firstNode = new CompositeNodeWrapper(rootObjectName);
+        for (Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
+            addChildToParent(childOfFirstNode.getKey(), childOfFirstNode.getValue(), firstNode);
+        }
+        return firstNode;
+    }
+    
+    private void addChildToParent(String childName, JsonElement childType, CompositeNodeWrapper parent) {
+        if (childType.isJsonObject()) {
+            CompositeNodeWrapper child = new CompositeNodeWrapper(childName);
+            parent.addValue(child);
+            for (Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
+                addChildToParent(childOfChild.getKey(), childOfChild.getValue(), child);
+            }
+        } else if (childType.isJsonArray()) {
+            for (JsonElement childOfChildType : childType.getAsJsonArray()) {
+                addChildToParent(childName, childOfChildType, parent);
+            }
+        } else if (childType.isJsonPrimitive()) {
+            JsonPrimitive childPrimitive = childType.getAsJsonPrimitive();
+            String value = childPrimitive.getAsString();
+            SimpleNodeWrapper child = null;
+            if (value.equals("[null]")) {
+                child = new SimpleNodeWrapper(childName, null);
+            } else {
+                child = new SimpleNodeWrapper(childName, value);
+            }
+            parent.addValue(child);
+        }
+    }
+}
index cc6d449523671cfdca429ea1bb31779726a57b9c..daaedd92b8d6c85f05f26365b90f6bbe68f7d5d6 100644 (file)
@@ -11,6 +11,7 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.Provider;
 
@@ -21,7 +22,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 @Consumes({API+RestconfService.JSON})
 public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
     INSTANCE;
-
+    
     @Override
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return true;
@@ -31,8 +32,13 @@ public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNo
     public CompositeNode readFrom(Class<CompositeNode> type, Type genericType, Annotation[] annotations,
             MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
             throws IOException, WebApplicationException {
-        // TODO Auto-generated method stub
-        return null;
+        JsonReader jsonReader = new JsonReader();
+        try {
+            return jsonReader.read(entityStream);
+        } catch (UnsupportedJsonFormatException e) {
+            throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
+                    .entity(e.getMessage()).build());
+        }
     }
 
 }
index b0e1e03c6c2715c0b99f271619d387f721d39884..4a851a3f6ca531f6042b9d20df7f4d9ba3cd3517 100644 (file)
@@ -12,11 +12,13 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.Provider;
 
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 
 import com.google.gson.stream.JsonWriter;
@@ -40,11 +42,16 @@ public enum StructuredDataToJsonProvider implements MessageBodyWriter<Structured
     public void writeTo(StructuredData t, Class<?> type, Type genericType, Annotation[] annotations,
             MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
             throws IOException, WebApplicationException {
+        CompositeNode data = t.getData();
+        if (data == null) {
+            throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
+        }
+
         JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
         writer.setIndent("    ");
         JsonMapper jsonMapper = new JsonMapper();
-        jsonMapper.write(writer, t.getData(), (DataNodeContainer) t.getSchema());
+        jsonMapper.write(writer, data, (DataNodeContainer) t.getSchema());
         writer.flush();
     }
-    
+
 }
index 0bce2e2ae0f87843e33ccb162da5186a40fd7b33..9f41b571dade2dc5eb806e350a6e229d17598ded 100644 (file)
@@ -51,8 +51,11 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
             MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
             throws IOException, WebApplicationException {
         CompositeNode data = t.getData();
-        Document domTree = NodeUtils.buildShadowDomTree(data);
+        if (data == null) {
+            throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
+        }
         
+        Document domTree = NodeUtils.buildShadowDomTree(data);
         try {
             TransformerFactory tf = TransformerFactory.newInstance();
             Transformer transformer = tf.newTransformer();
@@ -64,7 +67,7 @@ public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredD
             transformer.transform(new DOMSource(domTree), new StreamResult(entityStream));
         } catch (TransformerException e) {
             logger.error("Error during translation of Document to OutputStream", e);
-            new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR).build());
+            throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR).build());
         }
     }
 
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java
new file mode 100644 (file)
index 0000000..dccf29b
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+public class UnsupportedJsonFormatException extends Exception {
+
+    private static final long serialVersionUID = -1741388894406313402L;
+
+    public UnsupportedJsonFormatException() {
+        super();
+    }
+
+    public UnsupportedJsonFormatException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public UnsupportedJsonFormatException(String message) {
+        super(message);
+    }
+
+    public UnsupportedJsonFormatException(Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java
new file mode 100644 (file)
index 0000000..da07bba
--- /dev/null
@@ -0,0 +1,220 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+
+import com.google.common.base.Preconditions;
+
+public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, CompositeNode {
+
+    private MutableCompositeNode compositeNode;
+
+    private String localName;
+    private URI namespace;
+    private List<NodeWrapper<?>> values = new ArrayList<>();
+    
+    public CompositeNodeWrapper(String localName) {
+        this.localName = Preconditions.checkNotNull(localName);
+    }
+
+    @Override
+    public String getLocalName() {
+        if (compositeNode != null) {
+            return compositeNode.getNodeType().getLocalName();
+        }
+        return localName;
+    }
+
+    @Override
+    public URI getNamespace() {
+        if (compositeNode != null) {
+            return compositeNode.getNodeType().getNamespace();
+        }
+        return namespace;
+    }
+
+    @Override
+    public void setNamespace(URI namespace) {
+        Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
+        this.namespace = namespace;
+    }
+
+    public void addValue(NodeWrapper<?> value) {
+        Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
+        values.add(value);
+    }
+
+    public void removeValue(NodeWrapper<CompositeNode> value) {
+        Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
+        values.remove(value);
+    }
+    
+    public List<NodeWrapper<?>> getValues() {
+        Preconditions.checkState(compositeNode == null, "Data can be inconsistent.");
+        return Collections.unmodifiableList(values);
+    }
+
+    @Override
+    public CompositeNode unwrap(CompositeNode parent) {
+        if (compositeNode == null) {
+            Preconditions.checkNotNull(namespace);
+            compositeNode = NodeFactory.createMutableCompositeNode(new QName(namespace, localName), 
+                    parent, new ArrayList<Node<?>>(), ModifyAction.CREATE, null);
+            
+            List<Node<?>> nodeValues = new ArrayList<>();
+            for (NodeWrapper<?> nodeWrapper : values) {
+                nodeValues.add(nodeWrapper.unwrap(compositeNode));
+            }
+            compositeNode.setValue(nodeValues);
+            
+            values = null;
+            namespace = null;
+            localName = null;
+        }
+        return compositeNode;
+    }
+
+    @Override
+    public QName getNodeType() {
+        return unwrap(null).getNodeType();
+    }
+
+    @Override
+    public CompositeNode getParent() {
+        return unwrap(null).getParent();
+    }
+
+    @Override
+    public List<Node<?>> getValue() {
+        return unwrap(null).getValue();
+    }
+
+    @Override
+    public ModifyAction getModificationAction() {
+        return unwrap(null).getModificationAction();
+    }
+
+    @Override
+    public List<Node<?>> getChildren() {
+        return unwrap(null).getChildren();
+    }
+
+    @Override
+    public List<CompositeNode> getCompositesByName(QName children) {
+        return unwrap(null).getCompositesByName(children);
+    }
+
+    @Override
+    public List<CompositeNode> getCompositesByName(String children) {
+        return unwrap(null).getCompositesByName(children);
+    }
+
+    @Override
+    public List<SimpleNode<?>> getSimpleNodesByName(QName children) {
+        return unwrap(null).getSimpleNodesByName(children);
+    }
+
+    @Override
+    public List<SimpleNode<?>> getSimpleNodesByName(String children) {
+        return unwrap(null).getSimpleNodesByName(children);
+    }
+
+    @Override
+    public CompositeNode getFirstCompositeByName(QName container) {
+        return unwrap(null).getFirstCompositeByName(container);
+    }
+
+    @Override
+    public SimpleNode<?> getFirstSimpleByName(QName leaf) {
+        return unwrap(null).getFirstSimpleByName(leaf);
+    }
+
+    @Override
+    public MutableCompositeNode asMutable() {
+        return unwrap(null).asMutable();
+    }
+
+    @Override
+    public QName getKey() {
+        return unwrap(null).getKey();
+    }
+
+    @Override
+    public List<Node<?>> setValue(List<Node<?>> value) {
+        return unwrap(null).setValue(value);
+    }
+
+    @Override
+    public int size() {
+        return unwrap(null).size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return unwrap(null).isEmpty();
+    }
+
+    @Override
+    public boolean containsKey(Object key) {
+        return unwrap(null).containsKey(key);
+    }
+
+    @Override
+    public boolean containsValue(Object value) {
+        return unwrap(null).containsValue(value);
+    }
+
+    @Override
+    public List<Node<?>> get(Object key) {
+        return unwrap(null).get(key);
+    }
+
+    @Override
+    public List<Node<?>> put(QName key, List<Node<?>> value) {
+        return unwrap(null).put(key, value);
+    }
+
+    @Override
+    public List<Node<?>> remove(Object key) {
+        return unwrap(null).remove(key);
+    }
+
+    @Override
+    public void putAll(Map<? extends QName, ? extends List<Node<?>>> m) {
+        unwrap(null).putAll(m);
+    }
+
+    @Override
+    public void clear() {
+        unwrap(null).clear();
+    }
+
+    @Override
+    public Set<QName> keySet() {
+        return unwrap(null).keySet();
+    }
+
+    @Override
+    public Collection<List<Node<?>>> values() {
+        return unwrap(null).values();
+    }
+
+    @Override
+    public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
+        return unwrap(null).entrySet();
+    }
+
+}
index 400850103d7be35f72beeb39088a1618a23feff5..624178569d4e71551507f7733cec7c93bf4b032c 100644 (file)
@@ -294,5 +294,9 @@ class ControllerContext implements SchemaServiceListener {
     def ContainerSchemaNode getRpcOutputSchema(QName name) {
         qnameToRpc.get(name)?.output;
     }
+    
+    def ContainerSchemaNode getRpcInputSchema(QName name) {
+        qnameToRpc.get(name)?.input;
+    }
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NodeWrapper.java
new file mode 100644 (file)
index 0000000..0a3616e
--- /dev/null
@@ -0,0 +1,17 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface NodeWrapper<T extends Node<?>> {
+
+    T unwrap(CompositeNode parent);
+    
+    URI getNamespace();
+
+    void setNamespace(URI namespace);
+    
+    String getLocalName();
+}
\ No newline at end of file
index 31fbe8ec876876b0d677ffaa90df95fddbdfa91a..ea3a4fbcfcbae90e848c39e505008dd701613b26 100644 (file)
@@ -1,7 +1,10 @@
 package org.opendaylight.controller.sal.restconf.impl
 
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import java.util.List
 import org.opendaylight.controller.sal.rest.api.RestconfService
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
 
 class RestconfImpl implements RestconfService {
     
@@ -44,17 +47,20 @@ class RestconfImpl implements RestconfService {
 
     override createConfigurationData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.toInstanceIdentifier
-        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+        val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
     }
 
     override updateConfigurationData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.toInstanceIdentifier
-        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+        val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
     }
 
     override invokeRpc(String identifier, CompositeNode payload) {
         val rpc = identifier.toQName;
-        val rpcResult = broker.invokeRpc(rpc, payload);
+        val value = resolveNodeNamespaceBySchema(payload, controllerContext.getRpcInputSchema(rpc))
+        val rpcResult = broker.invokeRpc(rpc, value);
         val schema = controllerContext.getRpcOutputSchema(rpc);
         return new StructuredData(rpcResult.result, schema);
     }
@@ -81,12 +87,35 @@ class RestconfImpl implements RestconfService {
     
     override createOperationalData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.toInstanceIdentifier
-        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+        val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
     }
     
     override updateOperationalData(String identifier, CompositeNode payload) {
         val identifierWithSchemaNode = identifier.toInstanceIdentifier
-        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+        val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
+    }
+    
+    private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) {
+        if (node instanceof CompositeNodeWrapper) {
+            addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema)
+            return (node as CompositeNodeWrapper).unwrap(null)
+        }
+        return node
+    }
+
+    private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
+        if (nodeBuilder.namespace == null) {
+            nodeBuilder.namespace = schema.QName.namespace
+        }
+        if (nodeBuilder instanceof CompositeNodeWrapper) {
+            val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
+            for (child : children) {
+                addNamespaceToNodeFromSchemaRecursively(child,
+                    (schema as DataNodeContainer).childNodes.findFirst[n|n.QName.localName === child.localName])
+            }
+        }
     }
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/SimpleNodeWrapper.java
new file mode 100644 (file)
index 0000000..50b6ac7
--- /dev/null
@@ -0,0 +1,98 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+
+import com.google.common.base.Preconditions;
+
+public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<String> {
+    
+    private SimpleNode<String> simpleNode;
+    
+    private String localName;
+    private String value;
+    private URI namespace;
+
+    public SimpleNodeWrapper(String localName, String value) {
+        this.localName = Preconditions.checkNotNull(localName);
+        this.value = value;
+    }
+    
+    @Override
+    public String getLocalName() {
+        if (simpleNode != null) {
+            return simpleNode.getNodeType().getLocalName();
+        }
+        return localName;
+    }
+    
+    @Override
+    public URI getNamespace() {
+        if (simpleNode != null) {
+            return simpleNode.getNodeType().getNamespace();
+        }
+        return namespace;
+    }
+
+    @Override
+    public void setNamespace(URI namespace) {
+        Preconditions.checkState(simpleNode == null, "Cannot change the object, due to data inconsistencies.");
+        this.namespace = namespace;
+    }
+
+    @Override
+    public SimpleNode<String> unwrap(CompositeNode parent) {
+        if (simpleNode == null) {
+            Preconditions.checkNotNull(namespace);
+            simpleNode = NodeFactory.createImmutableSimpleNode(new QName(namespace, localName), parent, value);
+            
+            value = null;
+            namespace = null;
+            localName = null;
+        }
+        return simpleNode;
+    }
+
+    @Override
+    public QName getNodeType() {
+        return unwrap(null).getNodeType();
+    }
+
+    @Override
+    public CompositeNode getParent() {
+        return unwrap(null).getParent();
+    }
+
+    @Override
+    public String getValue() {
+        return unwrap(null).getValue();
+    }
+
+    @Override
+    public ModifyAction getModificationAction() {
+        return unwrap(null).getModificationAction();
+    }
+
+    @Override
+    public MutableSimpleNode<String> asMutable() {
+        return unwrap(null).asMutable();
+    }
+
+    @Override
+    public QName getKey() {
+        return unwrap(null).getKey();
+    }
+
+    @Override
+    public String setValue(String value) {
+        return unwrap(null).setValue(value);
+    }
+
+
+}
diff --git a/opendaylight/md-sal/statistics-manager/pom.xml b/opendaylight/md-sal/statistics-manager/pom.xml
new file mode 100644 (file)
index 0000000..3a355d2
--- /dev/null
@@ -0,0 +1,65 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.opendaylight.controller.md</groupId>
+    <artifactId>statistics-manager</artifactId>
+    <packaging>bundle</packaging>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-statistics</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-base</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.controller.md.statistics.manager.StatisticsManagerActivator</Bundle-Activator>
+                        <Private-Package>org.opendaylight.controller.md.statistics.manager</Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsManagerActivator.java
new file mode 100644 (file)
index 0000000..3c5c579
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.osgi.framework.BundleContext;
+
+public class StatisticsManagerActivator extends AbstractBindingAwareProvider {
+
+    private static ProviderContext pSession;
+    
+    private static StatisticsProvider statsProvider = new StatisticsProvider();
+   
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        
+        DataProviderService dps = session.<DataProviderService>getSALService(DataProviderService.class);
+        StatisticsManagerActivator.statsProvider.setDataService(dps);
+        NotificationProviderService nps = session.<NotificationProviderService>getSALService(NotificationProviderService.class);
+        StatisticsManagerActivator.statsProvider.setNotificationService(nps);
+        StatisticsManagerActivator.statsProvider.start();
+
+    }
+    
+    @Override
+    protected void stopImpl(BundleContext context) {
+        StatisticsManagerActivator.statsProvider.close();
+    }
+    
+    public static ProviderContext getProviderContext(){
+        return pSession;
+    }
+
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java
new file mode 100644 (file)
index 0000000..073d43e
--- /dev/null
@@ -0,0 +1,82 @@
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StatisticsProvider implements AutoCloseable {
+
+    public final static Logger spLogger = LoggerFactory.getLogger(StatisticsProvider.class);
+    
+    private DataProviderService dps;
+
+    private NotificationProviderService nps;
+    
+    private OpendaylightGroupStatisticsService groupStatsService;
+    
+    private OpendaylightMeterStatisticsService meterStatsService;
+    
+    public DataProviderService getDataService() {
+      return this.dps;
+    }
+    
+    public void setDataService(final DataProviderService dataService) {
+      this.dps = dataService;
+    }
+    
+    public NotificationProviderService getNotificationService() {
+      return this.nps;
+    }
+    
+    public void setNotificationService(final NotificationProviderService notificationService) {
+      this.nps = notificationService;
+    }
+
+    private final StatisticsUpdateCommiter updateCommiter = new StatisticsUpdateCommiter(StatisticsProvider.this);
+    
+    private Registration<NotificationListener> listenerRegistration;
+    
+    public void start() {
+        
+        NotificationProviderService nps = this.getNotificationService();
+        Registration<NotificationListener> registerNotificationListener = nps.registerNotificationListener(this.updateCommiter);
+        this.listenerRegistration = registerNotificationListener;
+        
+        // Get Group/Meter statistics service instance
+        groupStatsService = StatisticsManagerActivator.getProviderContext().getRpcService(OpendaylightGroupStatisticsService.class);
+        
+        meterStatsService = StatisticsManagerActivator.getProviderContext().getRpcService(OpendaylightMeterStatisticsService.class);
+
+        spLogger.info("Statistics Provider started.");
+    }
+    
+    protected DataModificationTransaction startChange() {
+        
+        DataProviderService dps = this.getDataService();
+        return dps.beginTransaction();
+    }
+    
+    @Override
+    public void close(){
+        
+        try {
+            spLogger.info("Statistics Provider stopped.");
+            if (this.listenerRegistration != null) {
+              
+                this.listenerRegistration.close();
+            
+            }
+          } catch (Throwable e) {
+            throw Exceptions.sneakyThrow(e);
+          }
+
+    }
+
+}
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java
new file mode 100644 (file)
index 0000000..f952124
--- /dev/null
@@ -0,0 +1,57 @@
+package org.opendaylight.controller.md.statistics.manager;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener;
+
+public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsListener,
+        OpendaylightMeterStatisticsListener {
+    
+    private final StatisticsProvider statisticsManager;
+
+    public StatisticsUpdateCommiter(final StatisticsProvider manager){
+
+        this.statisticsManager = manager;
+    }
+    public StatisticsProvider getStatisticsManager(){
+        return statisticsManager;
+    }
+    @Override
+    public void onMeterConfigStatsUpdated(MeterConfigStatsUpdated notification) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void onMeterStatisticsUpdated(MeterStatisticsUpdated notification) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void onGroupDescStatsUpdated(GroupDescStatsUpdated notification) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void onGroupStatisticsUpdated(GroupStatisticsUpdated notification) {
+        // TODO Auto-generated method stub
+
+    }
+    @Override
+    public void onMeterFeaturesUpdated(MeterFeaturesUpdated notification) {
+        // TODO Auto-generated method stub
+        
+    }
+    @Override
+    public void onGroupFeaturesUpdated(GroupFeaturesUpdated notification) {
+        // TODO Auto-generated method stub
+        
+    }
+
+}
index e8690aa889aee1d449601a3156757d298de9dd72..c08ee80e24c44f3551d949e0ff607c7264be9167 100644 (file)
@@ -12,6 +12,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -67,8 +68,8 @@ public class NeutronNetworksNorthbound {
     @Produces({ MediaType.APPLICATION_JSON })
     //@TypeHint(OpenStackNetworks.class)
     @StatusCodes({
-            @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 401, condition = "Unauthorized") })
+        @ResponseCode(code = 200, condition = "Operation successful"),
+        @ResponseCode(code = 401, condition = "Unauthorized") })
     public Response listNetworks(
             // return fields
             @QueryParam("fields") List<String> fields,
@@ -88,7 +89,7 @@ public class NeutronNetworksNorthbound {
             @QueryParam("marker") String marker,
             @QueryParam("page_reverse") String pageReverse
             // sorting not supported
-        ) {
+            ) {
         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
         if (networkInterface == null) {
             throw new ServiceUnavailableException("Network CRUD Interface "
@@ -103,12 +104,15 @@ public class NeutronNetworksNorthbound {
             Boolean bAdminStateUp = null;
             Boolean bShared = null;
             Boolean bRouterExternal = null;
-            if (queryAdminStateUp != null)
+            if (queryAdminStateUp != null) {
                 bAdminStateUp = Boolean.valueOf(queryAdminStateUp);
-            if (queryShared != null)
+            }
+            if (queryShared != null) {
                 bShared = Boolean.valueOf(queryShared);
-            if (queryRouterExternal != null)
+            }
+            if (queryRouterExternal != null) {
                 bRouterExternal = Boolean.valueOf(queryRouterExternal);
+            }
             if ((queryID == null || queryID.equals(oSN.getID())) &&
                     (queryName == null || queryName.equals(oSN.getNetworkName())) &&
                     (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&
@@ -116,10 +120,11 @@ public class NeutronNetworksNorthbound {
                     (bShared == null || bShared.booleanValue() == oSN.isShared()) &&
                     (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&
                     (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {
-                if (fields.size() > 0)
+                if (fields.size() > 0) {
                     ans.add(extractFields(oSN,fields));
-                else
+                } else {
                     ans.add(oSN);
+                }
             }
         }
         //TODO: apply pagination to results
@@ -135,9 +140,9 @@ public class NeutronNetworksNorthbound {
     @Produces({ MediaType.APPLICATION_JSON })
     //@TypeHint(OpenStackNetworks.class)
     @StatusCodes({
-            @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 401, condition = "Unauthorized"),
-            @ResponseCode(code = 404, condition = "Not Found") })
+        @ResponseCode(code = 200, condition = "Operation successful"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 404, condition = "Not Found") })
     public Response showNetwork(
             @PathParam("netUUID") String netUUID,
             // return fields
@@ -148,15 +153,17 @@ public class NeutronNetworksNorthbound {
             throw new ServiceUnavailableException("Network CRUD Interface "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
         }
-        if (!networkInterface.networkExists(netUUID))
+        if (!networkInterface.networkExists(netUUID)) {
             return Response.status(404).build();
+        }
         if (fields.size() > 0) {
             NeutronNetwork ans = networkInterface.getNetwork(netUUID);
             return Response.status(200).entity(
                     new NeutronNetworkRequest(extractFields(ans, fields))).build();
-        } else
+        } else {
             return Response.status(200).entity(
                     new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
+        }
     }
 
     /**
@@ -166,9 +173,9 @@ public class NeutronNetworksNorthbound {
     @Consumes({ MediaType.APPLICATION_JSON })
     @TypeHint(NeutronNetwork.class)
     @StatusCodes({
-            @ResponseCode(code = 201, condition = "Created"),
-            @ResponseCode(code = 400, condition = "Bad Request"),
-            @ResponseCode(code = 401, condition = "Unauthorized") })
+        @ResponseCode(code = 201, condition = "Created"),
+        @ResponseCode(code = 400, condition = "Bad Request"),
+        @ResponseCode(code = 401, condition = "Unauthorized") })
     public Response createNetworks(final NeutronNetworkRequest input) {
         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
         if (networkInterface == null) {
@@ -181,20 +188,23 @@ public class NeutronNetworksNorthbound {
             /*
              * network ID can't already exist
              */
-            if (networkInterface.networkExists(singleton.getID()))
+            if (networkInterface.networkExists(singleton.getID())) {
                 return Response.status(400).build();
+            }
 
             Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
             if (instances != null) {
                 for (Object instance : instances) {
                     INeutronNetworkAware service = (INeutronNetworkAware) instance;
                     int status = service.canCreateNetwork(singleton);
-                    if (status < 200 || status > 299)
+                    if (status < 200 || status > 299) {
                         return Response.status(status).build();
+                    }
                 }
             }
 
             // add network to cache
+            singleton.initDefaults();
             networkInterface.addNetwork(singleton);
             if (instances != null) {
                 for (Object instance : instances) {
@@ -215,16 +225,19 @@ public class NeutronNetworksNorthbound {
                  * network ID can't already exist, nor can there be an entry for this UUID
                  * already in this bulk request
                  */
-                if (networkInterface.networkExists(test.getID()))
+                if (networkInterface.networkExists(test.getID())) {
                     return Response.status(400).build();
-                if (testMap.containsKey(test.getID()))
+                }
+                if (testMap.containsKey(test.getID())) {
                     return Response.status(400).build();
+                }
                 if (instances != null) {
                     for (Object instance: instances) {
                         INeutronNetworkAware service = (INeutronNetworkAware) instance;
                         int status = service.canCreateNetwork(test);
-                        if (status < 200 || status > 299)
+                        if (status < 200 || status > 299) {
                             return Response.status(status).build();
+                        }
                     }
                 }
                 testMap.put(test.getID(),test);
@@ -255,10 +268,10 @@ public class NeutronNetworksNorthbound {
     @Consumes({ MediaType.APPLICATION_JSON })
     //@TypeHint(OpenStackNetworks.class)
     @StatusCodes({
-            @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 400, condition = "Bad Request"),
-            @ResponseCode(code = 403, condition = "Forbidden"),
-            @ResponseCode(code = 404, condition = "Not Found"), })
+        @ResponseCode(code = 200, condition = "Operation successful"),
+        @ResponseCode(code = 400, condition = "Bad Request"),
+        @ResponseCode(code = 403, condition = "Forbidden"),
+        @ResponseCode(code = 404, condition = "Not Found"), })
     public Response updateNetwork(
             @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input
             ) {
@@ -271,18 +284,21 @@ public class NeutronNetworksNorthbound {
         /*
          * network has to exist and only a single delta is supported
          */
-        if (!networkInterface.networkExists(netUUID))
+        if (!networkInterface.networkExists(netUUID)) {
             return Response.status(404).build();
-        if (!input.isSingleton())
+        }
+        if (!input.isSingleton()) {
             return Response.status(400).build();
+        }
         NeutronNetwork delta = input.getSingleton();
 
         /*
          * transitions forbidden by Neutron
          */
         if (delta.getID() != null || delta.getTenantID() != null ||
-                delta.getStatus() != null)
+                delta.getStatus() != null) {
             return Response.status(400).build();
+        }
 
         Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
         if (instances != null) {
@@ -290,22 +306,23 @@ public class NeutronNetworksNorthbound {
                 INeutronNetworkAware service = (INeutronNetworkAware) instance;
                 NeutronNetwork original = networkInterface.getNetwork(netUUID);
                 int status = service.canUpdateNetwork(delta, original);
-                if (status < 200 || status > 299)
+                if (status < 200 || status > 299) {
                     return Response.status(status).build();
+                }
             }
         }
 
         // update network object and return the modified object
-        networkInterface.updateNetwork(netUUID, delta);
-        NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);
-        if (instances != null) {
-            for (Object instance : instances) {
-                INeutronNetworkAware service = (INeutronNetworkAware) instance;
-                service.neutronNetworkUpdated(updatedSingleton);
-            }
-        }
-        return Response.status(200).entity(
-                new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
+                networkInterface.updateNetwork(netUUID, delta);
+                NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);
+                if (instances != null) {
+                    for (Object instance : instances) {
+                        INeutronNetworkAware service = (INeutronNetworkAware) instance;
+                        service.neutronNetworkUpdated(updatedSingleton);
+                    }
+                }
+                return Response.status(200).entity(
+                        new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
     }
 
     /**
@@ -314,10 +331,10 @@ public class NeutronNetworksNorthbound {
     @Path("{netUUID}")
     @DELETE
     @StatusCodes({
-            @ResponseCode(code = 204, condition = "No Content"),
-            @ResponseCode(code = 401, condition = "Unauthorized"),
-            @ResponseCode(code = 404, condition = "Not Found"),
-            @ResponseCode(code = 409, condition = "Network In Use") })
+        @ResponseCode(code = 204, condition = "No Content"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 404, condition = "Not Found"),
+        @ResponseCode(code = 409, condition = "Network In Use") })
     public Response deleteNetwork(
             @PathParam("netUUID") String netUUID) {
         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
@@ -329,10 +346,12 @@ public class NeutronNetworksNorthbound {
         /*
          * network has to exist and not be in use before it can be removed
          */
-        if (!networkInterface.networkExists(netUUID))
+        if (!networkInterface.networkExists(netUUID)) {
             return Response.status(404).build();
-        if (networkInterface.networkInUse(netUUID))
+        }
+        if (networkInterface.networkInUse(netUUID)) {
             return Response.status(409).build();
+        }
 
         NeutronNetwork singleton = networkInterface.getNetwork(netUUID);
         Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
@@ -340,8 +359,9 @@ public class NeutronNetworksNorthbound {
             for (Object instance : instances) {
                 INeutronNetworkAware service = (INeutronNetworkAware) instance;
                 int status = service.canDeleteNetwork(singleton);
-                if (status < 200 || status > 299)
+                if (status < 200 || status > 299) {
                     return Response.status(status).build();
+                }
             }
         }
         networkInterface.removeNetwork(netUUID);
index 08e5dfbb364d6cf7c82b2c677cff3359f533a13b..d3c262f222f7f62bd612193944b0b0d919a50271 100644 (file)
@@ -12,6 +12,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -71,9 +72,9 @@ public class NeutronPortsNorthbound {
     @Produces({ MediaType.APPLICATION_JSON })
     //@TypeHint(OpenStackPorts.class)
     @StatusCodes({
-            @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 401, condition = "Unauthorized"),
-            @ResponseCode(code = 501, condition = "Not Implemented") })
+        @ResponseCode(code = 200, condition = "Operation successful"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 501, condition = "Not Implemented") })
     public Response listPorts(
             // return fields
             @QueryParam("fields") List<String> fields,
@@ -112,10 +113,11 @@ public class NeutronPortsNorthbound {
                     (queryDeviceID == null || queryDeviceID.equals(oSS.getDeviceID())) &&
                     (queryDeviceOwner == null || queryDeviceOwner.equals(oSS.getDeviceOwner())) &&
                     (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
-                if (fields.size() > 0)
+                if (fields.size() > 0) {
                     ans.add(extractFields(oSS,fields));
-                else
+                } else {
                     ans.add(oSS);
+                }
             }
         }
         //TODO: apply pagination to results
@@ -131,10 +133,10 @@ public class NeutronPortsNorthbound {
     @Produces({ MediaType.APPLICATION_JSON })
     //@TypeHint(OpenStackPorts.class)
     @StatusCodes({
-            @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 401, condition = "Unauthorized"),
-            @ResponseCode(code = 404, condition = "Not Found"),
-            @ResponseCode(code = 501, condition = "Not Implemented") })
+        @ResponseCode(code = 200, condition = "Operation successful"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 404, condition = "Not Found"),
+        @ResponseCode(code = 501, condition = "Not Implemented") })
     public Response showPort(
             @PathParam("portUUID") String portUUID,
             // return fields
@@ -144,15 +146,17 @@ public class NeutronPortsNorthbound {
             throw new ServiceUnavailableException("Port CRUD Interface "
                     + RestMessages.SERVICEUNAVAILABLE.toString());
         }
-        if (!portInterface.portExists(portUUID))
+        if (!portInterface.portExists(portUUID)) {
             return Response.status(404).build();
+        }
         if (fields.size() > 0) {
             NeutronPort ans = portInterface.getPort(portUUID);
             return Response.status(200).entity(
                     new NeutronPortRequest(extractFields(ans, fields))).build();
-        } else
+        } else {
             return Response.status(200).entity(
                     new NeutronPortRequest(portInterface.getPort(portUUID))).build();
+        }
     }
 
     /**
@@ -163,14 +167,14 @@ public class NeutronPortsNorthbound {
     @Consumes({ MediaType.APPLICATION_JSON })
     //@TypeHint(OpenStackPorts.class)
     @StatusCodes({
-            @ResponseCode(code = 201, condition = "Created"),
-            @ResponseCode(code = 400, condition = "Bad Request"),
-            @ResponseCode(code = 401, condition = "Unauthorized"),
-            @ResponseCode(code = 403, condition = "Forbidden"),
-            @ResponseCode(code = 404, condition = "Not Found"),
-            @ResponseCode(code = 409, condition = "Conflict"),
-            @ResponseCode(code = 501, condition = "Not Implemented"),
-            @ResponseCode(code = 503, condition = "MAC generation failure") })
+        @ResponseCode(code = 201, condition = "Created"),
+        @ResponseCode(code = 400, condition = "Bad Request"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 403, condition = "Forbidden"),
+        @ResponseCode(code = 404, condition = "Not Found"),
+        @ResponseCode(code = 409, condition = "Conflict"),
+        @ResponseCode(code = 501, condition = "Not Implemented"),
+        @ResponseCode(code = 503, condition = "MAC generation failure") })
     public Response createPorts(final NeutronPortRequest input) {
         INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
         if (portInterface == null) {
@@ -194,24 +198,30 @@ public class NeutronPortsNorthbound {
              * the port must be part of an existing network, must not already exist,
              * have a valid MAC and the MAC not be in use
              */
-            if (singleton.getNetworkUUID() == null)
+            if (singleton.getNetworkUUID() == null) {
                 return Response.status(400).build();
-            if (portInterface.portExists(singleton.getID()))
+            }
+            if (portInterface.portExists(singleton.getID())) {
                 return Response.status(400).build();
-            if (!networkInterface.networkExists(singleton.getNetworkUUID()))
+            }
+            if (!networkInterface.networkExists(singleton.getNetworkUUID())) {
                 return Response.status(404).build();
+            }
             if (singleton.getMacAddress() == null ||
-                    !singleton.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))
+                    !singleton.getMacAddress().matches("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")) {
                 return Response.status(400).build();
-            if (portInterface.macInUse(singleton.getMacAddress()))
+            }
+            if (portInterface.macInUse(singleton.getMacAddress())) {
                 return Response.status(409).build();
+            }
             Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
             if (instances != null) {
                 for (Object instance : instances) {
                     INeutronPortAware service = (INeutronPortAware) instance;
                     int status = service.canCreatePort(singleton);
-                    if (status < 200 || status > 299)
+                    if (status < 200 || status > 299) {
                         return Response.status(status).build();
+                    }
                 }
             }
             /*
@@ -225,18 +235,23 @@ public class NeutronPortsNorthbound {
                 Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
                 while (fixedIPIterator.hasNext()) {
                     Neutron_IPs ip = fixedIPIterator.next();
-                    if (ip.getSubnetUUID() == null)
+                    if (ip.getSubnetUUID() == null) {
                         return Response.status(400).build();
-                    if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+                    }
+                    if (!subnetInterface.subnetExists(ip.getSubnetUUID())) {
                         return Response.status(400).build();
+                    }
                     NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
-                    if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+                    if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) {
                         return Response.status(400).build();
+                    }
                     if (ip.getIpAddress() != null) {
-                        if (!subnet.isValidIP(ip.getIpAddress()))
+                        if (!subnet.isValidIP(ip.getIpAddress())) {
                             return Response.status(400).build();
-                        if (subnet.isIPInUse(ip.getIpAddress()))
+                        }
+                        if (subnet.isIPInUse(ip.getIpAddress())) {
                             return Response.status(409).build();
+                        }
                     }
                 }
             }
@@ -262,33 +277,41 @@ public class NeutronPortsNorthbound {
                  * have a valid MAC and the MAC not be in use.  Further the bulk request
                  * can't already contain a new port with the same UUID
                  */
-                if (portInterface.portExists(test.getID()))
+                if (portInterface.portExists(test.getID())) {
                     return Response.status(400).build();
-                if (testMap.containsKey(test.getID()))
+                }
+                if (testMap.containsKey(test.getID())) {
                     return Response.status(400).build();
+                }
                 for (NeutronPort check : testMap.values()) {
-                    if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress()))
+                    if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress())) {
                         return Response.status(409).build();
+                    }
                     for (Neutron_IPs test_fixedIP : test.getFixedIPs()) {
                         for (Neutron_IPs check_fixedIP : check.getFixedIPs()) {
-                            if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress()))
+                            if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress())) {
                                 return Response.status(409).build();
+                            }
                         }
                     }
                 }
                 testMap.put(test.getID(), test);
-                if (!networkInterface.networkExists(test.getNetworkUUID()))
+                if (!networkInterface.networkExists(test.getNetworkUUID())) {
                     return Response.status(404).build();
-                if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))
+                }
+                if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$")) {
                     return Response.status(400).build();
-                if (portInterface.macInUse(test.getMacAddress()))
+                }
+                if (portInterface.macInUse(test.getMacAddress())) {
                     return Response.status(409).build();
+                }
                 if (instances != null) {
                     for (Object instance : instances) {
                         INeutronPortAware service = (INeutronPortAware) instance;
                         int status = service.canCreatePort(test);
-                        if (status < 200 || status > 299)
+                        if (status < 200 || status > 299) {
                             return Response.status(status).build();
+                        }
                     }
                 }
                 /*
@@ -302,20 +325,25 @@ public class NeutronPortsNorthbound {
                     Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
                     while (fixedIPIterator.hasNext()) {
                         Neutron_IPs ip = fixedIPIterator.next();
-                        if (ip.getSubnetUUID() == null)
+                        if (ip.getSubnetUUID() == null) {
                             return Response.status(400).build();
-                        if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+                        }
+                        if (!subnetInterface.subnetExists(ip.getSubnetUUID())) {
                             return Response.status(400).build();
+                        }
                         NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
-                        if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+                        if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) {
                             return Response.status(400).build();
+                        }
                         if (ip.getIpAddress() != null) {
-                            if (!subnet.isValidIP(ip.getIpAddress()))
+                            if (!subnet.isValidIP(ip.getIpAddress())) {
                                 return Response.status(400).build();
+                            }
                             //TODO: need to add consideration for a fixed IP being assigned the same address as a allocated IP in the
                             //same bulk create
-                            if (subnet.isIPInUse(ip.getIpAddress()))
+                            if (subnet.isIPInUse(ip.getIpAddress())) {
                                 return Response.status(409).build();
+                            }
                         }
                     }
                 }
@@ -346,13 +374,13 @@ public class NeutronPortsNorthbound {
     @Consumes({ MediaType.APPLICATION_JSON })
     //@TypeHint(OpenStackPorts.class)
     @StatusCodes({
-            @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 400, condition = "Bad Request"),
-            @ResponseCode(code = 401, condition = "Unauthorized"),
-            @ResponseCode(code = 403, condition = "Forbidden"),
-            @ResponseCode(code = 404, condition = "Not Found"),
-            @ResponseCode(code = 409, condition = "Conflict"),
-            @ResponseCode(code = 501, condition = "Not Implemented") })
+        @ResponseCode(code = 200, condition = "Operation successful"),
+        @ResponseCode(code = 400, condition = "Bad Request"),
+        @ResponseCode(code = 401, condition = "Unauthorized"),
+        @ResponseCode(code = 403, condition = "Forbidden"),
+        @ResponseCode(code = 404, condition = "Not Found"),
+        @ResponseCode(code = 409, condition = "Conflict"),
+        @ResponseCode(code = 501, condition = "Not Implemented") })
     public Response updatePort(
             @PathParam("portUUID") String portUUID,
             NeutronPortRequest input
@@ -369,26 +397,30 @@ public class NeutronPortsNorthbound {
         }
 
         // port has to exist and only a single delta is supported
-        if (!portInterface.portExists(portUUID))
+        if (!portInterface.portExists(portUUID)) {
             return Response.status(404).build();
+        }
         NeutronPort target = portInterface.getPort(portUUID);
-        if (!input.isSingleton())
+        if (!input.isSingleton()) {
             return Response.status(400).build();
+        }
         NeutronPort singleton = input.getSingleton();
         NeutronPort original = portInterface.getPort(portUUID);
 
         // deltas restricted by Neutron
         if (singleton.getID() != null || singleton.getTenantID() != null ||
-                singleton.getStatus() != null)
+                singleton.getStatus() != null) {
             return Response.status(400).build();
+        }
 
         Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
         if (instances != null) {
             for (Object instance : instances) {
                 INeutronPortAware service = (INeutronPortAware) instance;
                 int status = service.canUpdatePort(singleton, original);
-                if (status < 200 || status > 299)
+                if (status < 200 || status > 299) {
                     return Response.status(status).build();
+                }
             }
         }
 
@@ -398,25 +430,30 @@ public class NeutronPortsNorthbound {
             Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
             while (fixedIPIterator.hasNext()) {
                 Neutron_IPs ip = fixedIPIterator.next();
-                if (ip.getSubnetUUID() == null)
+                if (ip.getSubnetUUID() == null) {
                     return Response.status(400).build();
-                if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+                }
+                if (!subnetInterface.subnetExists(ip.getSubnetUUID())) {
                     return Response.status(400).build();
+                }
                 NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
-                if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+                if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) {
                     return Response.status(400).build();
+                }
                 if (ip.getIpAddress() != null) {
-                    if (!subnet.isValidIP(ip.getIpAddress()))
+                    if (!subnet.isValidIP(ip.getIpAddress())) {
                         return Response.status(400).build();
-                    if (subnet.isIPInUse(ip.getIpAddress()))
+                    }
+                    if (subnet.isIPInUse(ip.getIpAddress())) {
                         return Response.status(409).build();
+                    }
                 }
             }
         }
 
-//        TODO: Support change of security groups
+        //        TODO: Support change of security groups
         // update the port and return the modified object
-        portInterface.updatePort(portUUID, singleton);
+                portInterface.updatePort(portUUID, singleton);
         NeutronPort updatedPort = portInterface.getPort(portUUID);
         if (instances != null) {
             for (Object instance : instances) {
@@ -449,20 +486,23 @@ public class NeutronPortsNorthbound {
         }
 
         // port has to exist and not be owned by anyone.  then it can be removed from the cache
-        if (!portInterface.portExists(portUUID))
+        if (!portInterface.portExists(portUUID)) {
             return Response.status(404).build();
+        }
         NeutronPort port = portInterface.getPort(portUUID);
         if (port.getDeviceID() != null ||
-                port.getDeviceOwner() != null)
+                port.getDeviceOwner() != null) {
             Response.status(403).build();
+        }
         NeutronPort singleton = portInterface.getPort(portUUID);
         Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
         if (instances != null) {
             for (Object instance : instances) {
                 INeutronPortAware service = (INeutronPortAware) instance;
                 int status = service.canDeletePort(singleton);
-                if (status < 200 || status > 299)
+                if (status < 200 || status > 299) {
                     return Response.status(status).build();
+                }
             }
         }
         portInterface.removePort(portUUID);