For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Pool Member Update By A Record

Problem this snippet solves:

This is a script will do an A record lookup for a hostname and populate the specified pool with all available A records. The script will not change the existing pool member(s) or modify their connections if the next A record matches. Only changes to the associated A record will result in changes to the pool members. The script will error out and print a help message if any of the following conditions are met: 6 arguments are not provided (BIG-IP address, BIG-IP user, BIG-IP password, A record query, pool name, pool member port), the port is an invalid integer (valid ports: 1-65535), BIG-IP connection cannot be made, the pool does not exist, or no A record returned.

How to use this snippet:

Requirements

  • Ruby
  • Ruby Gems
  • F5 iControl for Ruby library (https://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/1086421/Getting-Started-With-Ruby-and-iControl.aspx)
  • other dependencies will be installed with the iControl gem

Installation Steps

  1. Install Ruby, Ruby's OpenSSL library, Ruby Gems, and the Ruby iControl libraries
  2. Copy this code to /usr/local/bin and chmod +x to make the script executable
  3. Run it!
    • change-pool-member-to-a-record-result <BIG-IP address> <BIG-IP user> <BIG-IP password> < A record query> < pool name> < pool member port>

Code :

#!/usr/bin/ruby

require 'rubygems'
require 'f5-icontrol'
require 'resolv'

def usage
  puts $0 + '      '
  exit
end

# make sure enough arguments have been provided
usage if $*.size < 6
$*[5] = $*[5].to_i

# create iControl interface
bigip = F5::IControl.new($*[0], $*[1], $*[2], ['LocalLB.Pool']).get_interfaces

# test iControl connectivity
begin
  bigip['LocalLB.Pool'].get_version
rescue
  puts "Error: could not establish a connection to the BIG-IP. Check the hostname, user, and password."
  exit 1
end

# ensure that the pool member port is an integer and in the valid range
unless $*[5].between?(1, 65535)
  puts "Error: please provide a valid integer for the pool member port."
  exit 1
end

# make sure that the provided pool exists
unless bigip['LocalLB.Pool'].get_list.include? $*[4]
  puts "Error: could not locate #{$*[4]} pool. If using version 11, make sure to prepend the folder, e.g. /Common/my_pool"
  exit 1
end

# attempt to resolve the hostname
resources = Resolv::DNS.new.getresources($*[3], Resolv::DNS::Resource::IN::A)

# check if we received a response, exit on empty responses
if resources.size == 0
  puts "Error: could not resolve #{$*[3]}. Please verify the name, ensure that it is fully qualified, and verify setting in /etc/resolv.conf"
  exit 1
end

# grab a list of current pool members
old_members = bigip['LocalLB.Pool'].get_member([ $*[4] ])[0].collect do |member|
  { 'address' => member.address, 'port' => member.port }
end

# create an array to hold new member records and 
new_members = []

# add each of the returned a records to the pool
resources.each do |record|
  new_member = { 'address' => record.address.to_s, 'port' => $*[5] }

  if old_members.include? new_member
    old_members.delete new_member
    puts "Info: preserving pool member: #{new_member['address']}:#{new_member['port']}"
  else
    new_members << new_member
  end
end

# delete old members that are no longer used
old_members.each do |member|
  puts "Info: removing pool member: #{member['address']}:#{member['port']}"
end

bigip['LocalLB.Pool'].remove_member([ $*[4] ], [ old_members ])

# add new members to pool
new_members.each do |member|
  puts "Info: adding new pool member: #{member['address']}:#{member['port']}"
end

bigip['LocalLB.Pool'].add_member([ $*[4] ], [ new_members ])
Published Mar 09, 2015
Version 1.0
No CommentsBe the first to comment