Added enable/disable methods to affinity link. 77/2277/1
authorSuchi Raman <suchi.raman@plexxi.com>
Wed, 30 Oct 2013 16:00:39 +0000 (12:00 -0400)
committerSuchi Raman <suchi.raman@plexxi.com>
Wed, 30 Oct 2013 16:00:39 +0000 (12:00 -0400)
Called from Northbound API classes and implemented within nfchain agent.

Signed-off-by: Suchi Raman <suchi.raman@plexxi.com>
affinity/api/src/main/java/org/opendaylight/affinity/affinity/IAffinityManager.java
affinity/implementation/src/main/java/org/opendaylight/affinity/affinity/internal/AffinityManagerImpl.java
affinity/northbound/src/main/java/org/opendaylight/affinity/affinity/northbound/AffinityNorthbound.java
affinity/yang/src/main/yang/affinity-config-all.yang [deleted file]
nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/NFchainAgent.java
scripts/affinity.py

index 7f29b132fb9a78db24dcc4da8514653ba53abbc8..2af466c07732aa8093e1f19d1189a04087113338 100644 (file)
@@ -58,6 +58,7 @@ public interface IAffinityManager {
     /* Methods to add and enable network service chains. */
     public Status addNfchain(AffinityLink al);
     public Status enableRedirect(AffinityLink al) throws Exception;
+    public Status disableRedirect(AffinityLink al) throws Exception;
 
     //    public Status addFlowRulesForRedirect(AffinityLink al) throws Exception;
     //    public Status pushFlowRule(InetAddress from, InetAddress to, byte [] mac);
index 00505ad1891e140a854c6c0b37883378c64e6db4..14ba6ffb68c98f158e24f94033ea3a03d5804dee 100644 (file)
@@ -609,7 +609,7 @@ public class AffinityManagerImpl implements IAffinityManager, IfNewHostNotify,
     /**
      * Function called after registering the service in OSGi service registry.
      */
-    void started(){
+    void started() {
         // Retrieve current statistics so we don't have to wait for next refresh
         IAffinityManager affinityManager = (IAffinityManager) ServiceHelper.getInstance(
                 IAffinityManager.class, this.getContainerName(), this);
@@ -691,4 +691,15 @@ public class AffinityManagerImpl implements IAffinityManager, IfNewHostNotify,
         String nfccname = al.getName();
         return nfchainagent.enable(nfccname);
     }
+   public Status disableRedirect(AffinityLink al) throws Exception {
+        String nfccname = al.getName();
+        return nfchainagent.disable(nfccname);
+    }
+
+   public Status removeNfchain(AffinityLink al) throws Exception {
+        String nfccname = al.getName();
+        return nfchainagent.removeNfchain(nfccname);
+    }
+
 }
index 6dce287bdbcacebeb716b942768e69990b3af6be..80b8cfcbea76c6be4f93f0588b688f2591417a6b 100644 (file)
@@ -276,6 +276,40 @@ public class AffinityNorthbound {
         al1.setWaypoint(waypointIP);
         try {
             affinityManager.addNfchain(al1);
+        } catch (Exception e) {
+            String message = "An error occurred during flow programming.";
+            log.error(message, e);
+        }
+        return Response.status(Response.Status.CREATED).build();
+    }
+
+
+    @Path("/{containerName}/link/{affinityLinkName}/enable")
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @TypeHint(Response.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+    public Response enableLink(
+            @PathParam("containerName") String containerName,
+            @PathParam("affinityLinkName") String affinityLinkName) {
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                                            + containerName);
+        }
+
+        IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+        if (affinityManager == null) {
+            throw new ServiceUnavailableException("Affinity Manager "
+                                                  + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        log.info("Enable (link) " + affinityLinkName);
+
+        AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
+        try {
             affinityManager.enableRedirect(al1);
         } catch (Exception e) {
             String message = "An error occurred during flow programming.";
@@ -284,6 +318,39 @@ public class AffinityNorthbound {
         return Response.status(Response.Status.CREATED).build();
     }
 
+    @Path("/{containerName}/link/{affinityLinkName}/disable")
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @TypeHint(Response.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+    public Response disableLink(
+            @PathParam("containerName") String containerName,
+            @PathParam("affinityLinkName") String affinityLinkName) {
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                                            + containerName);
+        }
+
+        IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+        if (affinityManager == null) {
+            throw new ServiceUnavailableException("Affinity Manager "
+                                                  + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        log.info("Disable (link) " + affinityLinkName);
+
+        AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
+        try {
+            affinityManager.disableRedirect(al1);
+        } catch (Exception e) {
+            String message = "An error occurred during flow programming.";
+            log.error(message, e);
+        }
+        return Response.status(Response.Status.CREATED).build();
+    }
 
     /**
      * Add IP addresses to a group. 
diff --git a/affinity/yang/src/main/yang/affinity-config-all.yang b/affinity/yang/src/main/yang/affinity-config-all.yang
deleted file mode 100644 (file)
index fdabdfc..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-module affinity-config-all { 
-    namespace "urn:opendaylight:affinity";
-    prefix affinity;
-
-    import ietf-inet-types { prefix inet; }
-    import ietf-yang-types { prefix yang; }
-    import yang-ext { prefix ext; }
-    import opendaylight-inventory {prefix inv;}
-    import opendaylight-l2-types { prefix l2types; }
-
-    revision "2013-09-25" {
-       description "Initial revision of affinity model to be reviewed";
-    }
-
-
-  //**************************************************
-  // Stationary location within the network -- switch + port, including physical switch port 
-  // or virtual switch port within a hypervisor virtual switch. 
-  //**************************************************
-  grouping affinity-endpoint {
-      leaf switch-port {
-         type inv:node-connector-id;
-      }
-  }
-
-  //**************************************************
-  // Affinity address domain: This represents a domain (i.e, set) of one or
-  // more addresses. An affinity address may not always have a corresponding
-  // endpoint on the network, for example, an address domain representing 
-  // external addresses, or north-south traffic in a data center). Here the 
-  // IP address domain representing such external addresses does not map to 
-  // endpoints or node connectors on the network. 
-  // Whenever possible, the affinity service must resolve the address domain
-  // into a list of endpoints especially when the address is present on the network. 
-  // 
-  // Affinity address domains specify one or more of the following: 
-  // layer 2 address (vlan + mac range)
-  // layer 3 address (IP prefix)
-  // layer 4 address (tcp or udp port number)
-  //**************************************************
-
-   grouping affinity-address-domain {
-       // l2-domain-address is vlan + MAC address range
-       container l2-address {
-          leaf vlan-id {
-              type l2types:vlan-id; 
-          }
-          container mac-address-range {
-              uses mac-address-range;
-          }
-       }
-
-       // l3-domain-address is IPv4 prefix
-       leaf l3-address {
-          type inet:ipv4-prefix;
-       }
-
-       // l4 port number 
-       container l4-address {
-           leaf proto {
-               type string; // "tcp" or "udp"
-           }
-           leaf port-number {   
-               type inet:port-number;
-           }
-       }        
-   }       
-
-   grouping mac-address-range {
-       leaf start-address {
-          type yang:mac-address;
-       }
-       leaf end-address {
-          type yang:mac-address;
-       }
-   }
-
-   typedef affinity-group-ref {
-       type instance-identifier;
-   }
-   
-   typedef affinity-link-ref {
-       type instance-identifier;
-   }
-   
-   grouping affinity-element {
-       leaf id {
-          type string;
-       }
-       choice element {
-          description "affinity element";
-          case affinity-endpoint {
-                  uses affinity-endpoint;
-              }
-              
-              case affinity-address-domain {
-                      uses affinity-address-domain;
-                  }
-       }
-   }      
-   //**************************************************
-   // Affinity group
-   //**************************************************
-    grouping affinity-group {
-       leaf id {
-           type string;
-       }   
-       list affinity-element {
-           key id;
-           uses affinity-element;
-       }
-    }
-
-    //**************************************************
-    // Affinity link connects one group (from group) to another (to
-    // group). It represents a set of flows that start from the source group
-    // and end in the destination group.  An affinity link has attributes
-    // (policies) attached to it that represent how these flows must be
-    // handled. An affinity link also has directionality associated with
-    // it. A bidirectional affinity link is equivalent to two unidirectional
-    // affinity links, one in each direction.
-    //**************************************************
-    grouping affinity-link {
-       leaf id {
-           type string;
-       }
-       leaf from-affinity-group {
-           type affinity-group-ref;
-       }
-       leaf to-affinity-group {
-           type affinity-group-ref;
-       }
-       container attribute {
-           uses affinity-attribute; 
-       }
-    }
-
-    typedef affinity-access-control-type {
-             type enumeration {
-                 enum permit;
-                 enum deny;
-             }
-    }
-
-    //**************************************************
-    // Affinity attribute. Each is expanded in their own grouping construct below. 
-    //**************************************************
-    grouping affinity-attribute {
-       leaf id {
-           type string;
-       }
-       choice attribute-type {
-           description "affinity attribute";
-           // Apply access control to selected flows. 
-           case affinity-access-control {
-                   leaf affinity-access-control {
-                       type  affinity-access-control-type;
-                   }
-               }
-               
-               // Apply waypoint routing to the selected flows and send it through service chain. 
-           case network-service-chain {
-                   leaf network-service-chain  {
-                       type network-service-chain-ref;
-                   }
-           }
-       }
-    }
-
-    //**************************************************
-    // Network service chain configuration. 
-    //**************************************************
-    typedef network-service-chain-ref {
-        type instance-identifier;
-    }
-    
-    grouping network-service-chain {
-       leaf id {
-           type string;
-       }   
-       list service-chain {
-           key id;
-           uses network-service-function;
-       }
-    }
-
-    //**************************************************
-    // Network-service-function represented by one of the following
-    // types of addresses.
-    //**************************************************
-    grouping network-service-function {
-       leaf id {
-           type string;
-       }
-       // Address is either an IP address, MAC address, or switch/port. 
-       leaf location {
-           description "Mac or Inet address";
-           type union {
-               type inv:node-connector-id;
-               type yang:mac-address;
-               type inet:ip-address;
-           }
-       }
-    }
-
-    // Main container that represents the complete set of affinity
-    // groups and links. Each set is represented as a YANG list with 'id'
-    // as the key. List contains affinity group and affinity link objects
-    // defined above.
-    container affinity-config {
-       list affinity-group {
-           key id;
-           ext:context-instance "affinity-group-context";
-           uses affinity-group;
-       }
-       list affinity-link {
-           key id;
-           ext:context-instance "affinity-link-context";
-           uses affinity-link;
-       }
-    }
-
-    //******************************
-    // RPCs to create affinity groups, add endpoints and address domains. 
-    //******************************
-    rpc create-affinity-group {
-       input {
-           uses affinity-group;
-       }
-       output {
-           leaf status {
-               type string;
-           }
-       }
-    }
-
-    rpc add-affinity-endpoint {
-       input {
-           leaf affinity-endpoint {
-               type inv:node-connector-id;
-           }
-       }
-       output {
-           leaf status {
-               type string;
-           }
-       }
-    }
-
-    rpc add-affinity-domain {
-       input {
-           container affinity-domain {
-               uses affinity-address-domain;
-           }
-       }    
-       output {
-           leaf status {
-               type string;
-           }
-       }
-    }
-
-    rpc get-affinity-groups {
-       output {
-           list affinity-group {
-           key id;
-           uses affinity-group;
-           }
-       }
-    }
-    rpc get-affinity-links;
-    rpc get-affinity-group;
-    rpc get-affinity-link;
-
-    rpc get-stats-per-affinity-link;
-
-    //**************************************************
-    // Notifications 
-    //**************************************************
-    notification new-affinity-endpoint;
-    notification new-affinity-domain;
-    notification modify-affinity-attribute;
-
-}
-
-
index ae2183f3463e4da58b67304782e5780d8a64e10b..2c5f98df20d3920da03ba56af76acc3df9c59ec8 100644 (file)
@@ -152,11 +152,11 @@ public class NFchainAgent implements Serializable {
             /* Look up the output port leading to the waypoint. */
             NodeConnector dst_connector = l2agent.lookup_output_port(node, wphost.getDataLayerAddressBytes());
 
-            log.debug("Waypoint direction: node {} and connector {}", node, dst_connector);
+            log.debug("Waypoint direction added: node {} and connector {}", node, dst_connector);
             if (dst_connector != null) {
                 f.setActions(actions);
                 f.addAction(new Output(dst_connector));
-                log.debug("flow push flow = {} to node = {} ", f, node);
+                log.debug("flow push add flow = {} to node = {} ", f, node);
                 Status status = programmer.addFlow(node, f);
                 if (!status.isSuccess()) {
                     log.debug("Error during addFlow: {} on {}. The failure is: {}",
@@ -168,6 +168,42 @@ public class NFchainAgent implements Serializable {
     }
 
 
+
+    /** 
+     * remove flow rules for set of flows in nfchainconfig. Do this for
+     * each node connector in the network proactively.
+     */
+    public Status removerules(Node node, NFchainconfig nfcc) throws Exception {
+        List<Flow> flowlist = nfcc.getFlowList();
+        for (Flow f: flowlist) {
+            HostNodeConnector wphost = (HostNodeConnector) hostTracker.hostFind(nfcc.getWaypointIP()); 
+            List<Action> actions = new ArrayList<Action>();
+            /* Look up the output port leading to the waypoint. */
+            NodeConnector dst_connector = l2agent.lookup_output_port(node, wphost.getDataLayerAddressBytes());
+
+            log.debug("Waypoint settings removed: node {} and connector {}", node, dst_connector);
+            if (dst_connector != null) {
+                f.setActions(actions);
+                f.addAction(new Output(dst_connector));
+                log.debug("flow push remove flow = {} to node = {} ", f, node);
+                Status status = programmer.removeFlow(node, f);
+                if (!status.isSuccess()) {
+                    log.debug("Error during removeFlow: {} on {}. The failure is: {}",
+                              f, node, status.getDescription());
+                }
+            }
+        }
+        return new Status(StatusCode.SUCCESS); 
+    }
+
+
+    public Status removeNfchain(String key) {
+        if (allconfigs != null) {
+            allconfigs.remove(key);
+        }
+        return new Status(StatusCode.SUCCESS); 
+    }
+
     /** 
      * Enable the nfchain by programming flow rules on its behalf. 
      */
@@ -191,5 +227,29 @@ public class NFchainAgent implements Serializable {
         }
         return new Status(StatusCode.SUCCESS);         
     }
+
+    /** 
+     * Remove openflow rules added earlier. Restore default routing via standard L2 learning methods. 
+     */
+    public Status disable(String cfgname) throws Exception {
+        /* Get all node connectors. */
+        Set<Node> nodes = switchManager.getNodes();
+        NFchainconfig cfg = allconfigs.get(cfgname).get(0);
+
+        Status success = new Status(StatusCode.SUCCESS);
+        Status notfound = new Status(StatusCode.NOTFOUND);
+        Status ret;
+
+        if (nodes == null) {
+            log.debug("No nodes in network.");
+            return success;
+        } 
+
+        /* Send this flow rule to all nodes in the network. */
+        for (Node node: nodes) {
+            ret = removerules(node, cfg);
+        }
+        return new Status(StatusCode.SUCCESS);         
+    }
 }
 
index b559637ff7b268dda475da75a5d5dbcbb59483fa..fcdb7d28681949ceb74a63c6a16cf7a34ff20d8e 100644 (file)
@@ -86,6 +86,14 @@ def set_waypoint_address():
     put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/inflows/setwaypoint/' + wp
     rest_method(put_url, "PUT")
 
+def enable_waypoint():
+    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/inflows/enable/' 
+    rest_method(put_url, "PUT")
+
+def disable_waypoint():
+    put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/inflows/disable/'
+    rest_method(put_url, "PUT")
+
 # Add waypoint IP to an affinity link.
 def main():
     global h
@@ -99,6 +107,8 @@ def main():
     list_all_hosts()
 
     set_waypoint_address()
+    enable_waypoint()
+    disable_waypoint()
 
 #if __name__ == "__main__":
 #    main()