Forum Discussion

Twirrim_94896's avatar
Twirrim_94896
Icon for Nimbostratus rankNimbostratus
Mar 29, 2011

struggling to create irules

I'm using python 2.6.6 and pycontrol 2.0.1 to connect to our load balancer and configure it. I'm trying to make a rough start at creating a standard provisioning script for any new subdomains that are set up. I like python/pycontrol in general it's proving fairly easy and simple to get things rolling (particularly in comparison to the usual PITA that seems to go with Perl & APIs), I'm able to pull all sorts of data from the LBs with ease.

I'm going to keep hacking away at this and will update if I manage to solve this in case it's useful to others. The examples I've been able to find so far don't seem to show python creating irules.

!/usr/bin/python

Import pycontrol and connect to loadbalancer

import pycontrol.pycontrol as pc

myLTM = pc.BIGIP(

hostname = 'serv.er.addre.ss',

username = 'admin',

password = 'password',

fromurl=True,

wsdls = ['LocalLB.Rule'])

Provide rl as a shortcut to the rules service

rl=myLTM.LocalLB.Rule

Query the user for the domain

appname = raw_input("Enter new application/subdomain name:")

Generate the content of the new iRule

irules_content = []

irules_content.append(u' Rule generated for %s' % appname)

irules_content.append(u'when HTTP_REQUEST {')

irules_content.append(u' Check if Host header is %s.ourdomain.com' % appname)

irules_content.append(u' if {[HTTP::host] eq "%s.ourdomain.com"}{' % appname)

irules_content.append(u' use %s pool' % appname)

irules_content.append(u' pool %s_pool' % appname)

irules_content.append(u' }')

irules_content.append(u'}')

Combine it all into a single \n separated string

irules_content = '\n'.join(irules_content)

Define the name for the iRule

irule_name = appname+"_redirect"

Print to screen

print irule_name

print irules_content

Attempt to create rule

rl.create(rule_name = irule_name, rules = irules_content)

Double check for sanity

double_check = rl.query_rule(rule_names = [irules_name])

print "\nCreated iRule:\n"

print double_check[0].rule_definition

Whilst rl.create appears to work, no exception is reported, double_check fails telling me the requested rule wasn't found. I don't see any way to commit changes to the interface. I'm sure it's the "rules = " bit that is wrong, if I use rule_definition that I'd expect to use there, it fails telling me rules wasn't there:

"WebFault: Server raised fault: 'Could not find element by name: rules'"

edit: Really not keen on this forum software.. just doesn't want to accept code tags around the code, seems to expect me to prepend [ code ] to every line?! (minus the spaces)

  • Bah.. after struggling with this for a good while today, inspiration struck just after posting this..

    Need to define a dictionary (dict) object and pass that to the iRule create command:

     

     Attempt to create rule
    irule_def = dict(rule_name=irule_name,rule_definition = irules_content)
    rl.create(rules=[irule_def])

     

  • Nicely done. If you've not gone through it up until now, you may want to go through the typefactory screencast that I did a while back to help get folks up to speed on how pycontrol/suds handles types. You've discovered, as have a couple of other folks, that Suds will take a normal python data structure and try to do the right thing with it. IIRC, this isn't completely consistent though, especially with nested types. So I always use the typefactory, which is much more explicit...

     

     

    Anyhow, here's an example that may be useful for you (done via an iPython interactive shell session). It may save you a few lines of code.

     

    In [18]: r.create.params
    Out[18]: [(rules, u'LocalLB.Rule.RuleDefinitionSequence')]  This is the data structure we need to pass into the create call. Let's create the LocalLB.RuleDefinition object...
    In [19]: r_def = r.typefactory.create('LocalLB.Rule.RuleDefinition')
    In [20]: print r_def
    (LocalLB.Rule.RuleDefinition){
       rule_name = None
       rule_definition = None
     }  This shows us what attributes we need to tickle to pass in the call. Let's do that now...
    In [21]: r_def.rule_name = 'YOYO_pyControl'  The name of the rule. Now we'll actually add the iRule code.
    In [22]: raw_code = '''
       ....: when HTTP_REQUEST {
       ....:        log local0. "Python - I can fly!!"
       ....: }'''  Now we'll add this to our object's rule_definition attribute...
    In [23]: r_def.rule_definition = raw_code  Now we'll add it to BigIP...
    In [24]: r.create(rules = [r_def])  Notice to create a 'sequence' I just treat it like a list. Let's see if it saved!
    In [25]: r.get_list()
    Out[25]:
    [ _sys_APM_activesync,
     _sys_auth_ssl_cc_ldap,
     _sys_auth_krbdelegate,
     _sys_https_redirect, YOYO_pyControl,
     _sys_auth_ssl_crldp,
     _sys_auth_ssl_ocsp,
     nextgen-test,
     connection-limit,
     nextgen-dg-acl]
    Thanks for the post and I look forward to hearing more about your project!

     

    -Matt Cauthorn