Forum Discussion
Cynthia_18735
Nimbostratus
May 06, 2008More efficient way to get pool member status per URL using iControl?
I have a perl script that is does the following:
(1) Gets a list of WideIP's from GlobalLB/WideIP
(2) For each WideIP, gets a list of Pool names from GlobalLB/Pool.
Input is an array of WideIP's (from 1)
(3) For each pool name in each WideIP, gets a list of pool members from GlobalLB/PoolMember:
Input is an array with a single pool name.
Output is address and port.
(4) For each address:port in each pool gets enabled/disabled state from GlobalLB/VirtualServer
Inut an Array with a single address and port
for each pool member
Output is enabled/disabled state.
So, this processes as follows:
- Retrieve WideiP list
Start Loop 1:
For each WideIP --> get poolnames
Start Loop 2:
For each Poolname
--> get poolmembers
Start Loop 3:
For each poolmember
--> get VirtualServer states
End Loop 3
End Loop 2
End Loop 1
This results in many HTTP/Soap requests hitting the GTM very quickly. Is there a better way to do this?
11 Replies
- First off, thanks for the amount of detail, that makes things eaasier on this end. Second, why are you getting the enabled state from the GlobalLB.VirtualServer interface? Since you are querying Pool Members, wouldn't you want to use the GlobalLB.PoolMember interface to get those enabled states? I'm going to proceed assuming that you want to use the PoolMember states. If you really want to use those pool members as virtual server states, then just change step 4.
So, here's what I would suggest. I would definitely not loop all of your calls, but make use of the arrays of inputs. You will need to build some new arrays as inputs to the methods, but after it's all said and done, you should only have to make 4 API calls.
1. GlobalLB.WideIP.get_list()
This returns a list of wideips. Pass this into the next method.
2. GlobalLB.WideIP.get_wideip_pool(wideip_list)
This returns a 2-d array of WideIPPool structures, one for each passed in wideip. Take the pool names out of here and build an array that contains all the pool names (pool_names) and pass that into the next method.
3. GlobalLB.Pool.get_member(pool_names)
This returns a 2-d array of PoolMemberDefinition structures containing the pool name and member details. Take each Member addr:port and build an array of Common.IPPortDefinition structures (member_list) containing each pool member's definition. Then pass that array into the following method.
4. GlobalLB.PoolMember.get_enabled_state(member_list)
During this, you may need to do some bookkeeping on where the pool members belong but you should have all the returned structures to do reverse lookups.
Hope this helps...
-Joe - Cynthia_18735
Nimbostratus
Joe, thank you very much for the quick response. I will give your sugggestions a try. I'm not too great at coding complex perl structures, but will see what I can do. I'll let you know how it works out. Thanks again! - Cynthia_18735
Nimbostratus
Joe - I made some progress; however, am having a problem with the following:
$soapResponse = $POOLMEMBER->get_object_status(
SOAP::Data->name(pool_names => [ @mpools ]),
SOAP::Data->name(members => [ @List ])
);
I cannot get this particular call to return anything. No errors, nothing.
In this scenario, mpools equals an array of pool_names.
@List is an array of hashes, containing the following:
$members =
{
address => $address,
port => $port
};
push @List, $members; - The method prototype is the following:
MemberObjectStatus [] [] GlobalLB.PoolMember.get_object_status( in String [] pool_names, in Common__IPPortDefinition [] [] members );
You are passing in 1-d arrays for both paramters. You'll need to convert the second parameter into a 2-d array.
Something like this:$members = { address => $address, port => $port }; push @List, $members; push @Lists, @List $soapResponse = $POOLMEMBER->get_object_status( SOAP::Data->name(pool_names => [ @mpools ]), SOAP::Data->name(members => [ @Lists ]) );
You'll just want to make sure that you do one push on the Lists array for each pool in your mpools array.
-Joe - Cynthia_18735
Nimbostratus
I think I am getting close, but just not quite there yet. I did your suggestion with @List and @Lists variables. @Lists only gets pushed to once for each pool. But, the call still isn't returning anything. I must be missing something. I don't understand why @Lists would still list 8 hashes, when I think, it should only list 4 (one hash for each pool, right?)
Pool: int-rpsuatbatch
Address:port - 10.122.204.119:21
Address:port - 10.168.116.145:21
@List: HASH(0x48ed4e8) HASH(0x48daa58)
Pool: sbox-americancentury
Address:port - 10.140.251.200:80
Address:port - 192.168.117.222:80
@List: HASH(0x48ccb6c) HASH(0x48e7bb4)
Pool: sbox-learningquestsavings
Address:port - 10.140.251.202:80
Address:port - 192.168.117.224:80
@List: HASH(0x48cbd8c) HASH(0x48cde30)
Pool: sbox-retireonline
Address:port - 10.140.251.206:80
Address:port - 192.168.117.146:80
@List: HASH(0x48ed62c) HASH(0x48cbe34)
@Lists: HASH(0x48ed4e8) HASH(0x48daa58) HASH(0x48ccb6c) HASH(0x48e7
bb4) HASH(0x48cbd8c) HASH(0x48cde30) HASH(0x48ed62c) HASH(0x48cbe34)
@pools: int-rpsuatbatch sbox-americancentury sbox-learningquestsavings sbox-learningquestsavings sbox-retireonline - Can you post your code and I'll take a look.
-Joe - Cynthia_18735
Nimbostratus
Joe - I got it working. I had a problem with the structure for 'members', but looked through some code posted to this site, and got the problem resolved. The script is working as expected, and we're putting it through some testing this morning, and should be able to move the changes to our prod enviornment later today. Thanks again for your asistance with this and all of the good suggestions!! I really appreciate it. - The dynamic languages like Perl and Python are always the hardest to get off the ground running with more complex parameters.
Glad you got things running and feel free to post questions anytime. We'll do our best to help you out.
-Joe - Cynthia_18735
Nimbostratus
Joe - I have moved this code into production, and seems to be working just great! Just one more question though.
In the /var/logs/httpd/ssl_access_log file, we have the following entries. All of these entries are generatd from the soap requests. My question is about the entries with the '406' error code. Is this normal? Seems like I get one of these right before it makes the actual SOAP calls. I'm guessing this is the soap calls with authorization, that look something like this.
SOAP API Calls with authorization
$WIDEIP = SOAP::Lite
-> uri('urn:iControl:GlobalLB/WideIP')
-> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi");
eval { $Rule->transport->http_request->header
(
'Authorization' =>
'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '')
); };
Following are the log entries:
May 7 15:03:02 gtm-01 logger: [ssl_acc] 10.115.84.20 - - [07/May/2008:15:03:02 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 406 -
May 7 15:03:02 gtm-01 logger: [ssl_acc] 10.115.84.20 - userid [07/May/2008:15:03:02 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 200 5221
May 7 15:03:03 gtm-01 logger: [ssl_acc] 10.115.84.20 - - [07/May/2008:15:03:03 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 406 -
May 7 15:03:03 gtm-01 logger: [ssl_acc] 10.115.84.20 - userid [07/May/2008:15:03:03 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 200 12691
May 7 15:03:03 gtm-01 logger: [ssl_acc] 10.115.84.20 - - [07/May/2008:15:03:03 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 406 -
May 7 15:03:04 gtm-01 logger: [ssl_acc] 10.115.84.20 - userid [07/May/2008:15:03:04 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 200 28777
May 7 15:03:06 gtm-01 logger: [ssl_acc] 10.115.84.20 - - [07/May/2008:15:03:05 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 406 -
May 7 15:03:07 gtm-01 logger: [ssl_acc] 10.115.84.20 - userid [07/May/2008:15:03:06 -0500] "POST /iControl/iControlPortal.cgi HTTP/1.1" 200 77607 - Don_MacVittie_1Historic F5 AccountHey Cynthia,
A 406 error normally means that the content the server was going to return was not acceptable to the client, so the server logged the error. When using iControl in KSOAP, I ran into this error when first connecting because the first attempt by KSOAP to connect was incomplete (didn't know the servers' security requirements until it talked to the server), immediately attempting to resend resolved it - but leaves this entry in the logs because the error did occur.
Other possible incompatibilities are things like MIME type and language - if the server only returns English and your browser doesn't understand English, for example... But I doubt that is the case here because the connection does indeed go through.
One of the other F5 staffers might have seen the code though and be able to give you a definitive "yep, that's what we're returning when security is enabled and not yet satisfied" - I haven't seen the source, so I can't say positively.
Don.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* 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
Discover DevCentral Connects
