perl
87 TopicsAdding or deleting a pool member
Problem this snippet solves: The script you need for this task must:. Identify the Enterprise Manager through which you will access the necessary BIG-IP devices. Authenticate your client to the Enterprise Manager. Retrieve a list of the BIG-IP devices managed by Enterprise Manager. For each managed BIG-IP device, retrieve a list of pools and pool members. For each managed BIG-IP device, specify the operation you want to perform (add/delete). How to use this snippet: To add/delete pool members: Create a script similar to the code sample shown below. Use either the add or delete parameter to produce the required outcome. From a command prompt, run your script. When the code finishes running, the specified pool member is enabled or disabled in each pool and on each device on which it resides. Code : #!/usr/bin/perl use SOAP::Lite; use UNIVERSAL 'isa'; $ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0; # Description: Adds/removes a pool member to/from all the pools on all BIG-IP devices managed by EM. # Usage: test-icontrolproxy-pool-member-operation.pl host uid pwd pool_member add|remove #---------------------------------------------------------------------------- # Validate Arguments #---------------------------------------------------------------------------- my $sHost = $ARGV[0]; # EM Host my $sUID = $ARGV[1]; # EM User (administrator role) my $sPWD = $ARGV[2]; # EM Password my $sPoolMember = $ARGV[3]; # BIG-IP Pool Member my $sOperation = $ARGV[4]; # BIG-IP Pool Member operation: add/remove my $proxy_uri = sprintf("https://%s:443/iControl/iControlPortal.cgi", $sHost); my $soap = SOAP::Lite->proxy($proxy_uri); sub SOAP::Transport::HTTP::Client::get_basic_credentials { return $sUID => $sPWD; } sub checkResponse { my ($resp) = (@_); die "$resp->faultcode $resp->faultstring\n" if $resp->fault; if (@{$resp->result}) { print "\tItem: $_\n" foreach (@{$resp->result}); } else { printf "\tResult: %s\n", $resp->result; } } sub getPoolList() { $soapResponse = $soap->uri("urn:iControl:LocalLB/Pool")->get_list(); &checkResponse($soapResponse); my @pool_list = @{$soapResponse->result}; return @pool_list; } sub getMemberLists() { my (@pool_list) = (@_); # Get the list of pool members for all the pools. $soapResponse = $soap->uri("urn:iControl:LocalLB/Pool")->get_member ( SOAP::Data->name(pool_names => [@pool_list]) ); &checkResponse($soapResponse); @member_lists = @{$soapResponse->result}; return @member_lists; } sub findPoolsFromMember() { my ($node_addr_port) = (@_); my ($node_addr, $node_port) = split(/:/, $node_addr_port, 2); my @pool_match_list; my @pool_list = &getPoolList(); my @member_lists = &getMemberLists(@pool_list); for $i (0 .. $#pool_list) { $pool = @pool_list[$i]; foreach $member (@{@member_lists[$i]}) { $addr = $member->{"address"}; $port = $member->{"port"}; if ( ($node_addr eq $addr) && ($node_port eq $port) ) { push @pool_match_list, $pool; } } } return @pool_match_list; } #---------------------------------------------------------------------------- # Adds or removes a pool member to/from all pools. #---------------------------------------------------------------------------- sub performPoolMemberOperation() { my ($node_addr_port, $operation) = (@_); my ($node_addr, $node_port) = split(/:/, $node_addr_port, 2); my $member = { address => $node_addr, port => $node_port }; # Validate operation. if (($operation ne "add") and ($operation ne "remove")) { print "Invalid operation: $operation..."; return; } my @pool_list; # Depending on the operation, get the appropraite pool list. if ($operation eq "add") { @pool_list = &getPoolList(); } else { @pool_list = &findPoolsFromMember($node_addr_port); } # memberList is the 1st dimension of the array, we need one for each pool push @memberList, $member; # memberLists is the 2nd dimension. push pool members for each pool here. for $i (0 .. $#pool_list) { push @memberLists, [@memberList]; } # Perform pool member operation. if ($operation eq "add") { $resp = $soap->uri("urn:iControl:LocalLB/Pool")->add_member( SOAP::Data->name(pool_names => [@pool_list]), SOAP::Data->name(members => [@memberLists])); } else { $resp = $soap->uri("urn:iControl:LocalLB/Pool")->remove_member( SOAP::Data->name(pool_names => [@pool_list]), SOAP::Data->name(members => [@memberLists])); } &checkResponse($soapResponse); print "Pool member: $node_addr_port. Operation: $operation. Affected pools: "; foreach $pool (@pool_list) { print "$pool, "; } print "\n"; } #---------------------------------------------------------------------------- # Main application entry point. #---------------------------------------------------------------------------- # EM: get devices. print "\nGet devices...\n"; my $resp = $soap->uri('urn:iControl:Management/EM')->get_devices(); my $device_list = $resp->result; # EM: generate a context ID. print "\nGenerate context ID...\n"; $resp = $soap->uri("urn:iControl:Management/EM")->get_context_id(); my $context_id = $resp->result; # Append context ID to SOAP URI. $proxy_uri = sprintf("%s?context_id=%s", $proxy_uri, $context_id); $soap = SOAP::Lite->proxy($proxy_uri); # Iterate through the device list. foreach (@{$device_list}) { # Get current device address. my $device = $_; # EM: set device context (to proxy to). print "\nSet device context...\n"; $resp = $soap->uri("urn:iControl:Management/EM")->set_device_context(SOAP::Data->name("ip_address" => $device)); &checkResponse($resp); # Perform pool member operation. &performPoolMemberOperation($sPoolMember, $sOperation); }1.1KViews0likes0CommentsPerl Ltm Config To Xml/Excel (version 3.1)
Problem this snippet solves: This code is an improvement of "Perl Ltm Config To Xml (version 2)" published on previous DevCentral (https://devcentral.f5.com/s/articles/perl-ltm-config-to-xml-version-2-1009) queries the components of a virtual servers configuration and prints it out in an XML format. Is recursive through partitions and prints the following data: VS_name VS_IP: IP and port RD (route domain) VS_state: status (ex. green) and state (ex. enabled) Profiles: name, type, context. If SSL profile aditional info: certificate, chain, key, cipher list Persistence iRules: order and name Pool_name LB-method: method, minimum active members Member: name, IP, port, ratio, priority, status and state Monitors: name, interval, timeout. If HTTP/HTTPS monitors additional info: Send and Receive strings SNAT_name SNAT_members Has a new option "-s" or "-simplified" which outputs multiple values like the profile list or pool members into a unique XML field. Purpose of simplified mode is to be able to have one Virtual Server per row on Excel, with lists showing on a single cell. This code has been tested on BIG-IP version 12.1 and 14.1. How to use this snippet: Default mode: ./LTM-to-XML.pl bigip uid pwd > result.xml Example for simplified mode and removal of partition information: ./LTM-to-XML.pl -s 127.0.0.1 uid pwd | sed "s/\/.*app\///g" | sed "s/\/Common\///g" > result.xml The XML can be dragged and dropped on MS Excel and opened as an XML table. Code : (see ZIP file) Tested this on version: 12.1, 14.1999Views2likes3CommentsBIG-IP Configuration Visualizer
Problem this snippet solves: This is a script utilizing the Graphviz package that will create graphs of the relationships of configuration objects of a virtual server. How to use this snippet: Requirements Perl SOAP::Lite Net::Netmask Graphviz Note: There are other required packages, but the remainder are default in Ubuntu 10.10 perl distribution. This may not be the case with your configuration. Install dependent libraries via apt-get - depending on your distribution you may have all of these as packages: libssl-dev libcrypt-ssleay-perl libio-socket-ssl-perl libgraph-writer-graphviz-perl libsoap-lite-perl libnet-netmask-perl For any which aren't available, open a CPAN shell (perl -MCPAN -e shell) and install them with commands such as: install SOAP::Lite install Net::Netmask Grab the archive below, extract the perl script file, and make it executable Minimal command-line invocation is: ./f5-gl.pl -t bigip-host-name.your.domain -u userid -p password The output by default goes into a subdirectory img, but you might want to add the option -d output-directory to keep output files separate from successive runs, particularly if you will run the utility against different BIG-IP systems for different operational environments. You can also use these: -c partition -v vs to run for only a particular VS (the partition must also be given) -e to change the output file type - default is JPG, but there are the options of SVG or PNG Run it! Put it in /etc/crontab to run every night, perhaps, and output the files to a directory served by Apache? The files are predictably named, so you could link directly to them from other tools. If you are averse to command-line parameters (perhaps you don't want the password to appear in a process listing) you can instead update these variables in the script: my $ltm_host my $user_id my $user_password940Views0likes4CommentsPerl Ltm Config To Xml (version 2)
Problem this snippet solves: This example is based on "Perl Ltm Config To Xml" by Joe Pruitt: queries the components of a virtual servers configuration and prints it out in an XML format for further processing. Now with a few more data retrieved (SNAT, object status) and does recursively on partitions, this way listing configuration generated by iApps on separate partitions. How to use this snippet: ./LTM-to-XML.pl bigip user pass Code : #!/usr/bin/perl #---------------------------------------------------------------------------- # The contents of this file are subject to the iControl Public License # Version 4.5 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.f5.com/. # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. # # The Original Code is iControl Code and related documentation # distributed by F5. # # The Initial Developer of the Original Code is F5 Networks, # Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2003 F5 Networks, # Inc. All Rights Reserved. iControl (TM) is a registered trademark of F5 Networks, Inc. # # Alternatively, the contents of this file may be used under the terms # of the GNU General Public License (the "GPL"), in which case the # provisions of GPL are applicable instead of those above. If you wish # to allow use of your version of this file only under the terms of the # GPL and not to allow others to use your version of this file under the # License, indicate your decision by deleting the provisions above and # replace them with the notice and other provisions required by the GPL. # If you do not delete the provisions above, a recipient may use your # version of this file under either the License or the GPL. #---------------------------------------------------------------------------- #use SOAP::Lite + trace => qw(method debug); use SOAP::Lite; #---------------------------------------------------------------------------- # Validate Arguments #---------------------------------------------------------------------------- my $BIGIP = $ARGV[0]; my $User = $ARGV[1]; my $Pass = $ARGV[2]; sub usage() { die ("Usage: LtmConfigToXml.pl host uid pwd\n"); } if ( ($BIGIP eq "") or ($User eq "") or ($Pass eq "") ) { usage(); } #---------------------------------------------------------------------------- # Transport Information #---------------------------------------------------------------------------- sub SOAP::Transport::HTTP::Client::get_basic_credentials { return "$User" => "$Pass"; } $urnMap = { "{urn:iControl}LocalLB.LBMethod" => 1, "{urn:iControl}LocalLB.MonitorRuleType" => 1, "{urn:iControl}LocalLB.ProfileContextType" => 1, "{urn:iControl}LocalLB.ProfileType" => 1, "{urn:iControl}LocalLB.VirtualServer.VirtualServerType" => 1, "{urn:iControl}LocalLB.AvailabilityStatus" => 1, "{urn:iControl}LocalLB.MonitorStatus" => 1, "{urn:iControl}LocalLB.EnabledStatus" => 1, "{urn:iControl}Common.EnabledState" => 1, "{urn:iControl}Common.VLANFilterList" => 1, }; sub SOAP::Deserializer::typecast { my ($self, $value, $name, $attrs, $children, $type) = @_; my $retval = undef; if ( 1 == $urnMap->{$type} ) { $retval = $value; } return $retval; } sub GetInterface() { my ($module, $name) = @_; $interface = SOAP::Lite -> uri("urn:iControl:$module/$name") -> readable(1) -> proxy("https://$BIGIP/iControl/iControlPortal.cgi"); eval { $interface->transport->http_request->header ( 'Authorization' => 'Basic ' . MIME::Base64::encode("$User:$Pass", '') ); }; return $interface; } sub FixEmptyEntries() { my @list1 = @_; my @list2; my $valid_item = ""; for $i (0 .. $#list1) { $item = @list1[$i]; if ( $item ne "" ) { $valid_item = $item; break; } } for $i (0 .. $#list1) { $item = @list1[$i]; if ( $item ne "" ) { push @list2, $item; } else { push @list2, $valid_item; } } return @list2; } # Status conversion my $MONITOR_STATUS_MAP = { "MONITOR_STATUS_UNCHECKED" => "UNCHECKED", "MONITOR_STATUS_CHECKING" => "CHECKING", "MONITOR_STATUS_UP" => "UP", "MONITOR_STATUS_DOWN" => "DOWN", "MONITOR_STATUS_FORCED_DOWN" => "FORCED_DOWN", "MONITOR_STATUS_MAINT" => "MAINT", "MONITOR_STATUS_ADDRESS_DOWN" => "ADDRESS_DOWN", }; my $ENABLED_STATUS_MAP = { "ENABLED_STATUS_NONE" => "NONE", "ENABLED_STATUS_ENABLED" => "ENABLED", "ENABLED_STATUS_DISABLED" => "DISABLED", "ENABLED_STATUS_DISABLED_BY_PARENT" => "DISABLED_BY_PARENT", }; # Get config sub GetConfigXML() { # Enable Recursive Partition/Folder lookup and set /Common as active folder $SystemSession = &GetInterface("System", "Session"); $soapResponse = $SystemSession->set_recursive_query_state( SOAP::Data->name(state => "STATE_ENABLED") ); &checkResponse($soapResponse); $soapResponse = $SystemSession->set_active_folder( SOAP::Data->name(folder => "/") ); # Get data $LocalLBVirtualServer = &GetInterface("LocalLB", "VirtualServer"); $LocalLBPool = &GetInterface("LocalLB", "Pool"); $LocalLBPoolMember = &GetInterface("LocalLB", "PoolMember"); $LocalLBSNATPool = &GetInterface("LocalLB", "SNATPool"); # VS List $soapResponse = $LocalLBVirtualServer->get_list(); &checkResponse($soapResponse); @vs_list = @{$soapResponse->result}; # Destination $soapResponse = $LocalLBVirtualServer->get_destination_v2( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @destination_list = @{$soapResponse->result}; # Type $soapResponse = $LocalLBVirtualServer->get_type( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @vstype_list = @{$soapResponse->result}; # iRules $soapResponse = $LocalLBVirtualServer->get_rule( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @rule_listA = @{$soapResponse->result}; # Profiles $soapResponse = $LocalLBVirtualServer->get_profile( SOAP::Data->name(virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @profile_listA = @{$soapResponse->result}; $soapResponse = $LocalLBVirtualServer->get_persistence_profile( SOAP::Data->name(virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @persistenceprofile_listA = @{$soapResponse->result}; # SNAT $soapResponse = $LocalLBVirtualServer->get_source_address_translation_snat_pool( SOAP::Data->name(virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @snat_list = @{$soapResponse->result}; # ensure we don't pass empty entries to the following methods. @snat_list2 = &FixEmptyEntries(@snat_list); # SNAT Pool Members $soapResponse = $LocalLBSNATPool->get_member_v2( SOAP::Data->name(snat_pools => [@snat_list2]) ); &checkResponse($soapResponse); @snatmember_listA = @{$soapResponse->result}; # State $soapResponse = $LocalLBVirtualServer->get_enabled_state( SOAP::Data->name(virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @state_list = @{$soapResponse->result}; # Pools $soapResponse = $LocalLBVirtualServer->get_default_pool_name( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @pool_list = @{$soapResponse->result}; # ensure we don't pass empty entries to the following methods. @pool_list2 = &FixEmptyEntries(@pool_list); # Pool Members $soapResponse = $LocalLBPool->get_member_v2( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @member_listA = @{$soapResponse->result}; # Member/Monitor Status $soapResponse = $LocalLBPoolMember->get_monitor_status( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @monitor_statusA = @{$soapResponse->result}; $soapResponse = $LocalLBPoolMember->get_object_status( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @object_statusA = @{$soapResponse->result}; # LB Method $soapResponse = $LocalLBPool->get_lb_method( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @lbmethod_list = @{$soapResponse->result}; $soapResponse = $LocalLBPool->get_monitor_association( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @monitor_list = @{$soapResponse->result}; # print XML print "\n"; print " \n"; print " \n"; for $i (0 .. $#vs_list) { # vip $vip = @vs_list[$i]; $pool = @pool_list[$i]; $destination = @destination_list[$i]; $vstype = @vstype_list[$i]; $snat = @snat_list[$i]; $state = @state_list[$i]; @rule_list = @{$rule_listA[$i]}; @profile_list = @{$profile_listA[$i]}; @persistenceprofile_list = @{$persistenceprofile_listA[$i]}; # pool @member_list = @{$member_listA[$i]}; @monitor_status = @{$monitor_statusA[$i]}; @object_status = @{$object_statusA[$i]}; $monitorassociations = @monitor_list[$i]; $monitor_rule = $monitorassociations->{"monitor_rule"}; $lb_method = $lbmethod_list[$i]; # SNAT @snatmember_list = @{$snatmember_listA[$i]}; $daddr = $destination->{"address"}; $dport = $destination->{"port"}; print " \n"; for $j (0 .. $#rule_list) { $rule = @rule_list[$j]; $name = $rule->{"rule_name"}; $priority = $rule->{"priority"}; print " \n"; } for $j (0 .. $#profile_list) { $profile = @profile_list[$j]; $name = $profile->{"profile_name"}; $type = $profile->{"profile_type"}; $context = $profile->{"profile_context"}; $default = $pprofile->{"default_profile"}; print " \n"; } for $j (0 .. $#persistenceprofile_list) { $pprofile = @persistenceprofile_list[$j]; $name = $pprofile->{"profile_name"}; $default = $pprofile->{"default_profile"}; print " \n"; } if ( $pool ne "" ) { print " \n"; for $j (0 .. $#member_list) { $member = @member_list[$j]; $address = $member->{"address"}; $port = $member->{"port"}; $monitorS = @monitor_status[$j]->{"monitor_status"}; $objectS = @object_status[$j]->{"object_status"}; $enabledS = $objectS->{"enabled_status"}; $status = "$MONITOR_STATUS_MAP->{$monitorS}-$ENABLED_STATUS_MAP->{$enabledS}"; print " \n"; } $type = $monitor_rule->{"type"}; @templates = @{$monitor_rule->{"monitor_templates"}}; print " \n"; for $j (0 .. $#templates) { $template = @templates[$j]; print " \n"; } print " \n"; print " \n"; } if ( $snat ne "" ) { print " \n"; for $j (0 .. $#snatmember_list) { $snatmember = @snatmember_list[$j]; print " \n"; } print " \n"; } print " \n"; } print " \n"; print " \n"; # Set /Common as active folder $soapResponse = $SystemSession->set_active_folder( SOAP::Data->name(folder => "/") ); &checkResponse($soapResponse); } &GetConfigXML(); #---------------------------------------------------------------------------- # checkResponse #---------------------------------------------------------------------------- sub checkResponse() { my ($soapResponse) = (@_); if ( $soapResponse->fault ) { print $soapResponse->faultcode, " ", $soapResponse->faultstring, "\n"; exit(); } } Tested this on version: 12.0867Views0likes5CommentsBIG-IP Backup Scripts
Problem this snippet solves: A set of scripts that can manage F5 configuration backups, runs on a scheduler, currently geared towards a Windows Server for remote backups. Requires SSH and passwordless key-based authentication. All files backed up are date stamped with the current day and can be used to perform a b config load and restore the appliances to a different state. There are 2 scripts as follows: f5confbkp.pl (runs on the BIG-IP). Uses b config save to save a copy under /var/tmp/f5configs f5getconf.pl (runs on a Windows server, modify the script if you want to run it on a UNIX system). Uses the key pair generated above to remote scp the files off of the F5's to a directory structure, in the scripts example that is e:\f5backups.) Key Exchange Setup Note: Only required for backup from a remote system. Generate a set of keys without a passphrase. (Reference ssh-keygen for details on generating keys). Take the id_dsa.pub key and put that into the /root/.ssh/authorized_keys file on the BIG-IP's you want to back up. Permissions on the authorized_keys file must be set to 644. Test your ssh connections from the remote system to ensure the account you are using on the remote backup server can ssh into the F5's you are backing up without getting prompted, as this will cause the script to fail otherwise. Cron job setup Setup the cronjob on the BIG-IP's. A job similar to the following will run the f5confbkp.pl script every day at 1 30 1 * /usr/bin/perl /root/scripts/f5confbkp.pl #!/usr/bin/perl # ------------------------------------ # # Name: f5getconf.pl # Purpose: Using SSH key based authentication gets the most current date stamped ucs file # Compatible: v4X and v9X versions of BigIP appliances, Windows 2k/2k3 or any Unix system # Requirements: On Windows cygwin (including ssh service installed) # SSH Key gen with no password for passwordless authentication # Requires that you connect and accept the key finger print before running # as a cron or via the Windows scheduler, otherwise it will stick trying to # connect via SCP. # Also requires an F5hosts.txt with the following entries: # bigipname (Case sensitive) IP Address. Example: # noc-f5-somehostname 10.0.1.1 # noc-f5-somehostnameb 10.0.1.2 # # Version: 2.0 # Author: Wes North # Currently geared for: Windows 2k/2k3 # ------------------------------------ # #Get LocalTime use Net::Telnet; #to test the socket before trying to SCP use Sys::Hostname; @T=localtime(); $year = $T[5] + 1900; $month = $T[4] + 1; $day = $T[3]; if ($T[2] > 12) { $hour = $T[2] - 12; $time = "$hour$T[1]PM"; } else { $hour = $T[2]; $time = "$hour$T[1]AM"; } if ($month < 10) { $month = "0$month"; } if ($day < 10) { $day = "0$day"; } $date = "$year$month$day"; #returns yyyymmdd $bakfile = "${hostname}-${date}.ucs"; $destdrive = qq!E:\\!; $destdir = qq!${destdrive}f5backups!; if (!-d $destdir) { `mkdir $destdir`; } $errdir = qq!$destdir\\errors!; if (!-d $errdir) { `mkdir $errdir`; } $errfile = "$errdir/debug.log"; open (ERROR, ">>$errfile") || die "Cannot open $errfile because $!\n"; #Get the current backup file for the F5 running config $cathosts = qq!cmd \/c type f5hosts.txt!; @f5list = split '\n', `$cathosts`; foreach $f5 (@f5list) { next if ($f5 =~ /^\#/); $errnum = ""; @sepline = split ' ', $f5; $hostname = $sepline[0]; $ip = $sepline[1]; $connection=Net::Telnet->new(Timeout => 2, Host => "$ip", port=>22, Errmode => sub {&error;}); if ($errnum ne "") { print ERROR "$month\/$day\/$year: $ip is not accessible $!\n"; next; } $bkfile = qq!${hostname}-${date}.ucs!; $putdir = qq!${destdir}\\$hostname!; if (!-d $putdir) { `mkdir $putdir`; } $getdir = qq!/var/tmp/f5configs!; $getfile = qq!${getdir}/${bkfile}!; #Replace the directory path and private key file reference with your own. $scpcmd = qq!cmd \/c scp -i "/cygdrive/c/Documents\ and\ Settings//.ssh/id_dsa" \ root\@${ip}\:${getfile} /cygdrive//f5backups/${hostname}/${bkfile}!; $Error = 0; $Error += system($scpcmd); if ($Error > 0) { print ERROR "$month\/$day\/$year: $scp command failed $!\n"; } else { print ERROR "$month\/$day\/$year: scp command for $hostname at $ip was successful\n"; } } close ERROR; #Cheesy and can be done differently, I didn't have a whole lot of time, so I settled for something like this. sub error { $errnum = 1; return $errnum; #print "Connection Failed!\n"; } exit 0; Code : #!/usr/bin/perl # ------------------------------------ # # Name: f5confbkp.pl # Purpose: without the enterprise management appliance, this can be run as a cron to backup configs from F5 appliances # Compatible: v4X and v9X versions of BigIP appliances # Requirements: Enough space to store ucs files, and really nothing else, it uses the builtin perl binaries # # Version: 2.0 # Author: Wes North # Currently geared for: Any version that supports b config save # ------------------------------------ # #Get LocalTime # use Sys::Hostname; #Locatime section, cheesy but have to set specific month and hour values @T=localtime(); $year = $T[5] + 1900; $month = $T[4] + 1; $day = $T[3]; if ($T[2] > 12) { $hour = $T[2] - 12; $time = "$hour$T[1]PM"; } else { $hour = $T[2]; $time = "$hour$T[1]AM"; } if ($month < 10) { $month = "0$month"; } if ($day < 10) { $day = "0$day"; } $date = "$year$month$day"; #returns yyyymmdd $fqdn = hostname(); #returns node.domain.suffix @n = split '\.', $fqdn; $hostname = $n[0]; #$bakfile = "${hostname}-${date}_${time}.ucs"; $bakfile = "${hostname}-${date}.ucs"; $errdir = "/var/tmp/f5configs"; if (!-d $errdir) { `mkdir $errdir`; } $errfile = "$errdir/$date-Error.log"; open (ERROR, ">>$errfile") || die "Cannot open $errfile because $!\n"; #Create a backup file for the F5 running config $bcmd = "b config save"; $path = "/var/tmp"; $f5cmd = "${bcmd} ${path}/f5configs/${bakfile} >> /dev/null 2>&1 &"; if (-f "$path/f5configs/$bakfile") { print ERROR "$month\/$day\/$year: $bakfile already exists exiting $0\n"; exit 1; } else { $possiblefile = "$path/f5configs/$hostname-*"; $ls = `ls $path/f5configs | grep .ucs`; if ($ls ne "" ) { @files = split '\n', $ls; foreach (@files) { $rm = qq!rm -rf "$path/f5configs/$_"!; `$rm`; } } $Error = 0; $Error += system($f5cmd); if ($Error != 0) { print ERROR "$month\/$day\/$year: $f5cmd command failed for $hostname\n"; exit 1; } else { print ERROR "$month\/$day\/$year: $f5cmd command completed successfully\n"; } } close ERROR; exit 0;825Views0likes0CommentsGetting Started with iControl Code Samples
Problem this snippet solves: This repository on github is for the full scripts highlighted in the Getting Started with iControl article series. Developed against BIG-IP TMOS version 12.0, but should work in most versions 11.6+. How to use this snippet: Choose your language and iControl portal of choice to start investigating iControl in your environment. Target audience: beginners. Code : https://github.com/f5devcentral/iControl-GettingStarted Tested this on version: 12.0811Views0likes0Commentsringdump
Problem this snippet solves: loop a tcpdump until a log message is seen Code : # Updated: 10/16/06 #!/usr/bin/perl ## VERSION v0.9b use strict; ################ # tcpdump settings ########## my %SETTINGS = ( external => { filter => "port 443" }, internal => { filter => "port 80" }, lo0 => { filter => "port 80" }, ); my $SNAPLEN = 4352; ################ # script settings ###### # free space checking my $FREE_SPACE_CHECK_INTERVAL = 1; # check free space every this number of seconds my $MIN_FREE_SPACE = 5; # minimum percent space left on parition my $CAPTURE_LOCATION = $ARGV[0]; # file rotation settings my $CAPTURES_TO_ROTATE = 4; # tcpdump capture files to rotate my $DESIRED_CAPTURE_SIZE = 15; # megabytes per capture file before rotating my $OVERLAP_DURING_ROTATE = 5; # seconds to overlap previous capture while starting a new one my $CAPTURE_CHECK_INTERVAL = 1; # how often (seconds) to check the size of capture files for rotating # trigger settings - time (run tcpdumps for x seconds) #my $TRIGGER = "time-based"; my $TIME_TO_CAPTURE = 300; # trigger settings - log-message (stop tcpdump when log message is received) my $TRIGGER = "log-message based"; my $LOG_FILE = "/var/log/messages"; my $LOG_MESSAGE = "no space in response line"; my $FOUND_MESSAGE_WAIT = 5; # how many seconds to gather tcpdumps after we match the log message # misc my $IDLE_TIMER = 5; # if ! receiving log entries, how long before checking if log is rotated my $MAX_ROTATED_LINES = 10000; # max lines to read from file we're re-reading because it's been rotated my $PID_FILE = "/var/run/ring_dump.pid"; my $DEBUG = 0; # 0/1 #################################################### # END OF THINGS THAT SHOULD NEED TO BE CONFIGURED #################################################### ######## # set defaults ### $SNAPLEN ||= 4352; $TRIGGER ||= "time"; $CAPTURE_LOCATION ||= "/var/tmp"; $TIME_TO_CAPTURE ||= 60; $FREE_SPACE_CHECK_INTERVAL ||= 5; $CAPTURES_TO_ROTATE ||= 3; $DESIRED_CAPTURE_SIZE ||= 10; $OVERLAP_DURING_ROTATE ||= 5; $CAPTURE_CHECK_INTERVAL ||= 5; $MIN_FREE_SPACE ||= 5; $LOG_FILE ||= "/var/log/messages"; $LOG_MESSAGE ||= "FAILED"; $FOUND_MESSAGE_WAIT ||= 5; $IDLE_TIMER ||= 5; $PID_FILE ||= "/var/run/ring_dump.pid"; $DEBUG ||= 0; unless (-d $CAPTURE_LOCATION) { print "$CAPTURE_LOCATION isn't a directory, using /mnt instead\n\n"; $CAPTURE_LOCATION = "/mnt"; } if (! -r $LOG_FILE) { die "Can't read \"$LOG_FILE\", EXIT\n"; } # insert code to find tcpdump instead of relying on path HERE: my $tcpdump = "/usr/sbin/tcpdump"; ###### # misc global variable declaration ########## my($answer, $interface, $pid, $tail_child, $F_LOG); my($current_size, $current_inode, $last_size, $last_inode); my @child_pids; my $ppid = $$; my $min_megabytes = $CAPTURES_TO_ROTATE * $DESIRED_CAPTURE_SIZE; $current_size = $current_inode = $last_size = $last_inode = 0; $|++; ########### # functions ####### # exit function that does does necessary child handling sub finish { $_ = shift(); if (defined($_) && $_ ne "") { print; } foreach $interface (keys( %SETTINGS )) { push(@child_pids, $SETTINGS{$interface}{pid}); } $DEBUG && print "INTERRUPT: sending SIGINT and SIGTERM to: ", join(" ", @child_pids), "\n"; kill(2, @child_pids); sleep(1); kill(15, @child_pids); $DEBUG && print "INTERRUPT: done, unlink pidfile and exit\n"; unlink($PID_FILE); exit(0); } $SIG{INT} = sub { finish(); }; # report usage on CAPTURE_LOCATION's MB free from df sub free_megabytes { my $partition = shift(); $partition ||= $CAPTURE_LOCATION; my $free_megabytes; $DEBUG && print "free_megabytes(): capture partition is $partition\n"; open(DF, "df $partition|"); # discard the first line; $_ = ; # parse the usage out of the second line $_ = ; $free_megabytes = (split)[3]; $free_megabytes = int($free_megabytes / 1024); close(DF); $DEBUG && print "free_megabytes(): finished reading df, output is: $free_megabytes\n"; $free_megabytes; } # report usage on CAPTURE_LOCATION's % usage from df sub free_percent { my $partition = shift(); $partition ||= $CAPTURE_LOCATION; my $free_percent; $DEBUG && print "free_percent(): capture partition is $partition\n"; open(DF, "df $partition|"); # discard the first line; $_ = ; # parse the usage out of the second line $_ = ; $free_percent = (split)[4]; chop($free_percent); ## chop off '%' $free_percent = (100 - $free_percent); close(DF); $DEBUG && print "free_percent(): finished reading df, output is: $free_percent\n"; $free_percent; } # simple sub to send SIGHUP to syslogd sub restart_syslogd () { if (-f "/var/run/syslog.pid") { open(PIDFILE, "; chomp; kill(1, ($_)); 1; } # simple wrapper to start tcpdumps, assuming obvious globals sub start_tcpdump { my $interface = shift(); my $capture_file = shift(); my $filter = shift(); my @cmd = ("$tcpdump", "-s$SNAPLEN", "-i$interface", "-w$capture_file", "$filter"); $DEBUG || open(STDERR, ">/dev/null"); $DEBUG && print "start_tcpdump(): about to start: ", join(" ", @cmd), "\n"; exec($cmd[0], @cmd[1..$#cmd]) || print "start_tcpdump(): FAILED to start: ", join(" ", @cmd), ", command not found\n"; $DEBUG || close(STDERR); exit(1); } # sub to see how much space a given capture file is using (to decide to rotate or not) sub capture_space ($) { my $capture_file = shift(); my $size = ( stat($capture_file) )[7]; $DEBUG && print "capture_space(): size of $capture_file is $size\n"; # return size of argument in megabytes, but don't divide by zero if ($size == 0) { return 0; } else { return ($size / 1048576); } } # gives user the option to create a MFS sub create_mfs () { if (-d $CAPTURE_LOCATION) { $DEBUG && print "create_mfs(): directory $CAPTURE_LOCATION exists\n"; } else { mkdir($CAPTURE_LOCATION, oct(0755)) || die "FAILED to create $CAPTURE_LOCATION\n"; print "Capture directory ($CAPTURE_LOCATION) did not exist, so it was created\n"; } # figure out the partition CAPTURE_LOCATION is on. This is cheap... fixme my $partition = $CAPTURE_LOCATION; $partition =~ s!(/[A-z0-9]*)/{0,1}.*!$1!g; open(MOUNT, "mount|") || die "FAILED to run \"mount\": !$\n"; while ( ) { next unless ((split())[2] =~ /^$partition$/); $DEBUG && print "create_mfs(): partition: $partition is already mounted, return\n"; # return 1 if it's already mounted return 1; } close(MOUNT); print "Mount a Memory File System (MFS) on ${CAPTURE_LOCATION}? [y/n]: "; my $answer = ; if (lc($answer) =~ "y") { print "Enter size of MFS in blocks (200000 = 100M), or just press enter for 100M: "; chomp (my $mfs_size = ); $mfs_size = 200000 if ($mfs_size eq ""); print "Allocating $mfs_size blocks to $CAPTURE_LOCATION for MFS\n"; system("mount_mfs -s $mfs_size $CAPTURE_LOCATION"); if (($? >> 8) != 0) { print "an error occurring trying to mount the MFS filesystem, exit status: $?\n"; 0; } else { print "MFS file system established\n\n"; 1; } } } sub fork_to_background ($) { my $cmd = shift(); my $pid = fork(); if ($pid == 0) { exec($cmd) || die "exec() failed: $!\n"; } else { return($pid); } } sub popen_read ($) { my $cmd = shift(); my $child; $DEBUG && print "Background: \"$cmd\"\n"; pipe(READLOG, WRITELOG); select(READLOG); $|++; select(WRITELOG); $|++; select(STDOUT); ## dup STDOUT and STDERR open(T_STDOUT, ">&STDOUT"); open(T_STDERR, ">&STDERR"); ## redir STDOUT to pipe for child open(STDOUT, ">&WRITELOG"); open(STDERR, ">&WRITELOG"); $child = fork_to_background($cmd); ## close STDOUT, STDERR and FILE close(STDOUT); close(STDERR); ## re-open STDOUT as normal and close dup open(STDOUT, ">&T_STDOUT"); close(T_STDOUT); open(STDERR, ">&T_STDERR"); close(T_STDERR); return($child, \*READLOG); } sub open_log ($$) { my $LOG_FILE = shift(); my $lines = shift(); if (defined($F_LOG) && defined(fileno($F_LOG)) ) { $DEBUG && print "Killing child before closing LOG\n"; kill(15, $tail_child); waitpid($tail_child, 0); $DEBUG && print "Closing LOG\n"; close($F_LOG); } $DEBUG && print "Opening \"$LOG_FILE\"\n"; ($tail_child, $F_LOG) = popen_read("tail -n $lines -f $LOG_FILE"); push(@child_pids, $tail_child); 1; } ## check to see if log is rotated, returns true if rotated sub is_rotated ($) { my $LOG_FILE = shift(); $DEBUG && print "enter is_rotated()\n"; ($current_inode, $current_size) = (stat($LOG_FILE))[1,7]; if (($last_size != 0) && ($last_size > $current_size)) { $DEBUG && print "File is now smaller. File must have been rotated\n"; $last_size = $current_size; $last_inode = $current_inode; open_log($LOG_FILE, $MAX_ROTATED_LINES) || die "open_log $LOG_FILE failed: $!\n"; return(1); } elsif (($last_inode != 0) && ($last_inode != $current_inode)) { $DEBUG && print "Inode changed. File must have been rotated\n"; $last_inode = $current_inode; $last_size = $current_size; open_log($LOG_FILE, $MAX_ROTATED_LINES) || die "open_log $LOG_FILE failed: $!\n"; return(1); } ($last_inode, $last_size) = ($current_inode, $current_size); 0; } ########### # MAIN ######## if (free_megabytes() < $min_megabytes) { print "free space on $CAPTURE_LOCATION is below ${min_megabytes}MB, you must create a Memory File System or choose another location to gather tcpdumps\n"; goto MUST_MFS; } ######### GET USER INPUT ############### if (free_percent() < $MIN_FREE_SPACE) { print "free space on $CAPTURE_LOCATION is below ${MIN_FREE_SPACE}%, you must create a Memory File System or choose another location to gather tcpdumps\n"; MUST_MFS: # require the user to create a MFS if they don't have enough free space exit(1) unless (create_mfs()); } else { create_mfs(); } if (free_percent() < $MIN_FREE_SPACE || free_megabytes() < $min_megabytes) { print "it appears the Memory File System is in place, but there is still insufficient space, exiting\n"; exit(1); } print "capturing to $CAPTURE_LOCATION using the following interfaces and filters:\n"; foreach $interface (keys( %SETTINGS )) { system("ifconfig $interface >/dev/null 2>&1"); if ( ($? >> 8) != 0) { $DEBUG && print "couldn't ifconfig $interface, removing from list\n"; delete( $SETTINGS{$interface} ); } else { print " $interface: $SETTINGS{$interface}{filter}\n"; } } print "does this look right? [y/n]: "; $answer = ; exit unless lc($answer) =~ "y"; ####### DAEMONIZE ############# chdir("/"); exit unless (fork() == 0); # kill old self, write pid file if (-f $PID_FILE) { open(PIDFILE, "<$PID_FILE"); kill(15, ); close(PIDFILE); } open(PIDFILE, ">$PID_FILE"); syswrite(PIDFILE, $$); close(PIDFILE); ########### START PROCESSING ############### foreach $interface (keys( %SETTINGS )) { my $filter = $SETTINGS{$interface}{filter}; $pid = fork(); $SETTINGS{$interface}{rotate_number} = 1; if (!defined($pid)) { print "fork() failed! exiting\n"; exit 1; } if ($pid == 0) { start_tcpdump( $interface, "$CAPTURE_LOCATION/${interface}.dump.$SETTINGS{$interface}{rotate_number}", $filter ); exit 1; } else { $SETTINGS{$interface}{pid} = $pid; print "started tcpdump as pid $pid on \"$interface\" filtered as \"$filter\"\n"; } } ###### # fork off a process to keep an eye on free space ######## $pid = fork(); if ($pid == 0) { while (1) { my $sleep_return = sleep($FREE_SPACE_CHECK_INTERVAL); $DEBUG && ($sleep_return != $FREE_SPACE_CHECK_INTERVAL) && print "WARN: free_percent() loop: sleep returned $sleep_return instead of $FREE_SPACE_CHECK_INTERVAL !\n"; if (free_percent() < $MIN_FREE_SPACE) { print "WARN: free space is below ${MIN_FREE_SPACE}%, killing main script\n"; kill(2, $ppid); sleep(1); kill(15, $ppid); print "WARN: sent SIGTERM to $ppid (main script), exiting\n"; exit 1; } else { $DEBUG && print "free_percent(): space is fine, continue\n"; } } } else { push(@child_pids, $pid); $DEBUG && print "started free_percent watcher as: $pid\n"; } ###### # fork off a process to rotate capture files as necessary ######## $pid = fork(); if ($pid == 0) { my $capture_file; while (1) { my $sleep_return = sleep($CAPTURE_CHECK_INTERVAL); $DEBUG && ($sleep_return != $CAPTURE_CHECK_INTERVAL) && print "WARN: start_tcpdump() loop: sleep returned $sleep_return instead of $CAPTURE_CHECK_INTERVAL !\n"; foreach $interface (keys( %SETTINGS )) { if (capture_space("$CAPTURE_LOCATION/${interface}.dump.$SETTINGS{$interface}{rotate_number}") >= $DESIRED_CAPTURE_SIZE) { if ($SETTINGS{$interface}{rotate_number} == $CAPTURES_TO_ROTATE) { print "reached maximum number of captures to rotate: $CAPTURES_TO_ROTATE, starting over at 1\n"; $SETTINGS{$interface}{rotate_number} = 1; } else { $SETTINGS{$interface}{rotate_number}++; } print "rotating capture file: ${interface}.dump, new extension .$SETTINGS{$interface}{rotate_number}\n"; $pid = fork(); if ($pid == 0) { start_tcpdump( $interface, "$CAPTURE_LOCATION/${interface}.dump.$SETTINGS{$interface}{rotate_number}", $SETTINGS{$interface}{filter}, ); exit 0; } push(@child_pids, $pid); # get some overlap in the two files sleep($OVERLAP_DURING_ROTATE); # kill the old tcpdump kill(2, $SETTINGS{$interface}{pid}); $DEBUG && print "sent SIGINT to $interface: $SETTINGS{$interface}{pid}, new pid $pid\n"; # record the new pid $SETTINGS{$interface}{pid} = $pid; } else { $DEBUG && print "capture file doesn't need to be rotated yet: ${interface}.dump\n"; } } # Reap any zombies from old tcpdumps $DEBUG && print "start_tcpdump() loop: \@child_pids = (", join(' ', @child_pids), ")\n"; while (1) { use POSIX ":sys_wait_h"; my $child = waitpid(-1, WNOHANG); if (defined $child and $child > 0) { # remove PID from @child_pids @child_pids = grep {$_ != $child} @child_pids; $DEBUG && print "start_tcpdump() loop: reaped child PID $child\n"; } else { # no one to reap last; } } } } else { push(@child_pids, $pid); $DEBUG && print "started capture file watcher as: $pid\n"; } ################ # watch triggers (time or log based) #################### $SIG{TERM} = sub { finish(); }; if (lc($TRIGGER) =~ /time/) { print "time-based trigger, will capture for $TIME_TO_CAPTURE seconds\n"; sleep($TIME_TO_CAPTURE); print "captured for $TIME_TO_CAPTURE seconds, stopping tcpdumps\n"; } elsif (lc($TRIGGER) =~ /log/) { print "log-based trigger, waiting for \"$LOG_MESSAGE\" in \"$LOG_FILE\"\n"; # creates global $F_LOG filehandle of $LOG_FILE open_log($LOG_FILE, 0) || finish("open_log $LOG_FILE failed: $!\n"); # flush syslogd's buffers (avoid never getting the message due to "last message repeated....") restart_syslogd() || finish("Restarting syslogd failed, EXIT\n"); # tail -f the log and wait for message while (1) { # reap any zombies during each loop my $return; while (1) { use POSIX ":sys_wait_h"; my $child = waitpid(-1, WNOHANG); if (defined $child and $child > 0) { $DEBUG && print "log trigger loop: reaped child PID $child\n"; } else { # no one to reap last; } } eval { $SIG{ALRM} = sub { die("ALRM\n"); }; alarm($IDLE_TIMER); $_ = <$F_LOG>; alarm(0); }; if ($@) { # this only occurs if we're idle for $IDLE_TIMER seconds because no new log entries are occuring $@ = undef; is_rotated($LOG_FILE); next; } $DEBUG && print "in LOG reading loop, current line: \"$_\"\n"; if (/$LOG_MESSAGE/) { $DEBUG && print "Current line matches: \"$LOG_MESSAGE\"\n"; last; } $DEBUG && print "no match, next\n"; } print "received log message, sleeping $FOUND_MESSAGE_WAIT seconds then stopping tcpdumps\n"; sleep($FOUND_MESSAGE_WAIT); } # figure out current tcpdump child_pids and push them onto the list foreach $interface (keys( %SETTINGS )) { push(@child_pids, $SETTINGS{$interface}{pid}); } # kill all tcpdumps + free space watcher + capture file rotator -- doesn't return finish(); 0;700Views0likes1CommentPerl Ltm Config To Xml
Problem this snippet solves: This example queries the components of a virtual servers configuration and prints it out in an XML format for further processing. How to use this snippet: .\PerlLtmConfigToXml.pl bigip user pass Code : #!/usr/bin/perl #---------------------------------------------------------------------------- # The contents of this file are subject to the iControl Public License # Version 4.5 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.f5.com/. # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. # # The Original Code is iControl Code and related documentation # distributed by F5. # # The Initial Developer of the Original Code is F5 Networks, # Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2003 F5 Networks, # Inc. All Rights Reserved. iControl (TM) is a registered trademark of F5 Networks, Inc. # # Alternatively, the contents of this file may be used under the terms # of the GNU General Public License (the "GPL"), in which case the # provisions of GPL are applicable instead of those above. If you wish # to allow use of your version of this file only under the terms of the # GPL and not to allow others to use your version of this file under the # License, indicate your decision by deleting the provisions above and # replace them with the notice and other provisions required by the GPL. # If you do not delete the provisions above, a recipient may use your # version of this file under either the License or the GPL. #---------------------------------------------------------------------------- #use SOAP::Lite + trace => qw(method debug); use SOAP::Lite; #---------------------------------------------------------------------------- # Validate Arguments #---------------------------------------------------------------------------- my $BIGIP = $ARGV[0]; my $User = $ARGV[1]; my $Pass = $ARGV[2]; sub usage() { die ("Usage: LtmConfigToXml.pl host uid pwd\n"); } if ( ($BIGIP eq "") or ($User eq "") or ($Pass eq "") ) { usage(); } #---------------------------------------------------------------------------- # Transport Information #---------------------------------------------------------------------------- sub SOAP::Transport::HTTP::Client::get_basic_credentials { return "$User" => "$Pass"; } $urnMap = { "{urn:iControl}LocalLB.LBMethod" => 1, "{urn:iControl}LocalLB.MonitorRuleType" => 1, "{urn:iControl}LocalLB.ProfileContextType" => 1, "{urn:iControl}LocalLB.ProfileType" => 1, "{urn:iControl}LocalLB.VirtualServer.VirtualServerType" => 1, }; sub SOAP::Deserializer::typecast { my ($self, $value, $name, $attrs, $children, $type) = @_; my $retval = undef; if ( 1 == $urnMap->{$type} ) { $retval = $value; } return $retval; } sub GetInterface() { my ($module, $name) = @_; $interface = SOAP::Lite -> uri("urn:iControl:$module/$name") -> readable(1) -> proxy("https://$BIGIP/iControl/iControlPortal.cgi"); eval { $interface->transport->http_request->header ( 'Authorization' => 'Basic ' . MIME::Base64::encode("$User:$Pass", '') ); }; return $interface; } &GetConfigXML(); sub FixEmptyEntries() { my @list1 = @_; my @list2; my $valid_item = ""; for $i (0 .. $#list1) { $item = @list1[$i]; if ( $item ne "" ) { $valid_item = $item; break; } } for $i (0 .. $#list1) { $item = @list1[$i]; if ( $item ne "" ) { push @list2, $item; } else { push @list2, $valid_item; } } return @list2; } sub GetConfigXML() { $LocalLBVirtualServer = &GetInterface("LocalLB", "VirtualServer"); $LocalLBPool = &GetInterface("LocalLB", "Pool"); $LocalLBPoolMember = &GetInterface("LocalLB", "PoolMember"); # VS List $soapResponse = $LocalLBVirtualServer->get_list(); &checkResponse($soapResponse); @vs_list = @{$soapResponse->result}; # Destination $soapResponse = $LocalLBVirtualServer->get_destination( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @destination_list = @{$soapResponse->result}; # Type $soapResponse = $LocalLBVirtualServer->get_type( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @vstype_list = @{$soapResponse->result}; # iRules $soapResponse = $LocalLBVirtualServer->get_rule( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @rule_listA = @{$soapResponse->result}; # Profiles $soapResponse = $LocalLBVirtualServer->get_profile( SOAP::Data->name(virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @profile_listA = @{$soapResponse->result}; $soapResponse = $LocalLBVirtualServer->get_persistence_profile( SOAP::Data->name(virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @persistenceprofile_listA = @{$soapResponse->result}; # Pools $soapResponse = $LocalLBVirtualServer->get_default_pool_name( SOAP::Data->name (virtual_servers => [@vs_list]) ); &checkResponse($soapResponse); @pool_list = @{$soapResponse->result}; # ensure we don't pass empty entries to the following methods. @pool_list2 = &FixEmptyEntries(@pool_list); # Pool Members $soapResponse = $LocalLBPool->get_member( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @member_listA = @{$soapResponse->result}; # LB Method $soapResponse = $LocalLBPool->get_lb_method( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @lbmethod_list = @{$soapResponse->result}; $soapResponse = $LocalLBPool->get_monitor_association( SOAP::Data->name(pool_names => [@pool_list2]) ); &checkResponse($soapResponse); @monitor_list = @{$soapResponse->result}; print "\n"; print " \n"; print " \n"; for $i (0 .. $#vs_list) { # vip $vip = @vs_list[$i]; $pool = @pool_list[$i]; $destination = @destination_list[$i]; $vstype = @vstype_list[$i]; @rule_list = @{$rule_listA[$i]}; @profile_list = @{$profile_listA[$i]}; @persistenceprofile_list = @{$persistenceprofile_listA[$i]}; # pool @member_list = @{$member_listA[$i]}; $monitorassociations = @monitor_list[$i]; $monitor_rule = $monitorassociations->{"monitor_rule"}; $lb_method = $lbmethod_list[$i]; $daddr = $destination->{"address"}; $dport = $destination->{"port"}; print " \n"; for $j (0 .. $#rule_list) { $rule = @rule_list[$j]; $name = $rule->{"rule_name"}; $priority = $rule->{"priority"}; print " \n"; } for $j (0 .. $#profile_list) { $profile = @profile_list[$j]; $type = $profile->{"profile_type"}; $context = $profile->{"profile_context"}; $name = $profile->{"profile_name"}; print " \n"; } for $j (0 .. $#persistenceprofile_list) { $pprofile = @persistenceprofile_list[$j]; $name = $pprofile->{"profile_name"}; $default = $pprofile->{"default_profile"}; print " \n"; } if ( $pool ne "" ) { print " \n"; for $j (0 .. $#member_list) { $member = @member_list[$j]; $address = $member->{"address"}; $port = $member->{"port"}; print " \n"; } $type = $monitor_rule->{"type"}; $quorum = $monitor_rule->{"quorum"}; @templates = @{$monitor_rule->{"monitor_templates"}}; print " \n"; for $j (0 .. $#templates) { $template = @templates[$j]; print " \n"; } print " \n"; print " \n"; } print " \n"; } print " \n"; print " \n"; } #---------------------------------------------------------------------------- # checkResponse #---------------------------------------------------------------------------- sub checkResponse() { my ($soapResponse) = (@_); if ( $soapResponse->fault ) { print $soapResponse->faultcode, " ", $soapResponse->faultstring, "\n"; exit(); } }682Views0likes5CommentsEnable/Disable pool member
Problem this snippet solves: This Perl script will enable or disable all instances of a node address and port across all pools. Code : #!/usr/bin/perl #---------------------------------------------------------------------------- # The contents of this file are subject to the "END USER LICENSE AGREEMENT FOR F5 # Software Development Kit for iControl"; you may not use this file except in # compliance with the License. The License is included in the iControl # Software Development Kit. # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. # # The Original Code is iControl Code and related documentation # distributed by F5. # # The Initial Developer of the Original Code is F5 Networks, # Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2004 F5 Networks, # Inc. All Rights Reserved. iControl (TM) is a registered trademark of F5 Networks, Inc. # # Alternatively, the contents of this file may be used under the terms # of the GNU General Public License (the "GPL"), in which case the # provisions of GPL are applicable instead of those above. If you wish # to allow use of your version of this file only under the terms of the # GPL and not to allow others to use your version of this file under the # License, indicate your decision by deleting the provisions above and # replace them with the notice and other provisions required by the GPL. # If you do not delete the provisions above, a recipient may use your # version of this file under either the License or the GPL. #---------------------------------------------------------------------------- #use SOAP::Lite + trace => qw(method debug); use SOAP::Lite; use MIME::Base64; #---------------------------------------------------------------------------- # Validate Arguments #---------------------------------------------------------------------------- my $sHost = $ARGV[0]; my $sUID = $ARGV[1]; my $sPWD = $ARGV[2]; my $sNodePort = $ARGV[3]; my $sEnable = $ARGV[4]; my $sProtocol = "https"; my $sPort = 443; if ( ($sHost eq "") or ($sUID eq "") or ($sPWD eq "") ) { die ("Usage: NodeServer.pl host uid pwd [[node_port] [enable|disable]]\n"); } #---------------------------------------------------------------------------- # support for custom enum types #---------------------------------------------------------------------------- sub SOAP::Deserializer::typecast { my ($self, $value, $name, $attrs, $children, $type) = @_; my $retval = undef; if ( "{urn:iControl}LocalLB.AvailabilityStatus" == $type ) { $retval = $value; } return $retval; } #---------------------------------------------------------------------------- # Transport Information #---------------------------------------------------------------------------- sub SOAP::Transport::HTTP::Client::get_basic_credentials { return "$sUID" => "$sPWD"; } $Pool = SOAP::Lite -> uri('urn:iControl:LocalLB/Pool') -> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi"); eval { $Pool->transport->http_request->header ( 'Authorization' => 'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '') ); }; $PoolMember = SOAP::Lite -> uri('urn:iControl:LocalLB/PoolMember') -> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi"); eval { $PoolMember->transport->http_request->header ( 'Authorization' => 'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '') ); }; #---------------------------------------------------------------------------- # sub ListPoolsAndMembers #---------------------------------------------------------------------------- sub ListPoolsAndMembers() { my ($node_addr_port) = (@_); my ($node_addr, $node_port) = split(/:/, $node_addr_port, 2); my @pool_list = &getPoolList(); my @object_status_lists = &getObjectStatusLists(@pool_list); # Loop over pools for $i (0 .. $#pool_list) { $bFound = 0; $pool = @pool_list[$i]; if ( "" == $node_addr ) { # if no node given, print out full list print "Pool $pool\n"; foreach $status (@{@object_status_lists[$i]}) { $member = $status->{"member"}; $addr = $member->{"address"}; $port = $member->{"port"}; $ostat = $status->{"object_status"}; $astat = $ostat->{"availability_status"}; $estat = $ostat->{"enabled_status"}; print " $addr:$port ($astat, $estat)\n"; } #print "\n"; } else { # else, only print out where matches are found. foreach $status (@{@object_status_lists[$i]}) { if ( !$bFound ) { $member = $status->{"member"}; $addr = $member->{"address"}; $port = $member->{"port"}; $ostat = $status->{"object_status"}; $astat = $ostat->{"availability_status"}; $estat = $ostat->{"enabled_status"}; if ( ($node_addr eq $addr) && ($node_port eq $port) ) { $bFound = 1; } } } if ( $bFound ) { print "Pool $pool : $node_addr:$node_port ($astat, $estat)\n"; } } } } #---------------------------------------------------------------------------- # sub setNodeServer #---------------------------------------------------------------------------- sub SetNodeServer() { my ($node_addr_port, $state) = (@_); my ($node_addr, $node_port) = split(/:/, $node_addr_port, 2); my @pool_list = &findPoolsFromMember($node_addr_port); my $member = { address => $node_addr, port => $node_port }; my $ENABLED_STATE = "STATE_ENABLED"; if ( $state eq "disable" ) { $ENABLED_STATE = "STATE_DISABLED"; } my $MemberMonitorState = { member => $member, monitor_state => $ENABLED_STATE }; my @MemberMonitorStateList; push @MemberMonitorStateList, $MemberMonitorState; my @MemberMonitorStateLists; for $i (0 .. $#pool_list) { push @MemberMonitorStateLists, [@MemberMonitorStateList]; } # Make call to set_monitor_state $soapResponse = $PoolMember->set_monitor_state( SOAP::Data->name(pool_names => [@pool_list]), SOAP::Data->name(monitor_states => [@MemberMonitorStateLists]) ); &checkResponse($soapResponse); print "Node Server $node_addr_port set to $ENABLED_STATE in pools: "; foreach $pool (@pool_list) { print "$pool, "; } print "\n"; } #---------------------------------------------------------------------------- # sub getPoolList #---------------------------------------------------------------------------- sub getPoolList() { # Get the list of pools $soapResponse = $Pool->get_list(); &checkResponse($soapResponse); my @pool_list = @{$soapResponse->result}; return @pool_list; } #---------------------------------------------------------------------------- # sub getMemberLists #---------------------------------------------------------------------------- sub getMemberLists() { my (@pool_list) = (@_); # Get the list of pool members for all the pools $soapResponse = $Pool->get_member ( SOAP::Data->name(pool_names => [@pool_list]) ); &checkResponse($soapResponse); @member_lists = @{$soapResponse->result}; return @member_lists; } #---------------------------------------------------------------------------- # sub getObjectStatus #---------------------------------------------------------------------------- sub getObjectStatusLists() { my (@pool_list) = (@_); # Get the list of pool members for all the pools $soapResponse = $PoolMember->get_object_status ( SOAP::Data->name(pool_names => [@pool_list]) ); &checkResponse($soapResponse); @object_status_lists = @{$soapResponse->result}; return @object_status_lists; } #---------------------------------------------------------------------------- # sub findPoolsFromMember #---------------------------------------------------------------------------- sub findPoolsFromMember() { my ($node_addr_port) = (@_); my ($node_addr, $node_port) = split(/:/, $node_addr_port, 2); my @pool_match_list; my @pool_list = &getPoolList(); my @member_lists = &getMemberLists(@pool_list); for $i (0 .. $#pool_list) { $pool = @pool_list[$i]; foreach $member (@{@member_lists[$i]}) { $addr = $member->{"address"}; $port = $member->{"port"}; if ( ($node_addr eq $addr) && ($node_port eq $port) ) { push @pool_match_list, $pool; } } } return @pool_match_list; } #---------------------------------------------------------------------------- # checkResponse #---------------------------------------------------------------------------- sub checkResponse() { my ($soapResponse) = (@_); if ( $soapResponse->fault ) { print $soapResponse->faultcode, " ", $soapResponse->faultstring, "\n"; exit(); } } #---------------------------------------------------------------------------- # main app logic #---------------------------------------------------------------------------- if ( ($sNodePort ne "") && ($sEnable ne "") ) { &SetNodeServer($sNodePort, $sEnable) } else { &ListPoolsAndMembers($sNodePort) }625Views0likes2CommentsEnabling or disabling a pool member
Problem this snippet solves: The script you need for this task must:. Identify the Enterprise Manager through which you will access the necessary BIG-IP devices. Authenticate your client to the Enterprise Manager. Retrieve a list of the BIG-IP devices managed by Enterprise Manager. For each managed BIG-IP device, retrieve a list of pools and pool members. For each managed BIG-IP device, specify the operation you want to perform (enable/disable). How to use this snippet: To enable/disable a pool member: Create a script similar to the code sample shown below. Use either the enable or disable parameter to produce the required outcome. From a command prompt, run your script. When the code finishes running, the specified pool member is enabled or disabled in each pool and on each device on which it resides. Code : #!/usr/bin/perl use SOAP::Lite; use UNIVERSAL 'isa'; $ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0; # Description: Enables/Disables a pool member in all pools of all BIG-IP devices managed by EM. # Usage: test-icontrolproxy-pool-member-state.pl host uid pwd pool_member enable|disable #---------------------------------------------------------------------------- # Validate Arguments #---------------------------------------------------------------------------- my $sHost = $ARGV[0]; # EM Host my $sUID = $ARGV[1]; # EM User (administrator role) my $sPWD = $ARGV[2]; # EM Password my $sPoolMember = $ARGV[3]; # BIG-IP Pool Member my $sState = $ARGV[4]; # BIG-IP Pool Member State: enable/disable my $proxy_uri = sprintf("https://%s:443/iControl/iControlPortal.cgi", $sHost); my $soap = SOAP::Lite->proxy($proxy_uri); sub SOAP::Transport::HTTP::Client::get_basic_credentials { return $sUID => $sPWD; } sub checkResponse { my ($resp) = (@_); die "$resp->faultcode $resp->faultstring\n" if $resp->fault; if (@{$resp->result}) { print "\tItem: $_\n" foreach (@{$resp->result}); } else { printf "\tResult: %s\n", $resp->result; } } sub getPoolList() { $soapResponse = $soap->uri("urn:iControl:LocalLB/Pool")->get_list(); &checkResponse($soapResponse); my @pool_list = @{$soapResponse->result}; return @pool_list; } sub getMemberLists() { my (@pool_list) = (@_); # Get the list of pool members for all the pools. $soapResponse = $soap->uri("urn:iControl:LocalLB/Pool")->get_member ( SOAP::Data->name(pool_names => [@pool_list]) ); &checkResponse($soapResponse); @member_lists = @{$soapResponse->result}; return @member_lists; } sub findPoolsFromMember() { my ($node_addr_port) = (@_); my ($node_addr, $node_port) = split(/:/, $node_addr_port, 2); my @pool_match_list; my @pool_list = &getPoolList(); my @member_lists = &getMemberLists(@pool_list); for $i (0 .. $#pool_list) { $pool = @pool_list[$i]; foreach $member (@{@member_lists[$i]}) { $addr = $member->{"address"}; $port = $member->{"port"}; if ( ($node_addr eq $addr) && ($node_port eq $port) ) { push @pool_match_list, $pool; } } } return @pool_match_list; } sub setPoolMemberState() { my ($node_addr_port, $state) = (@_); my ($node_addr, $node_port) = split(/:/, $node_addr_port, 2); my @pool_list = &findPoolsFromMember($node_addr_port); my $member = { address => $node_addr, port => $node_port }; my $ENABLED_STATE = "STATE_ENABLED"; if ( $state eq "disable" ) { $ENABLED_STATE = "STATE_DISABLED"; } my $MemberMonitorState = { member => $member, monitor_state => $ENABLED_STATE }; my @MemberMonitorStateList; push @MemberMonitorStateList, $MemberMonitorState; my @MemberMonitorStateLists; for $i (0 .. $#pool_list) { push @MemberMonitorStateLists, [@MemberMonitorStateList]; } # Make call to set_monitor_state $soapResponse = $soap->uri("urn:iControl:LocalLB/PoolMember")->set_monitor_state( SOAP::Data->name(pool_names => [@pool_list]), SOAP::Data->name(monitor_states => [@MemberMonitorStateLists]) ); &checkResponse($soapResponse); print "Pool member $node_addr_port set to $ENABLED_STATE in pools: "; foreach $pool (@pool_list) { print "$pool, "; } print "\n"; } #---------------------------------------------------------------------------- # Main application entry point. #---------------------------------------------------------------------------- # EM: get devices. print "\nGet devices...\n"; my $resp = $soap->uri('urn:iControl:Management/EM')->get_devices(); my $device_list = $resp->result; # EM: generate a context ID. print "\nGenerate context ID...\n"; $resp = $soap->uri("urn:iControl:Management/EM")->get_context_id(); my $context_id = $resp->result; # Append context ID to SOAP URI. $proxy_uri = sprintf("%s?context_id=%s", $proxy_uri, $context_id); $soap = SOAP::Lite->proxy($proxy_uri); # Iterate through the device list. foreach (@{$device_list}) { # Get current device address. my $device = $_; # EM: set device context (to proxy to). print "\nSet device context...\n"; $resp = $soap->uri("urn:iControl:Management/EM")->set_device_context(SOAP::Data->name("ip_address" => $device)); &checkResponse($resp); # Set pool member state. &setPoolMemberState($sPoolMember, $sState); }599Views0likes2Comments