Forum Discussion

ML_108504's avatar
ML_108504
Icon for Nimbostratus rankNimbostratus
May 11, 2012

Most efficient way to re-prioritize a virtual server's iRules?

Hi folks,

I'm writing a powershell script to add and remove a maintenance page redirect iRule to the top of a given virtual server's iRule list (TMOS versions 9.4.x and 10.x). Any given virtual server that this script would run against would already have a list of iRules applied to it.

To my chagrin, it appears that there's no way to directly change the priority of iRules already assigned to a virtual server, so it seems that I have to:

1. dump the existing list of iRules (and their original priorities) to a 2-dimensional array (storing .rule_name and .priority)

2. add 1 to the value of all their priorities

3. add the maintenance page redirect iRule to the virtual server (with a priority of 0)

4. add back all of the original iRules with their modified priorities

5. do the reverse when it's time to remove the maint page redirect iRule

NOTE: I could store the original irule names and priorities, NOT change their priorities, and then just add them back after removing the maint page redirect iRule, but then I'd need to reliably store the original iRule information somewhere where ANYONE on the team can re-apply the original iRules from any of a number of different workstations, and it's just not worth the additional complexity. By leaving all of the original iRules applied to the virtual (with modified priorities) it's easy for any admin running the script to remove the maint redirect iRule at any time, from any of their workstations. Anyway ...

I was going to simply dump the results of this query to a 2-dimensional array, but the results appear to come back as one field:


PS C:\> $rule_list = (Get-F5.iControl).LocalLBVirtualServer.get_rule((, $vs_name))
PS C:\> $rule_list | Format-Table -AutoSize
rule_name priority
--------- --------
iRule_go2_tst_icontrol_pageA 0
iRule_go2_tst_icontrol_pageB 1
PS C:\> $rule_list.count
1

Can anyone please suggest the most efficient way to do this sort of iRule priority swapping via iControl and Powershell?

Thank you!
  • George_Watkins_'s avatar
    George_Watkins_
    Historic F5 Account
    Hi ML,

    Here's a little trick that might help. All iRules have a global priority and their individual events have priorities as well. By default, this priority is 500 if it is not defined in the iRule. If no priority are defined, then the iRules are executed based on the order in the web UI. If a lower priority (say 100) is defined for an iRule or its events, they will be executed before those with lower priorities regardless of their position in the list. There is a fair amount of documentation on the priority command in the DevCentral iRules Wiki.

    What I would do is just set a higher priority for the maintenance iRule and then just add it to begin maintenance,and delete it from the virtual server to end maintenance. The iRule might look like this:

    priority 100
    
    when HTTP_REQUEST {
        HTTP::redirect "http://mysite.com/maintenance.html"
    }

    You can then just use the LocalLB::VirtualServer::add_rule and LocalLB::VirtualServer::remove_rule methods to add and delete the iRule. You can put the iRule in any order and it should always fire first.

    Hope that helps,

    -George
  • Thanks for the reply watkins!

     

     

    iRules added via the GUI (at least in version 9) don't have a default priority of 500, from what I can see, so I can't count on that. When I create a new test VS, with no iRules, and add a single iRule to the VS using the GUI, the priority is 0. If I add a second iRule below the first one, the priority is 1.

     

     

    Are we talking about different priorities specified in different places? If I assume that the priority values returned by .get_rule (0 for the pageA iRule and 1 for the pageB iRule, as per my code block above) are actually some kind of different priority value than that default priority of 500 that is persumed defined in the iRule itself, then are you saying that I can add my maint iRule to the bottom of the list (i.e. priority 2 according to .get_rule output above), but as long as I have priority 100 in my maint iRule (and all other iRules are assumed to be the default of 500) then my main iRule will fire w/higher priority?

     

     

  • George_Watkins_'s avatar
    George_Watkins_
    Historic F5 Account
    Yes, the priorities that are returned from iControl are the GUI orderings, which are different from priorities defined in an iRule. Both determine the order of execution, but the Gui order is only used to resolve equal priorities in multiple iRules. The iRules priority command that I am referencing changes the internal priority in which the iRules are executed and takes precedence over the GUI ordering.

     

     

    Since you don't have any priority defined in the iRule code, we can assumed that all the iRules have an equal priority of 500 therefore they'll fallback to the GUI ordering (the 1,2,3, etc. you're seeing in iControl) that you are seeing in iControl. If however you add "priority 400" to the top of any iRule and then place it at the bottom of the list in the GUI, it will still be executed first because it has a higher internal priority. The other iRules that still have a default (and equal) priority they will execute their events in the GUI order after each of the priority 400 iRule's events are completed.

     

     

    Likewise, if an iRule with priority 900 is at the top of the list, it will still be executed last if there are no lower priority rules.

     

     

    If you have a desired order for all your iRules, you can add priorities to the top of all of them, then when they're added to the GUI it won't matter what order they are in because they'll always fire in the right order. I apologize if I just confused you more,

     

     

    -George

     

  • OK, bit of follow up here and more questions.

     

     

    I have added priority 100 statements to all of my outage iRules. All other non-outage iRules have no custom priority set, and should therefore have default priorities of 500. My script code can add and remove the outage irules to the iRule list for any given virtual server. I only need to add one outage iRule to any given virtual server during any given outage scenario. So far so good.

     

     

    I am attempting to use event disable statements in my outage iRules to ensure that only the outage iRule is evaluated and run for any given connection. That seemed to work just fine in my testing environment (which used dummy virtual servers that had simple iRules applied that just sent http redirects or sent simple html pages back to client browsers). However, in my integration environment (which has slightly more complicated iRules applied to virtual servers) the event disable statements in my outage iRules did not seem to achieve the desired result. My outage iRule would send an http::redirect to any incoming clients and, presuma bly, cease processing any further iRules because my outage iRule ends with an event disable statement.

     

     

    However, the outage redirect did not seem to work as desired. I received page not found errors instead of the simple html "sorry" page that the http::redirect statement redirected to. When I put the URL that the http::redirect statement returns, the "sorry" page comes up fine. When I hit my test virtual servers that have the outage iRule (with priority 100) and the day-to-day iRule (assumed default priority 500), I do not get the "sorry" page. The iRule that is applied to the virtual servers in question here is essentially just a large switch block, that directs clients to certain pools based upon URI.

     

     

    I'm assuming that the event disable statement at the end of my outage iRule is all I should need to have the bigip skip processing the day-to-day iRule after processing my outage iRule http::redirect. Is there some other way to ensure that, if two iRules are applied, one with priority 100 and one with priority 500, only the priority 100 iRule will be processed?

     

     

    Perhaps I should post some example script blocks up here to clarify, I'll get on that after this post.

     

     

    Thanks!

     

     

     

     

  • OK, here is the essence of my outage iRule:
    
    priority 100
    when HTTP_REQUEST {
      HTTP::redirect "http://www.outagesite.com/dir/sorrypage.html"
      event disable
    }

    And here is the essence of my "day-to-day" iRule that is applied to the virtual servers that I am testing:
    when HTTP_REQUEST {
      set host "wwwt.testsite.com"
      set Dir1 [string tolower [getfield [HTTP::uri] "/" 2]]
      set Dir2 [string tolower [getfield [HTTP::uri] "/" 3]]
    switch -glob $Dir1 {
      "uri_A" -
      "uri_B" -
      "uri_C" { pool p_test_A_http }
      "uri_D" -
      "uri_E" { pool p_test_B_http }
      "uri_F" {
        switch -glob $SCEDir2 {
          "uri_X" -
          "uri_Y" -
          "uri_Z" { pool p_test_X_http }
          }
        }
        default { pool p_test_Z_http }
    }
    }
    When I browse to the redirect URL directly (http://www.outagesite.com/dir/sorrypage.html), the sorry page comes up fine.

    When I hit a virtual server that has both the outage iRule (priority 100) and the "day-to-day" iRule (assumed priority 500), then I get a 404 not found.

    The question: am I correct in assuming that the combination of setting priority 100 to the outage iRule and using event disable in that outage iRule should result in the "day-to-day" iRule not executing for any inbound request? Is there a better way to ensure that the "day-to-day" iRule will not execute when the outage iRule is applied?

    Thanks!