Forum Discussion
Smart way to convert a PoolMemberDefinitionSequenceSequence to a IPPortDefinitionSequenceSequence
Hi,
I want to dump out (and eventually read in and set) the enabled state of each of my GTM pools pool members. Its easy to get a list of the pools and pool members, but the PoolMember.get_enabled_state requires input parameters of the pools (simple) and a Common.IPPortDefinitionSequenceSequence. I'm having trouble figuring out the best way to programmatically get an IPPortDefinitionSequenceSequnce to pass in.
I have a PoolMemberDefinition named poolmembers loaded as follows:
wideips = wipobj.get_list()
pools = poolobj.get_list()
poolmembers = poolobj.get_member(pools)
I want to get the enabled state of each of the poolmembers. I should be able to loop through the poolmembers object and strip out each poolmember address and port and save it to another object (which would then be of type IPPortDefinition), but is that the best way?
thanks,
andy
21 Replies
- L4L7_53191
Nimbostratus
Ok - this should get you close. My brain is a bit fried so there are probably more optimizations available. Note that I added the little stub class just for some sane data structures that we can access via attributes. This is probably slower than other methods, but to me it's cleaner...wipobj = b.GlobalLB.WideIP poolobj = b.GlobalLB.Pool poolmemobj = b.GlobalLB.PoolMember wideips = wipobj.get_list() pools = poolobj.get_list() poolmembers = poolobj.get_member(pools) class DataHolder(): ''' A dummy class to set attrs against for ease of reading ''' def __init__(self, tup): self.pool = tup[0] self.members = self.clean_members(tup) self.member_states = [] def clean_members(self, tup): return [x.member for x in tup[1]] combined = zip(pools,poolmembers) data_list = [] print out pool name, and its members. for x in combined: data_list.append(DataHolder(x)) print "Pool: %s" % x[0] print "\t Mems:" for y in x[1]: print "\t=>%s:%s" % (y.member.address,y.member.port) Now, we've got the IPPort definitions already defined, per pool found inside the data_list[idx].members attribute. We can pass that array into a Commoon.IPPortSequence.items[] array and get the status. pmemseq = poolmemobj.typefactory.create('Common.IPPortDefinitionSequence') pmemseq.item = [x.members for x in [y for y in data_list]] member_status = poolmemobj.get_enabled_state(pool_names = [x.pool for x in data_list], members = [pmemseq])
Once you nail down a final version, would you mind posting it back?
Thanks!
-Matt - I will post it for sure. thanks for your help!
- i don't really understand the shortcuts you've taken with the for loops here:
pmemseq.item = [x.members for x in [y for y in data_list]]
member_status = poolmemobj.get_enabled_state(pool_names = [x.pool for x in data_list], members = [pmemseq])
what would each of these look like expanded? whats a good python reference keyword i can search on to see these explained?
it looks like the reverse of nested for loops, which is what i was working on except i couldn't figure out how to create a sequence of IPPortDefinition i could then assign via the '.item' method(?)
so for example, would [x.members for x in [y for y in data_list]] expand similar to:
for y in data_list:
for x in y
?? - L4L7_53191
Nimbostratus
Have a look at 'list comprehensions'. They're extremely handy in situations like this. Think of them as an easy way to create a list from another iterable after you've manipulated it in some way. Similar to map(). So expanded, this:
[x.pool for x in data_list] translates to something like:
for x in data_list:
x.pool
but it returns a list of the returned items, not the items individually. That second comprehension is nested, and they'll bend your mind if you're coming into them new. I usually avoid nested comprehensions but for some reason it felt natural to do it in your case.
So you're dead right:the purpose of: [x.members for x in [y for y in data_list]] is to essentially get a the members attribute of the returned objects from get_member(). I needed a way to flatten out that list to nothing more than the pool members as defined by their IPPortDefinitions.
-Matt
-Matt - mytestpool1 is the first pool in the list (e.g. data_list[0].pool) and its members are 1.1.1.1:80 and 1.1.1.2:80
mytestpool2 is the 2nd pool in the list, e.g. data_list[1].pool and it members are 1.1.2.10:80 and 1.1.2.11:80
maybe for each pool the code is trying to iterate every poolmember defined in poolmemseq?
so first it tries with pool mytestpool1 and gets the state for member 1.1.1.1:80 and then 1.1.1.2:80 both of which are valid (and no errors are raised). and then it tries the same pool with pool member 1.1.2.10:80 which is NOT a valid pool member of that pool and the script exits with the error 'pool member was not found' Note - i edited this post after some investigation/testing.
ok, so i'm pretty sure the problem lies with the nested list comprehension you are using to define the pmemseq.it looks like the pmemseq is really a flat list- If it was an IPPortDefinitionSequence, shouldn't i be able to access each object using an index?
i.e. using my pool examples from above shouldn't i be able to do this:
pmemseq.item = [x.members for x in [y for y in data_list]]
pmemseq[0][0].address ?
instead i get an error:
In [316]: pmemseq[0][0].address
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
C:\Windows\system32\ in ()
IndexError: string index out of range
if i just dump out pmemseq it does contain data, but I can't seem to get to it via indices as i would expect:
In [326]: pmemseq
Out [326]:
(Common.IPPortDefinition){
address = "10.1.1.1"
port = 80
},
(Common.IPPortDefinition){
address = "10.1.1.2"
port = 80
},,
(Common.IPPortDefinition){
address = "10.1.2.10"
port = 80
},
(Common.IPPortDefinition){
address = "10.1.2.11"
port = 80
},,
}
- L4L7_53191
Nimbostratus
Yes, there's an ordering bug somewhere. I've got a few minutes to test at lunch, will post back what I fiind. The first call is accurate:
Pool: pc_test_pool2
Mems:
=>2.2.2.2:80
=>2.2.2.3:80
Pool: pc_test_pool
Mems:
=>1.1.1.1:8888
Pool: pc_test_pool3
Mems:
=>3.3.3.3:3333
=>3.3.3.4:4444
But something is going on with that second call. I'll update soon.
-Matt - a side question - is there an append or similar method to the .item call of an object (e.g. IPPortDefinitionSequence)? I'd like to loop through and add objects to the sequence one at a time. or do you have to build the whole list first and then assign? (which is the only use case i've seen in examples)
- L4L7_53191
Nimbostratus
To answer the side question: the items[] thing is simply an attribute you set against the sequence objects. It coerces suds into setting up the xml correctly to pass in a list of ojects. Any Sequence item (as opposed to sequencesequence) requires that this attribute is set. It's just a normal list, so any list method will work - append, index lookups, etc.
-Matt - brilliant! yes that works perfectly. and it was the 'sequence_factory' piece that was outside of my mental grasp. thank you very much for all your help!
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
