Class: PenBalancer

Inherits:
Object
  • Object
show all
Defined in:
lib/pen_balancer.rb

Constant Summary collapse

BOOLEAN_ATTRIBS =

TODO: :log has log, log=false and log=file

:web_stats
[:ascii=, :block=, :control=, :delayed_forward=, :hash=, :http=, :roundrobin=, :stubborn=, :weight=]
GETTERS_SETTERS =
[:blacklist, :client_acl, :control_acl, :debug, :tracking, :timeout]
GETTERS =
[:clients_max, :conn_max, :control, :listen, :status, :recent]
COMMANDS =
[:exit!, :include!, :write!]

Instance Method Summary collapse

Constructor Details

#initialize(address) ⇒ PenBalancer

Creates a new PenBalancer instance: If you have launched a local pen

instance with 8080 as the control port, you should use PenBalancer 
like this: PenBalancer.new 'localhost:8080'.

Throws an exception when pen can't be reached.


20
21
22
23
# File 'lib/pen_balancer.rb', line 20

def initialize( address )
  @pen = address
  raise "Can't find pen balancer at #{address}" unless Penctl.execute( @pen, "control")[0].match /#{address.split(':')[1]}/
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

penctl has the following three patterns:

  1) booleans (no getters): penctl localhost:8080 no ascii
                            penctl localhost:8080 ascii
  2) getters/setters:       penctl localhost:8080 debug 3
                            penctl localhost:8080 debug
  3) commands:              penctl localhost:8080 exit
The first two are turned into regular getters and setters and
the last into methods.


105
106
107
108
109
110
111
# File 'lib/pen_balancer.rb', line 105

def method_missing(method, *args)
  return Penctl.set_boolean_attribute(@pen, method, args[0])                if BOOLEAN_ATTRIBS.include? method
  return Penctl.get_set_attribute(@pen, method, args[0])                    if GETTERS_SETTERS.include? method.to_s.chomp('=').to_sym
  return Penctl.get_set_attribute(@pen, method, args[0])                    if GETTERS.include? method
  return Penctl.execute(@pen, "#{method.to_s.chomp('!')} #{args[0]}".strip) if COMMANDS.include? method
  raise "Missing method #{method}"
end

Instance Method Details

#add_server(host, port) ⇒ Object

Adds a server to the pool or throws an exception when there is no free

slot left

Raises:

  • (ArgumentError)


41
42
43
44
45
46
# File 'lib/pen_balancer.rb', line 41

def add_server( host, port )
  raise ArgumentError.new("Server is in the pool already") if server_in_pool?( host, port)
  free_slot = get_server( '0.0.0.0', 0 )
  Penctl.update_server( @pen, free_slot[:slot], :address => host, :port => port)
  server_in_pool? host, port
end

#blacklist_server(host, port, blacklist_seconds = 3600) ⇒ Object

Blacklists a server for the given amount of seconds or throws an

exception when the server cannot be found in the pool


62
63
64
65
# File 'lib/pen_balancer.rb', line 62

def blacklist_server( host, port, blacklist_seconds = 3600)
  server = get_server( host, port )
  Penctl.update_server( @pen, server[:slot], :blacklist => blacklist_seconds)
end

#remove_acl_entry(slot) ⇒ Object

Flushes the rules of an acl entry (==permit from all)

Raises:

  • (RangeError)


90
91
92
93
# File 'lib/pen_balancer.rb', line 90

def remove_acl_entry( slot )
  raise RangeError.new("slot #{slot} outside range 0-9") unless (0..9).include?(slot)
  Penctl.execute(@pen, "no acl #{slot}")
end

#remove_server(host, port) ⇒ Object

Removes a server from the pool or throws an exception when the server

cannot be found in the pool


52
53
54
55
56
# File 'lib/pen_balancer.rb', line 52

def remove_server( host, port )
  server = get_server( host, port )
  Penctl.update_server( @pen, server[:slot], :address => '0.0.0.0', :port => 0 )
  !server_in_pool? host, port
end

#serversObject

Returns an array of servers pen currently knows



28
29
30
31
32
33
34
35
# File 'lib/pen_balancer.rb', line 28

def servers
  list = []
  Penctl.execute(@pen, "servers", 5).each do |l| 
    server = Penctl.parse_server_line(l)
    list[server[:slot]] = server
  end
  list.compact
end

#set_acl_entry(slot, params) ⇒ Object

Updates an entry of the access control list. Params is a hash with

mandatory :policy => permit/deny and :source_ip. You can optionally
pass a :netmask.

Raises:

  • (RangeError)


81
82
83
84
85
# File 'lib/pen_balancer.rb', line 81

def set_acl_entry( slot, params )
  raise RangeError.new("slot #{slot} outside range 0-9")       unless (0..9).include?(slot)
  raise ArgumentError.new("policy must be either permit or deny") unless ['permit', 'deny'].include? params[:policy]
  Penctl.execute(@pen, "acl #{slot} #{params[:policy]} #{params[:source_ip]} #{params[:netmask]}".strip)
end

#whitelist_server(host, port) ⇒ Object

A shortcut for blacklisting a server for 0 seconds.



71
72
73
74
# File 'lib/pen_balancer.rb', line 71

def whitelist_server( host, port)
  server = get_server( host, port )
  Penctl.update_server( @pen, server[:slot], :blacklist => 0)
end