Forum Discussion

Julian_44743's avatar
Julian_44743
Icon for Nimbostratus rankNimbostratus
Nov 23, 2010

iNotes irule for v. 10.2.0 with HF2

Hi all,

 

 

Please forgive my noobness. I've been trying to get the irule for IBM Louts iNotes as published in the F5 deployment guide to work (http://www.f5.com/pdf/deployment-gu...tes-dg.pdf), with little success. I found that some of the syntax doesn't seem to work in v. 10.2.0, and I've rewritten a bunch during my debugging.

 

 

Anyway, what's supposed to happen is the client logs into the Lotus Notes redirector, which redirects them back to the virtual server with the uri of the user's mailbox. When the iRule sees that uri, it opens a ServersLookup Form on the inotes server to determine which pool member to redirect the traffic to. I got the iRule to successfully get the correct pool member, but for some reason, the connections don't appear to be persisting correctly after selecting the pool member. Can you help? What follows is my config (modified from the original code and sanitized). Again, sorry if I'm committing any nooby crimes.

 

 

profile persist inotes-cookie-persistence-profile-1 {

 

defaults from cookie

 

mode cookie

 

cookie mode insert

 

cookie name "inotes-cookie"

 

cookie expiration immediate

 

}

 

 

 

pool xnotes-inotes-pool-1 {

 

members {

 

192.168.100.1:http {

 

monitor xnotes-http-monitor-1

 

}

 

192.168.100.2:http {

 

monitor xnotes-http-monitor-1

 

}

 

}

 

}

 

 

virtual inotes-test-virtualserver {

 

snat automap

 

pool xnotes-inotes-pool-1

 

destination 192.168.1.1:http

 

ip protocol tcp

 

rules inotes-xnotes-irule-1

 

persist inotes-cookie-persistence-profile-1

 

profiles {

 

inotes-optimized-http-profile-1 {}

 

inotes-tcp-lan-profile-1 {

 

serverside

 

}

 

inotes-tcp-wan-profile-1 {

 

clientside

 

}

 

}

 

}

 

 

rule inotes-xnotes-irule-1 {

 

when RULE_INIT {

 

set static::xnotes1fqdn xnotes1.mydomain.com

 

set static::xnotes2fqdn xnotes2.mydomain.com

 

set static::xnotes1IP 192.168.100.1

 

set static::xnotes2IP 192.168.100.2

 

log local0. "got RULE_INIT"

 

}

 

 

when CLIENT_ACCEPTED {

 

log local0. "got CLIENT_ACCEPTED."

 

set gotserver 0

 

set retries 0

 

}

 

 

when HTTP_REQUEST {

 

log local0. "have request for [HTTP::uri]"

 

log local0. "retry count = $retries" log

 

local0. "gotserver count = $gotserver"

 

 

if { $gotserver == 0 and $retries == 0 } {

 

if { ([HTTP::uri]ends_with "OpenDatabase") and not ([HTTP::uri] contains "names.nsf") and not ([HTTP::uri] contains "iwaredir.nsf")}{

 

set original_request [HTTP::request]

 

set nsf "[substr [HTTP::uri] 1 ".nsf"].nsf"

 

log local0. "setting nsf: $nsf"

 

HTTP::uri /iwaredir.nsf/ServersLookup?OpenForm&nsfpath=$nsf

 

log local0. "setting uri: /iwaredir.nsf/ServersLookup?OpenForm&nsfpath=$nsf" }

 

else { do nothing }

 

} elseif { $gotserver == 1 and $retries >= 1 and [LB::status pool xnotes-inotes-pool-1 member $dest 80 ] eq "up"} {

 

log local0. "I should be directed to $dest with some kind of persistence"

 

pool xnotes-inotes-pool-1 member $dest 80

 

persist cookie insert inotes-cookie

 

log local0. "persist cookie should have been set"

 

}

 

}

 

 

when HTTP_RESPONSE {

 

if { $gotserver == 0 } {

 

if { [HTTP::header exists X-Domino-ClusterServers] } {

 

log local0. "X-Domino-ClusterServers headers exist."

 

set server_list [split [HTTP::header X-Domino-ClusterServers], ,]

 

foreach {svr} $server_list {

 

if { "" ne $svr }{

 

set servername [string trim $svr]

 

log local0. "servername is $servername"

 

if {$servername equals $static::xnotes1fqdn} {

 

set dest $static::xnotes1IP

 

set gotserver 1

 

log local0. "Had Servername $servername, so set destination to $dest Gotserver = $gotserver"

 

break

 

} elseif {$servername equals $static::xnotes2fqdn} {

 

set dest $static::xnotes2IP

 

set gotserver 1

 

log local0. "Had Servername $servername, so set destination to $dest Gotserver = $gotserver"

 

break

 

} else { log local0. "NO!! We got the wrong servername! ($servername)" }

 

}

 

}

 

if { $gotserver == 1 and [LB::status pool xnotes-inotes-pool-1 member $dest 80 ] eq "up" } {

 

incr retries

 

log local0. "retry count = $retries"

 

HTTP::retry $original_request

 

}

 

} elseif {[HTTP::header exists X-Domino-ReplicaServers]} {

 

log local0. "X-Domino-ReplicaServers headers exist."

 

set server_list [split [HTTP::header X-Domino-ReplicaServers], ,]

 

foreach {svr} $server_list {

 

if { "" ne $svr }{

 

set servername [string trim $svr]

 

log local0. "servername is $servername"

 

if {$servername equals $static::xnotes1fqdn} {

 

set dest $static::xnotes1IP

 

set gotserver 1

 

log local0. "Had Servername $servername, so set destination to $dest Gotserver = $gotserver"

 

break

 

} elseif {$servername equals $static::xnotes2fqdn} {

 

set dest $static::xnotes2IP

 

set gotserver 1

 

log local0. "Had Servername $servername, so set destination to $dest Gotserver = $gotserver"

 

break

 

} else { log local0. "NO!! We got the wrong servername! ($servername)" }

 

}

 

}

 

if { $gotserver == 1 and [LB::status pool xnotes-inotes-pool-1 member $dest 80 ] eq "up" } {

 

incr retries

 

HTTP::retry $original_request

 

}

 

} else {

 

log local0. "We did not get X-Domino-Headers"

 

}

 

}

 

}

 

  • Ok, so I decided to go back to the drawing board on this. Realizing (with some help from a colleague at work - thanks Jim) that the IBM lotus inotes redirector sends a meta refresh tag, I used the code found elsewhere on this site to examine the payload in the HTTP_RESPONSE_DATA and rewrite it as a redirect to the appropriate cluster.

     

     

    Thanks anyways if anyone was looking at this.

     

     

    Cheers,

     

    Julian
  • > but for some reason, the connections don't appear to be persisting correctly after selecting the pool member.

     

     

    Same problem here with BIG-IP 10.2.2 HFA4. We opend a case at F5 with problem descriptions like:

     

     

    'As you can see in the /var/log/ltm, the iRule always selects the correct pool-member (172.28.46.134) but 'http::retry $original_request' is sent to the randomly selected pool member at session start.

     

    So sometimes we get a 'HTTP/1.1 404 Not Found' and sometimes not.

     

    The 'pool [LB::server pool] member $dest' selection seems not to work.

     

    '

     

     

    'Thank you for the hints. We changed the irule and use the pool selection in HTTP_REQUEST.

     

    But that works only for one request.

     

    Similar problem like this: http://devcentral.f5.com/wiki/irules.manual_cookie_persistence.ashx

     

    I think, a new session cookie would solve our problem. Is there a simple way to generate a new session cookie with the right/selected member?'

     

     

    Case ended with statement from F5: 'it could be due to you are running the solution guide in a different version of software not supported by the mentioned guide.' Sad but true... :(

     

     

     

    So we modified the iRule on our own.

     

     

    Can anybody please tell us if the generation of a new session cookie is recommended in this scenario?

     

    And is there a more elegant way than LB::reselect based on 404-Code in the case the server crashes to which the user is connected to?

     

     

    Regards, Matthias

     

     

    iRule:

     

     

    iRule for iNotes-Access with Load Balancer Assistance Service on Notes

     

    based on 'F5 and IBM Lotus iNotes deployment guide Version 1.2' (f5-ibm-inotes-dg.pdf)

     

    which is inoperable with Notes 8.5.2, BIG-IP 10.2.2 and contains faults like missing spaces and HTTP::retry in HTTP_RESPONSE_DATA

     

    see deployment guide for cookie- and 'Data Group List' configuration

     

     

     

    when CLIENT_ACCEPTED {

     

    log local0. "ACC - got new connect"

     

    set retries 0

     

    set server_needed 0

     

    set server_selected "none"

     

    }

     

     

    when HTTP_REQUEST {

     

    when opening Notes database, set server_needed 1

     

    if {([HTTP::uri] ends_with ".nsf?OpenDatabase") and not ([HTTP::uri] contains "names.nsf") and not ([HTTP::uri] contains "iwaredir.nsf") and not ($server_selected == "new") and not ($server_selected == "orig") }{

     

    set original_request [HTTP::request]

     

    set server_needed 1

     

    set nsf "[substr [HTTP::uri] 1 ".nsf"].nsf"

     

    log local0. "REQ - Server needed: $server_needed"

     

    log local0. "REQ - NSF: $nsf"

     

    HTTP::uri /iwaredir.nsf/ServersLookup?OpenForm&nsfpath=$nsf

     

    log local0. "REQ - uri: /iwaredir.nsf/ServersLookup?OpenForm&nsfpath=$nsf"

     

    } else {

     

    set server_needed 0

     

    set original_request [HTTP::request]

     

    }

     

    when HTTP::retry with new server from X-header, select it from pool

     

    if { $server_selected == "new" } {

     

    pool [LB::server pool] member $dest

     

    log local0. "REQ - Using selected new server [LB::server addr] of pool: [LB::server pool] (Destination: $dest)"

     

    }

     

    }

     

     

    when LB_SELECTED {

     

    when HTTP::retry because of 404-Code, reselect member

     

    F5 unit sends a new session cookie

     

    if { ($retries > 0) and ($retries < 9) } {

     

    LB::reselect pool [LB::server pool]

     

    log local0. "SELE - Reselection No. $retries"

     

    }

     

    }

     

     

    when HTTP_RESPONSE {

     

    log local0. "RESP - Used server [LB::server addr] of pool: [LB::server pool]"

     

     

    when 404-Code after automatic reselection of F5 unit to wrong server occurs, do another try

     

    if { ([HTTP::status] == 404) and ($retries < 8) } {

     

    log local0. "ALERT: 404"

     

    incr retries

     

    log local0. "RESP - Retrying original request with reselection No. $retries"

     

    HTTP::retry $original_request

     

    }

     

     

    generate new session cookie (code from DevCentral) after member selection based on X-Headers because the F5 unit does not send one

     

    if { $server_selected == "new" } {

     

    set member "[LB::server addr]:[LB::server port]"

     

    scan $member "%u.%u.%u.%u:%u" a b c d e

     

    set pcookie "[scan [expr ($d<<24)|($c<<16)|($b<<8)|$a] %u].[expr 256*$e].0000"

     

    HTTP::cookie insert name BIGipServer[LB::server pool] value $pcookie path "/"

     

    log local0. "RESP - New persistence cookie sent for $dest"

     

    set server_selected "none"

     

    }

     

    build list of iNotes-Server from X-Domino Header

     

    if { $server_needed == 1} {

     

    set server_list1 [split [HTTP::header X-Domino-ClusterServers], ,]

     

    set server_list2 [split [HTTP::header X-Domino-ReplicaServers], ,]

     

    set server_list "${server_list1} ${server_list2}"

     

    log local0. "RESP - Server_list_Cluster: $server_list1"

     

    log local0. "RESP - Server_list_Replica: $server_list2"

     

    log local0. "RESP - Server_list: $server_list"

     

    HTTP::collect [HTTP::header Content-Length]

     

     

    check if we are already on right server and then set server_selected "orig"

     

    foreach {svr} $server_list {

     

    if { "" ne $svr }{

     

    set dest [class search -value iNotes_ReplicaServer equals "[string trim $svr]"]

     

    if {[LB::server addr] == $dest } {

     

    log local0. "RESP - Already on right server: $dest"

     

    set server_selected "orig"

     

    }

     

    }

     

    }

     

     

    foreach {svr} $server_list {

     

    if { "" ne $svr }{

     

    set dest [class search -value iNotes_ReplicaServer equals "[string trim $svr]"]

     

    when on right server, do HTTP::retry

     

    if { $server_selected == "orig" } {

     

    log local0. "RESP - Retrying original request for original server"

     

    HTTP::retry $original_request

     

    break

     

    }

     

    when server in list is up, do HTTP::retry

     

    if { [LB::status pool [LB::server pool] member $dest 80] eq "up" } {

     

    log local0. "RESP - Status of selected server $dest, pool [LB::server pool]: [LB::status pool [LB::server pool] member $dest 80]"

     

    set server_selected "new"

     

    log local0. "RESP - Retrying original request for new server"

     

    HTTP::retry $original_request

     

    break

     

    }

     

    }

     

    }

     

     

    }

     

    }