Forum Discussion

Narendra_26827's avatar
Narendra_26827
Icon for Nimbostratus rankNimbostratus
Jul 07, 2011

iRule to read key/value pair from Data Group lists

We have a requirement with our product that load balancer should be able to send requests to a particular pool ip based on a configuration file that we should have in the load balancer. Example:

 

 

- We have a VIP and pool of 3 app nodes behind the vip. e.g. vip=192.168.1.10:443 and the app nodes behind this vip are 192.168.1.11:80, 192.168.1.12:80 and 192.168.1.13:80

 

 

- We need to have a config file (may be data group lists) in load balancer that will be a key/value file. So the file will have entries as

 

sample1=192.168.1.11

 

sample2=192.168.1.12

 

sample3=192.168.1.13

 

 

- Each requests comes to the VIP and the request has a header with value for that would be sample1 or sample2 or sample3

 

 

- When the request comes to the VIP, we will have a irule that reads the header and has the header value stored to a variable like

 

 

sample=sample1

 

 

Here sample is the variable and sample1 is the value read from the header

 

 

- Now, irule need to read the config file and see what ip the variable is mapped to. In this case,

 

 

sample1=192.168.1.11

 

 

- So, the request that has come now to the VIP should be routed to the pool ip 192.168.1.11:80

 

 

Cany anybody help or provide any suggestions for the above condition iRule.

 

 

 

Thanks.

 

  • to be clear, sample=sample1 will be passed as some type of http header, or will sent as part of a HTTP POST or GET?
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account

    So all you're looking for is to look up a custom header value in a Data Group and have that map to a pool member address. That's very doable. You'd want something like:

     

    
    when HTTP_REQUEST {
      if {[HTTP::header exists "myCustomHeader"]} {
        set member [class match -value [HTTP::header "myCustomHeader"] equals myClassName]
        if {$member ne ""} {
          pool member $member 80
        }
      }
    }
    

     

    This would require a data group named myClassName that looks like you described above, sample1 with a value of 192.168.1.11, sample2 with a value of 192.168.1.12, etc. and it assumes the custom header is named "myCustomHeader" with the values of sample1, sample2, etc.

    You can, of course, change any of the variable or data group names to be more to your liking.

    Colin

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Yeah, that should be fine. If there's a header that contains the value, the above rule should work once you put in the right names for the header and create the data group, alter the data group name in the iRule, etc.

     

     

    Colin
  • Thanks Colin.

     

     

    Can you suggest me how do i read the "sample1" key only from the data group lists not its value (192.168.1.10:80) in the iRule.

     

     

    What i am trying to do is i am creating a class called sample_list

     

     

    class sample_list {

     

    {

     

    "sample1" {"192.168.1.10 80"}

     

    "sample2" {"192.168.1.11 80"}

     

    }

     

    }

     

     

    Now from iRule i want to read only key first ("sample") from class sample_list so after reading "sample1" i will get the appropriate value "192.168.1.10 80"

     

    what i am trying

     

     

    set key $::sample_list

     

    set value [class match -value $key contains sample_list]

     

     

    If i get the key with associated value after reading class i can redirect them to appropriate pool member (via value)

     

     

     

    Thanks.
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    If you just want the name of the key you can use the -name option. You can also read more about the class command here - Click Here

     

     

    Colin
  • I always like to check that the value of a header or cookie is not null instead of checking to see if it exists before trying to use the value. It's an odd corner case to check for, but I've seen a few rules break by assuming the header or cookie will have a value if it's present.

     

    
      if {[HTTP::header "myCustomHeader"] ne ""} {
        ...
    

     

    If the header isn't set, the header command will return a null string. You don't have to worry about an error if the header doesn't exist.

    Aaron

  • Thanks Aaron i will take that note into consideration.

     

     

    Edit:

     

     

    Now actually for testing purpose i have created the sample class like this

     

     

    class sample_list {

     

    {

     

    "test1.html" { "192.168.159.128:80" }

     

    "test2.html" { "192.168.159.129:80" }

     

    }

     

    }

     

     

    and iRule like this

     

     

    when HTTP_REQUEST {

     

    set key [class match -name [string tolower [HTTP::uri]] contains sample_list]

     

    set value [class match -value $key contains sample_list]

     

     

    if { $key eq "test1.html" } {

     

    pool Pool1_128 member $value

     

    } elseif { $key eq "test2.html" } {

     

    pool Pool1_128 member $value

     

    } else {

     

    HTTP::redirect "http://www.google.com"

     

    }

     

    }

     

     

    vip is 192.168.159.130

     

     

    http://192.168.159.130/test1.html should be served by 192.168.159.128:80 and http://192.168.159.130/test2.html by 192.168.159.129:80 respectively.

     

     

     

    Am i doing anything wrong in the above scenario. If you can kindly suggest. I have created this just to test the functionality.

     

     

    Thanks.
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Well, I can tell you that the pool member command is expecting either no port, or a port as a third argument. I'm not sure how well it's going to handle having the port tacked on with a colon. You might need to use split to separate the IP and port and pass them in separately, but that's pretty easy.

     

     

    Other than that your logic looks relatively solid. You could probably change your "contains" operators to "ends_with" operators, assuming the test1.html and test2.html pages will always be the end of the URI. Frankly you could change HTTP::uri to HTTP::path to ensure that even if there is a query string it doesn't get considered, if you're trying to identify the particular page in question, not the query string. (More on path here: Click Here )

     

     

    Also I'm still a bit unclear as to why you're doing a class match -name followed by a class match -value. By definition if you do a class match -value that results in anything other than an empty string you know that you have a valid name to start with, as only a valid name will result in a value response. Unless you're intending to do a -name search with a portion of a name value, and want to have it return the full value for some reason, I suppose.

     

     

    Anyway, enough of my meanderings...looks good so far. ;)

     

     

    Colin