Forum Discussion

ottleydamian's avatar
Jan 16, 2019

Create a node based on an event

From my research I believe what I need is an iCall. But as per my other DevCentral post I'm not sure how to actually implement an iCall: HowTo: iCall Question

 

The task: An HTTP request has the fqdn of a node in the URI. If the node exist forward the request to the node but if the node doesn't exist create an fqdn node and then forward the request.

 

My thoughts: In an iRule extract node's fqdn from the HTTP request (simple enough). Then with a mixture of iRule syntax and iStats/iCall compare fqdn with the current nodes in a particular pool. If it doesn't exist use iCall to create an fqdn node, add it to the pool and send it the request. Is this possible with iCall? If yes, what would the syntax be?

 

3 Replies

  • Hi ottleydamian,

    dont think iCall would be a good choice for your requirement.

    ISTAT based triggers adding some (unpredictable) latency and LOG based triggers wont be able to pass the entire log-line (including the requested HOSTHEADER) to your iCall scripts.

    It would be far more stable and elegant to SIDEBAND out of your iRule to F5's REST-API and create a new pool member or to use DevCentrals "Action On Log" contribution (https://devcentral.f5.com/codeshare?sid=430) to automate the pool member creation.

    Beside of this, what is the purpose of having those pool members in place? You could also perform a a simple DNS lookup (after visiting DNS-Caches) within your iRule and then forward the traffic based on the DNS responses.

    when HTTP_REQUEST {
         Extract the HOSTNAME value...
        set fqdn [URI::query [HTTP::uri] hostname]
         You may want to add some additional tests to make sure the passed HOSTNAME values are legit!!!!
        if { $fqdn ne "" } then {
            if { [set resolved_ip [table lookup "dns_cache_$fqdn"]] ne "" } then {
                 Found a cached DNS response...    
                node $resolved_ip
            } else {    
                 Need to DNS resolve the IP address
                if { [set resolved_ip [lindex [RESOLV::lookup @8.8.8.8%1 -a $fqdn] 0]] ne "" } then {
                     Found an IP address. Updating DNS cache (for 60 sec) and forwarding the request to the just resolved IP.
                    table set "dns_cache_$fqdn" $resolved_ip indef 60
                    node $resolved_ip
                } else {
                     HOST not found...
                    HTTP::respond 200 content "HOST not found..." "Content-type" "text/html"
                }
            }
        } else {
             Empty hostname param...
            HTTP::respond 200 content "Empty hostname value..." "Content-type" "text/html"  
        }
    }
    

    Cheers, Kai

  • if the goal is to add the node to a pool, then yes, you'll need something like iCall to do that. If you just want to forward the request to the node and not have BIG-IP "manage" that node as a pool member with health monitors, then you can just do that straight up in an iRule. Assuming you are handling the fqdn extraction from the uri, a header, or the payload, it's pretty basic:

     

    when RULE_INIT {
      set static::ldns "x.x.x.x"
    }
    
    when HTTP_REQUEST {
      set node_fqdn "your code to get fqdn here"
      set node_ip [RESOLV::lookup @$static::ldns -a $node_fqdn]
      if {$node_ip eq ""}{
         didn't resolv, send to default pool?
      } else {
           multiple ip's possibly returned, this covers string and list scenario
          node [lindex $node_ip 0]
      }
    }
  • Hey Ottleydamian,

     

    As I already said in my previous post, iCall is unfortunately not the right choice for your scenario.

     

    The problem with iCall in its current form is, that you can't syncronouly trigger an iCall script out of an iRule, while passing parameters/variables to the script execution and to get return information back once the script is executed.

     

    iCall is basically an asyncronouly operating framework which can trigger based on time, log events and ISTATS statistic counters. iCall has some awesome usecases, but in your specific scenario it would be a rather poor choice:

     

    • Triggering iCall scripts out of an iRule via iRule generated log-lines does not support to pass parameters based on dynamic information found in the log line itself (e.g. which NODE to add?). The executed iCall script would need to read the entire log file to begin with and extract the NODE information out of the individual log lines that may have triggered this script. You would need to implement a custom machanism to track which log lines have already been processed by previous iCall executions and which are outstanding. Kind of nightmare...
    • Triggering iCall scripts out of an iRule via ISTATS counter values adds unfortunately some delay till ISTATS collects and updates the counters (highly asynchronous) and you get no response back when the node has been added. So the iRule would need to HOLD the ongoing HTTP request and continiously check if the iCall script has already been added the pool members. In addition, you would be forced to implement some queuing logic, to support concurrent client side requests for new node objects. This is way to complex...

    As I already said, it's far more elegant to make a syncronous SIDEBAND request to the REST-API and execute a TMSH script, pass the NODE info via additional parameters, wait for the REST-API response and evaluate the return'ed information.

     

    PoC for changing DATA-GROUPS via TMSH Scripts out of an iRule via REST-API calls. https://devcentral.f5.com/questions/write-into-internal-data-group-from-irule-50597

     

    This may be usefull if you want to execute BASH commands (including native TMSH commands) out of an iRule via REST-API calls. https://devcentral.f5.com/questions/running-bash-commands-via-rest-api-51527

     

    Cheers, Kai