Forum Discussion
iControl + Python + add_member / remove_member
So I'm trying to get a handle on add and remove _member functions using pycontrol (v2).
I can't seem to get add/remove working correctly. Can someone help me out?
Here's what I attempted to hack from a base script
Base: https://devcentral.f5.com/wiki/iCon...ember.ashx
Code attempted:
import sys
import pycontrol.pycontrol as pc
import time
if len(sys.argv) < 7:
print "Usage %s ip_address username password" % sys.argv[0]
print "Usage %s ip_address username password pool_name member action" % sys.argv[0]
sys.exit(1)
a = sys.argv[1:]
POOL = sys.argv[4]
members = [sys.argv[5]]
action = sys.argv[6]
The constructor is similar to the original pyControl.
Note the change from wsdl_files to wsdls, which makes more sense.
b = pc.BIGIP(
hostname = a[0],
username = a[1],
password = a[2],
fromurl = True,
wsdls = ['LocalLB.PoolMember','LocalLB.Pool'])
--------- helper methods below ----------
def member_factory(b, member):
'''
Produces a Common.IPPortDefinition object per member ip:port combination
object per member ip:port combination. Add these to Common.IPPortDefinitionSequence.
args: a pycontrol LocalLB.PoolMember object and an ip:port
combination that you'd like to add.
'''
ip,port = member.split(':')
pmem = b.LocalLB.PoolMember.typefactory.create('Common.IPPortDefinition')
pmem.address = ip
pmem.port = int(port)
return pmem
def session_state_factory(b, members):
'''
Returns session state objects. Returns a list of session state objects with associated
members.
'''
session_states = []
create a type of: 'LocalLB.PoolMember.MemberSessionState'
Inside of this type, you'll see that it expects a pool member as an
attribute. Let's create that, set our attributes (address, port), and add it to sstate
above.
for x in members:
sstate = b.LocalLB.PoolMember.typefactory.create('LocalLB.PoolMember.MemberSessionState')
sstate.member = member_factory(b,x)
sstate.session_state = 'STATE_DISABLED'
session_states.append(sstate)
return session_states
The session state sequence object. Takes a list of 'member session state'
objects.Wrap the members in a LocalLB.PoolMember.MemberSessionStateSequence
sstate_seq = b.LocalLB.PoolMember.typefactory.create('LocalLB.PoolMember.MemberSessionStateSequence')
'item' is an attribute that maps to a list of 'Common.IPPortDefinition' objects.
sstate_seq.item = session_state_factory(b, members)
def disable_member(b, session_objects):
"""
Disable our members in the of session state
objects.
"""
try:
b.LocalLB.PoolMember.set_session_enabled_state(pool_names =
[POOL], session_states = [sstate_seq])
except Exception, e:
print e
sys.exit(1)
def enable_member(b, session_objects):
"""
Enable our members in the of session state
objects.
"""
Note how easy it is to simply 'toggle' the session state now that
we are dealing with object attributes.
for x in sstate_seq.item:
x.session_state = 'STATE_ENABLED'
try:
b.LocalLB.PoolMember.set_session_enabled_state(pool_names = [POOL],
session_states = [sstate_seq])
except Exception, e:
print e
sys.exit(1)
def add_member(b, members):
"""
"""
print repr(dir(b.LocalLB.Pool))
try:
b.LocalLB.Pool.add_member(pool_names = [POOL],
members = members)
except Exception, e:
print e
sys.exit(1)
def delete_member(b, session_objects):
"""
"""
print repr(dir(b.LocalLB.Pool))
try:
b.LocalLB.Pool.remove_member(pool_names = [POOL],
members = members)
except Exception, e:
print e
sys.exit(1)
if action == 'add':
Add an IP:PORT member to a pool
add_member(b, members)
Confirm pool list
res = b.LocalLB.PoolMember.get_session_enabled_state(pool_names = [POOL])
print "States: %s" % res
sys.exit(0)
elif action == 'delete':
Delete an IP:PORT member of a pool
delete_member(b, members)
Confirm pool list
res = b.LocalLB.PoolMember.get_session_enabled_state(pool_names = [POOL])
print "States: %s" % res
sys.exit(0)
else:
print "State: %s not defined" % action
sys.exit(1)
6 Replies
- Brian_Menges_10
Nimbostratus
The full code (I snipped some stuff out that wasn't directly relevent) runs fine without error, but the pool member list isn't modified. So I must be doing something wrong with the add/remove api calls.
- Brian_Menges_10
Nimbostratus
So now I have pool_objects which I construct using pool_factory... but now i'm getting complaints about suds and a reference to address:
def pool_factory(b, members): ''' ''' pobj = [] for x in members: ip,port = x.split(':') pmem = b.LocalLB.Pool.typefactory.create('Common.IPPortDefinition') pmem.address = ip pmem.port = int(port) pobj.append(pmem) return pobj pool_objects = pool_factory(b,members) def add_member(b, pool_objects): """ """ try: b.LocalLB.Pool.add_member(pool_names = [POOL], members = pool_objects) except Exception, e: print e raise sys.exit(1) elif action == 'add': Add an IP:PORT member to a pool add_member(b, pool_objects) Confirm pool list res = b.LocalLB.PoolMember.get_session_enabled_state(pool_names = [POOL]) print "States: %s" % res sys.exit(0) runtime gives No handlers could be found for logger "suds.client" Server raised fault: 'Could not find element by name: address' Traceback (most recent call last): File "modify_member.py", line 235, in add_member(b, pool_objects) File "modify_member.py", line 185, in add_member members = [pool_objects]) File "/usr/lib/pymodules/python2.6/suds/client.py", line 539, in __call__ return client.invoke(args, kwargs) File "/usr/lib/pymodules/python2.6/suds/client.py", line 598, in invoke result = self.send(msg) File "/usr/lib/pymodules/python2.6/suds/client.py", line 633, in send result = self.failed(binding, e) File "/usr/lib/pymodules/python2.6/suds/client.py", line 684, in failed r, p = binding.get_fault(reply) File "/usr/lib/pymodules/python2.6/suds/bindings/binding.py", line 238, in get_fault raise WebFault(p, faultroot) suds.WebFault: Server raised fault: 'Could not find element by name: address' - mhite_60883
Cirrocumulus
So now I have pool_objects which I construct using pool_factory... but now i'm getting complaints about suds and a reference to address:
def pool_factory(b, members): ''' ''' pobj = [] for x in members: ip,port = x.split(':') pmem = b.LocalLB.Pool.typefactory.create('Common.IPPortDefinition') pmem.address = ip pmem.port = int(port) pobj.append(pmem) return pobj pool_objects = pool_factory(b,members) def add_member(b, pool_objects): """ """ try: b.LocalLB.Pool.add_member(pool_names = [POOL], members = pool_objects) except Exception, e: print e raise sys.exit(1) elif action == 'add': Add an IP:PORT member to a pool add_member(b, pool_objects) Confirm pool list res = b.LocalLB.PoolMember.get_session_enabled_state(pool_names = [POOL]) print "States: %s" % res sys.exit(0) runtime gives No handlers could be found for logger "suds.client" Server raised fault: 'Could not find element by name: address' Traceback (most recent call last): File "modify_member.py", line 235, in add_member(b, pool_objects) File "modify_member.py", line 185, in add_member members = [pool_objects]) File "/usr/lib/pymodules/python2.6/suds/client.py", line 539, in __call__ return client.invoke(args, kwargs) File "/usr/lib/pymodules/python2.6/suds/client.py", line 598, in invoke result = self.send(msg) File "/usr/lib/pymodules/python2.6/suds/client.py", line 633, in send result = self.failed(binding, e) File "/usr/lib/pymodules/python2.6/suds/client.py", line 684, in failed r, p = binding.get_fault(reply) File "/usr/lib/pymodules/python2.6/suds/bindings/binding.py", line 238, in get_fault raise WebFault(p, faultroot) suds.WebFault: Server raised fault: 'Could not find element by name: address'- Global variables, evil.
- remove_member is deprecated, use remove_member_v2 for V11 F5
- You pass global members into session_objects function parameter to delete_member... then you don't reference it. Why?
- You pass global 'members' to "remove_member" API call. It's the wrong type -- you are supposed to pass a sequence of IPPortDefinition.
I have a complete solution I've written for my current employer. Would love it if I could just post it but I don't have that freedom at this point. That being said, something like this works:
def f5_build_address_port_seq(b, addressport): addressportseq = b.LocalLB.Pool.typefactory.create('Common.AddressPortSequence') addressportseq.item = addressport return addressportseq def f5_build_address_port(b, address, port): addressport = b.LocalLB.Pool.typefactory.create('Common.AddressPort') addressport.address = address addressport.port = port return addressport def f5_remove_pool_member_v11(b, poolname, address, port): addressport = f5_build_address_port(b, address, port) addressportseq = f5_build_address_port_seq(b, addressport) b.LocalLB.Pool.remove_member_v2(pool_names=[poolname], members=[addressportseq])Then you just run:
f5_remove_pool_member_v11(b, poolname, address, port)
As an aside, if I were doing this from scratch, I'd be using bigsuds and not pycontrol.
- Brian_Menges_10
Nimbostratus
If I didn't mention it before, I'm extremely new to python, however I'm also building off existing (albeit bad) code. My comfort level with this language isn't that high at this point.
Good notes on v11, but we're still working with v10 so the old deprecated api tree applies with add_member and remove_member; not sure if the v2 segments are compatible with v9 and v10 BigIPs.
I'll review what you've posted and see where I can go from there. Thanks.
- mhite_60883
Cirrocumulus
The parameter changes are minor. v11 uses addressport sequence, whereas pre-v11 uses ipportdefinition sequence. - Brian_Menges_10
Nimbostratus
Posted By mhite on 11/21/2012 11:14 AM
- Global variables, evil.
- remove_member is deprecated, use remove_member_v2 for V11 F5
- You pass global members into session_objects function parameter to delete_member... then you don't reference it. Why?
- You pass global 'members' to "remove_member" API call. It's the wrong type -- you are supposed to pass a sequence of IPPortDefinition.
I have a complete solution I've written for my current employer. Would love it if I could just post it but I don't have that freedom at this point. That being said, something like this works:def f5_build_address_port_seq(b, addressport): addressportseq = b.LocalLB.Pool.typefactory.create('Common.AddressPortSequence') addressportseq.item = addressport return addressportseq def f5_build_address_port(b, address, port): addressport = b.LocalLB.Pool.typefactory.create('Common.AddressPort') addressport.address = address addressport.port = port return addressport def f5_remove_pool_member_v11(b, poolname, address, port): addressport = f5_build_address_port(b, address, port) addressportseq = f5_build_address_port_seq(b, addressport) b.LocalLB.Pool.remove_member_v2(pool_names=[poolname], members=[addressportseq])
Then you just run:
f5_remove_pool_member_v11(b, poolname, address, port)
As an aside, if I were doing this from scratch, I'd be using bigsuds and not pycontrol.
mhite,Thanks for your insights with the code snippets. I was able to patch/cobble together the rest of the script required to do the necessary operations for the moment.
As I learn python more in-depth, I'm sure that I'll be able to craft much better code than that currently hacked upon; I don't like using other people's code for the reason that it inhibits my own learning, but deadlines are deadlines and I needed to get something out quick and most of the framework was there with the base script linked to above... just needed to bolt a few extra things on 😃
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
