GTM version 10 is here! With its arrival, GTM gets more than a fist-full of new iRules commands for you to add to the toolbox.  In this article, we'll take a look at the command syntax and work through some examples.

whoami

Returns the server name for the local GTM.  This example checks for client source and which GTM is handling the request so it can override the wideIP to serve up a specific host entry.

 

when DNS_REQUEST {
  if { ([IP::addr [IP::client_addr]/16 equals 10.10.0.0]) && ([whoami] equals "dc1-gtm01") } {
    host 10.10.1.100
    if { $::debug } { log local0. "GTM is dc1-gtm01, sending to host 10.10.1.100" }
  } elseif { ([IP::addr [IP::client_addr]/16 equals 10.20.0.0]) && ([whoami] equals "dc2-gtm01") } {
      host 10.10.2.100
      if { $::debug } { log local0. "GTM is dc2-gtm01, sending to host 10.10.2.100" }
  }
}

whereami

Returns the datacenter name for the local GTM.  This example is much like the first, only looking at the datacenter instead of a GTM within the datacenter.

when DNS_REQUEST {
  if { ([IP::addr [IP::client_addr]/16 equals 10.10.0.0]) && ([whereami] equals "dc01") } {
    host 10.10.1.100
    if { $::debug } { log local0. "DC is dc1, sending to host 10.10.1.100" }
  } elseif { ([IP::addr [IP::client_addr]/16 equals 10.20.0.0]) && ([whereami] equals "dc02") } {
      host 10.10.2.100
      if { $::debug } { log local0. "DC is dc2, sending to host 10.10.2.100" }
  }
}

uptime

Returns the number of seconds the local GTM has been up.  This can be useful for not answering queries until the GTM has been up for a set number of seconds, allowing it to get synchronized with the other GTM's in the group. 

when DNS_REQUEST {
  if { [uptime] < 300 } {
    discard
    if { $::debug } { log local0. "Request discarded, [whoami] has not passed uptime threshold, [expr 300 - [uptime]] seconds remaining." }
  }
}

Clients will timeout and resolve to one of the other GTM's authoritative for that name, and the log entry will look like this:

Apr  6 11:21:20 local/dc-gtm01 info gtmd[4123]: Rule test03: Request discarded, dc1-gtm01 has not passed uptime threshold, 158 seconds remaining.

members [-list] <pool name> [blue|green|yellow|red|gray]

Returns the number or list of members in the referenced pool.  This command is really flexible.  Returns all pool members as a number or a list, or if you want only a certain state (blue, green, yellow, red, gray) you can specify that too. 

when LB_SELECTED {
  if { $::debug } { log local0. "[members [LB::server pool] green]/[members [LB::server pool]] of the members in pool [LB::server pool] are green." }
  if { $::debug } { log local0. "Green members: [members -list [LB::server pool] green]" }
}

 A quick look in the log shows that the wi_pool has no green members but the il_pool has three:

Apr  6 11:44:41 local/dc-gtm01 info gtmd[2098]: Rule test05: 0/3 of the members in pool wi_pool are green.
Apr  6 11:44:41 local/dc-gtm01 info gtmd[2098]: Rule test05: Green members:
Apr  6 11:44:42 local/dc-gtm01 info gtmd[2098]: Rule test05: 3/3 of the members in pool il_pool are green.
Apr  6 11:44:42 local/dc-gtm01 info gtmd[2098]: Rule test05: Green members: {10.10.20.51 80} {10.10.20.52 80} {10.10.20.53 80}

pools [-list] [blue|green|yellow|red|gray]

Returns the number or list of pools in the wideIP.  This command has the same options as members, just one step up the hierarchy.  You can combine them to iterate through all the virtual servers under the wideIP:

when DNS_REQUEST {
  foreach x [pools -list] {
    foreach y [members -list $x] {
      if { $::debug } { log local0. "Pool is $x, Member is $y" }
    }
  }
}

Now you have all the pool members available in the request

Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is il_pool, Member is 10.10.20.51 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is il_pool, Member is 10.10.20.52 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is il_pool, Member is 10.10.20.53 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is mo_pool, Member is 10.10.21.51 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is mo_pool, Member is 10.10.21.52 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is mo_pool, Member is 10.10.21.53 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is wi_pool, Member is 10.10.22.51 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is wi_pool, Member is 10.10.22.52 80
Apr  6 12:15:34 local/dc1-gtm01 info gtmd[2098]: Rule test03: Pool is wi_pool, Member is 10.10.22.53 80

persist [enable|disable]

Returns the persistence state value.  You can enable/disable as arguments, so if you have a wideIP with persist enabled, you can now selectively disable (or selectively enable if persist is disabled globally):

when DNS_REQUEST {
  if { [IP::addr [IP::client_addr]/24 equals 10.1.1.0] } {
    persist disable
  }
}

This eliminates the need for this workaround described in the wiki, but keep in mind that there is no access to the persist data from the iRules, so other unique LDNS requests cannot be pinned to the same virtual server without another approach.

nodes_up [<virtual server name> | <ip address port>]

Returns the number of up nodes behind a virtual server.  This is to the vip that members command is to the GTM pool, and the pools command is to the GTM wideIP.  If the virtual server is blue, GTM interprets as green and the nodes_up value is 1, even if you have more functional servers in place and serving traffic.  This command gives you the opportunity to make some changes to your selection if the virtual chosen is constrained on resources that other virtuals might not be.  There is an issue passing variables or using memory lookups right now, but it is functional if you use the virtual name or specify literally the IP and port. 

when DNS_REQUEST {
  log local0. "[nodes_up vip01] nodes up on virtual: vip01"
  log local0. "[nodes_up 10.10.20.51 80] nodes up on virtual: 10.10.20.51:80"
}

Which results with a count of your active servers behind an LTM virtual:

Apr  6 12:20:45 local/dc1-gtm01 info gtmd[2098]: Rule test09: 3 nodes up on virtual: vip01
Apr  6 12:20:45 local/dc1-gtm01 info gtmd[2098]: Rule test09: 3 nodes up on virtual: 10.10.20.51:80

 That concludes this look into the new GTM iRules commands.  Users in the community are always discovering new and unique ways to use iRules in ways that were not originally intended, so I fully intend to see some real innovation in the coming months.  Enjoy!