used ansible conventions to use trigered action ==> state, now only two states are available enabled/disabled_ get weight for backend server, is default behavior for both state, supports set weight while enable server in lb pool
This commit is contained in:
parent
a1c5149de3
commit
e0f0cc4049
1 changed files with 47 additions and 131 deletions
|
@ -21,22 +21,26 @@
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
---
|
---
|
||||||
module: haproxy
|
module: haproxy
|
||||||
short_description: An Ansible module to handle actions enable/disable server and set/get weight from haproxy using socket commands.
|
short_description: An Ansible module to handle states enable/disable server and set weight to backend host in haproxy using socket commands.
|
||||||
description:
|
description:
|
||||||
- Enable/Diable Haproxy Backend Server,
|
- The Enable Haproxy Backend Server, with
|
||||||
- Get/Set weight of Haproxy Backend Server,
|
supports get current weight for server (default) and
|
||||||
using haproxy socket commands - http://haproxy.1wt.eu
|
set weight for haproxy backend server when provides.
|
||||||
|
|
||||||
|
- The Disable Haproxy Backend Server, with
|
||||||
|
supports get current weight for server (default) and
|
||||||
|
shutdown sessions while disabling backend host server.
|
||||||
notes:
|
notes:
|
||||||
- "enable or disable or set weight commands are restricted and can only be issued on sockets configured for level 'admin', "
|
- "enable or disable commands are restricted and can only be issued on sockets configured for level 'admin', "
|
||||||
- "Check - http://haproxy.1wt.eu/download/1.5/doc/configuration.txt, "
|
- "Check - http://haproxy.1wt.eu/download/1.5/doc/configuration.txt, "
|
||||||
- "Example: 'stats socket /var/run/haproxy.sock level admin'"
|
- "Example: 'stats socket /var/run/haproxy.sock level admin'"
|
||||||
options:
|
options:
|
||||||
action:
|
state:
|
||||||
description:
|
description:
|
||||||
- Action to take.
|
- describe the desired state of the given host in lb pool.
|
||||||
required: true
|
required: true
|
||||||
default: null
|
default: null
|
||||||
choices: [ "enabled", "disabled", "get_weight", "set_weight" ]
|
choices: [ "enabled", "disabled" ]
|
||||||
host:
|
host:
|
||||||
description:
|
description:
|
||||||
- Host (backend) to operate in Haproxy.
|
- Host (backend) to operate in Haproxy.
|
||||||
|
@ -66,26 +70,25 @@ options:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
# disable backend server in 'www' backend
|
examples:
|
||||||
- haproxy: action=disabled host={{ inventory_hostname }} backend=www
|
|
||||||
|
|
||||||
# disable backend server without backend name (applied to all)
|
# disable server in 'www' backend pool
|
||||||
- haproxy: action=disabled host={{ inventory_hostname }}
|
- haproxy: state=disabled host={{ inventory_hostname }} backend=www
|
||||||
|
|
||||||
|
# disable server without backend pool name (apply to all available backend pool)
|
||||||
|
- haproxy: state=disabled host={{ inventory_hostname }}
|
||||||
|
|
||||||
# disable server, provide socket file
|
# disable server, provide socket file
|
||||||
- haproxy: action=disabled host={{ inventory_hostname }} socket=/var/run/haproxy.sock backend=www
|
- haproxy: state=disabled host={{ inventory_hostname }} socket=/var/run/haproxy.sock backend=www
|
||||||
|
|
||||||
# disable backend server in 'www' backend and drop open sessions to it
|
# disable backend server in 'www' backend pool and drop open sessions to it
|
||||||
- haproxy: action=disabled host={{ inventory_hostname }} backend=www shutdown_sessions=true
|
- haproxy: state=disabled host={{ inventory_hostname }} backend=www socket=/var/run/haproxy.sock shutdown_sessions=true
|
||||||
|
|
||||||
# enable backend server in 'www' backend
|
# enable server in 'www' backend pool
|
||||||
- haproxy: action=enabled host={{ inventory_hostname }} backend=www
|
- haproxy: state=enabled host={{ inventory_hostname }} backend=www
|
||||||
|
|
||||||
# report a server's current weight in 'www' backend
|
# enable server in 'www' backend pool with change server(s) weight
|
||||||
- haproxy: action=get_weight host={{ inventory_hostname }} backend=www
|
- haproxy: state=enabled host={{ inventory_hostname }} socket=/var/run/haproxy.sock weight=10 backend=www
|
||||||
|
|
||||||
# change a server's current weight in 'www' backend
|
|
||||||
- haproxy: action=set_weight host={{ inventory_hostname }} backend=www weight=10
|
|
||||||
|
|
||||||
author: Ravi Bhure <ravibhure@gmail.com>
|
author: Ravi Bhure <ravibhure@gmail.com>
|
||||||
version_added: "1.9"
|
version_added: "1.9"
|
||||||
|
@ -104,14 +107,12 @@ def main():
|
||||||
ACTION_CHOICES = [
|
ACTION_CHOICES = [
|
||||||
'enabled',
|
'enabled',
|
||||||
'disabled',
|
'disabled',
|
||||||
'get_weight',
|
|
||||||
'set_weight'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# load ansible module object
|
# load ansible module object
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec = dict(
|
argument_spec = dict(
|
||||||
action = dict(required=True, default=None, choices=ACTION_CHOICES),
|
state = dict(required=True, default=None, choices=ACTION_CHOICES),
|
||||||
host=dict(required=True, default=None),
|
host=dict(required=True, default=None),
|
||||||
backend=dict(required=False, default=None),
|
backend=dict(required=False, default=None),
|
||||||
weight=dict(required=False, default=None),
|
weight=dict(required=False, default=None),
|
||||||
|
@ -121,7 +122,7 @@ def main():
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
|
|
||||||
)
|
)
|
||||||
action = module.params['action']
|
state = module.params['state']
|
||||||
host = module.params['host']
|
host = module.params['host']
|
||||||
backend = module.params['backend']
|
backend = module.params['backend']
|
||||||
weight = module.params['weight']
|
weight = module.params['weight']
|
||||||
|
@ -129,7 +130,7 @@ def main():
|
||||||
shutdown_sessions = module.params['shutdown_sessions']
|
shutdown_sessions = module.params['shutdown_sessions']
|
||||||
|
|
||||||
##################################################################
|
##################################################################
|
||||||
# Required args per action:
|
# Required args per state:
|
||||||
# (enabled/disabled) = (host)
|
# (enabled/disabled) = (host)
|
||||||
#
|
#
|
||||||
# AnsibleModule will verify most stuff, we need to verify
|
# AnsibleModule will verify most stuff, we need to verify
|
||||||
|
@ -137,16 +138,12 @@ def main():
|
||||||
|
|
||||||
##################################################################
|
##################################################################
|
||||||
|
|
||||||
if action in ['set_weight']:
|
|
||||||
if not weight:
|
|
||||||
module.fail_json(msg='no weight specified for action, require value in number')
|
|
||||||
|
|
||||||
##################################################################
|
##################################################################
|
||||||
if not socket:
|
if not socket:
|
||||||
module.fail_json('unable to locate haproxy.sock')
|
module.fail_json('unable to locate haproxy.sock')
|
||||||
|
|
||||||
##################################################################
|
##################################################################
|
||||||
required_one_of=[['action', 'host']]
|
required_one_of=[['state', 'host']]
|
||||||
|
|
||||||
ansible_haproxy = HAProxy(module, **module.params)
|
ansible_haproxy = HAProxy(module, **module.params)
|
||||||
if module.check_mode:
|
if module.check_mode:
|
||||||
|
@ -173,7 +170,7 @@ class HAProxy(object):
|
||||||
|
|
||||||
def __init__(self, module, **kwargs):
|
def __init__(self, module, **kwargs):
|
||||||
self.module = module
|
self.module = module
|
||||||
self.action = kwargs['action']
|
self.state = kwargs['state']
|
||||||
self.host = kwargs['host']
|
self.host = kwargs['host']
|
||||||
self.backend = kwargs['backend']
|
self.backend = kwargs['backend']
|
||||||
self.weight = kwargs['weight']
|
self.weight = kwargs['weight']
|
||||||
|
@ -190,7 +187,6 @@ class HAProxy(object):
|
||||||
|
|
||||||
buffer = ""
|
buffer = ""
|
||||||
|
|
||||||
|
|
||||||
self.client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
self.client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
self.client.connect(self.socket)
|
self.client.connect(self.socket)
|
||||||
self.client.sendall('%s\n' % cmd)
|
self.client.sendall('%s\n' % cmd)
|
||||||
|
@ -200,11 +196,11 @@ class HAProxy(object):
|
||||||
while buf:
|
while buf:
|
||||||
result += buf
|
result += buf
|
||||||
buf = self.client.recv(RECV_SIZE)
|
buf = self.client.recv(RECV_SIZE)
|
||||||
self.command_results = result.strip()
|
self.command_results = result.strip()
|
||||||
self.client.close()
|
self.client.close()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def enabled(self, host, backend):
|
def enabled(self, host, backend, weight):
|
||||||
"""
|
"""
|
||||||
Enables backend server for a particular backend.
|
Enables backend server for a particular backend.
|
||||||
|
|
||||||
|
@ -232,12 +228,16 @@ class HAProxy(object):
|
||||||
if 'BACKEND' in line:
|
if 'BACKEND' in line:
|
||||||
result = line.split(',')[0]
|
result = line.split(',')[0]
|
||||||
pxname = result
|
pxname = result
|
||||||
cmd = "enable server %s/%s" % (pxname, svname)
|
cmd = "get weight %s/%s ; enable server %s/%s" % (pxname, svname, pxname, svname)
|
||||||
|
if weight:
|
||||||
|
cmd += "; set weight %s/%s %s" % (pxname, svname, weight)
|
||||||
self.execute(cmd)
|
self.execute(cmd)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pxname = backend
|
pxname = backend
|
||||||
cmd = "enable server %s/%s" % (pxname, svname)
|
cmd = "get weight %s/%s ; enable server %s/%s" % (pxname, svname, pxname, svname)
|
||||||
|
if weight:
|
||||||
|
cmd += "; set weight %s/%s %s" % (pxname, svname, weight)
|
||||||
self.execute(cmd)
|
self.execute(cmd)
|
||||||
|
|
||||||
def disabled(self, host, backend, shutdown_sessions):
|
def disabled(self, host, backend, shutdown_sessions):
|
||||||
|
@ -273,117 +273,33 @@ class HAProxy(object):
|
||||||
if 'BACKEND' in line:
|
if 'BACKEND' in line:
|
||||||
result = line.split(',')[0]
|
result = line.split(',')[0]
|
||||||
pxname = result
|
pxname = result
|
||||||
cmd = "disable server %s/%s" % (pxname, svname)
|
cmd = "get weight %s/%s ; disable server %s/%s" % (pxname, svname, pxname, svname)
|
||||||
if shutdown_sessions:
|
if shutdown_sessions == 'true':
|
||||||
cmd += "; shutdown sessions server %s/%s" % (pxname, svname)
|
cmd += "; shutdown sessions server %s/%s" % (pxname, svname)
|
||||||
self.execute(cmd)
|
self.execute(cmd)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pxname = backend
|
pxname = backend
|
||||||
cmd = "disable server %s/%s" % (pxname, svname)
|
cmd = "get weight %s/%s ; disable server %s/%s" % (pxname, svname, pxname, svname)
|
||||||
if shutdown_sessions:
|
if shutdown_sessions == 'true':
|
||||||
cmd += "; shutdown sessions server %s/%s" % (pxname, svname)
|
cmd += "; shutdown sessions server %s/%s" % (pxname, svname)
|
||||||
self.execute(cmd)
|
self.execute(cmd)
|
||||||
|
|
||||||
def get_weight(self, host, backend):
|
|
||||||
"""
|
|
||||||
Report a server's current weight.
|
|
||||||
|
|
||||||
get weight <backend>/<server>
|
|
||||||
Report the current weight and the initial weight of server <server> in
|
|
||||||
backend <backend> or an error if either doesn't exist. The initial weight is
|
|
||||||
the one that appears in the configuration file. Both are normally equal
|
|
||||||
unless the current weight has been changed. Both the backend and the server
|
|
||||||
may be specified either by their name or by their numeric ID, prefixed with a
|
|
||||||
sharp ('#').
|
|
||||||
|
|
||||||
Syntax: get weight <pxname>/<svname>
|
|
||||||
"""
|
|
||||||
svname = host
|
|
||||||
if self.backend is None:
|
|
||||||
output = self.execute('show stat')
|
|
||||||
#sanitize and make a list of lines
|
|
||||||
output = output.lstrip('# ').strip()
|
|
||||||
output = output.split('\n')
|
|
||||||
result = output
|
|
||||||
|
|
||||||
for line in result:
|
|
||||||
if 'BACKEND' in line:
|
|
||||||
result = line.split(',')[0]
|
|
||||||
pxname = result
|
|
||||||
cmd = "get weight %s/%s" % (pxname, svname)
|
|
||||||
self.execute(cmd)
|
|
||||||
|
|
||||||
else:
|
|
||||||
pxname = backend
|
|
||||||
cmd = "get weight %s/%s" % (pxname, svname)
|
|
||||||
self.execute(cmd)
|
|
||||||
|
|
||||||
def set_weight(self, host, backend, weight):
|
|
||||||
"""
|
|
||||||
Change a server's current weight.
|
|
||||||
|
|
||||||
set weight <backend>/<server> <weight>[%]
|
|
||||||
Change a server's weight to the value passed in argument. If the value ends
|
|
||||||
with the '%' sign, then the new weight will be relative to the initially
|
|
||||||
configured weight. Relative weights are only permitted between 0 and 100%,
|
|
||||||
and absolute weights are permitted between 0 and 256. Servers which are part
|
|
||||||
of a farm running a static load-balancing algorithm have stricter limitations
|
|
||||||
because the weight cannot change once set. Thus for these servers, the only
|
|
||||||
accepted values are 0 and 100% (or 0 and the initial weight). Changes take
|
|
||||||
effect immediately, though certain LB algorithms require a certain amount of
|
|
||||||
requests to consider changes. A typical usage of this command is to disable
|
|
||||||
a server during an update by setting its weight to zero, then to enable it
|
|
||||||
again after the update by setting it back to 100%. This command is restricted
|
|
||||||
and can only be issued on sockets configured for level "admin". Both the
|
|
||||||
backend and the server may be specified either by their name or by their
|
|
||||||
numeric ID, prefixed with a sharp ('#').
|
|
||||||
|
|
||||||
Syntax: set weight <pxname>/<svname>
|
|
||||||
"""
|
|
||||||
svname = host
|
|
||||||
weight = weight
|
|
||||||
if self.backend is None:
|
|
||||||
output = self.execute('show stat')
|
|
||||||
#sanitize and make a list of lines
|
|
||||||
output = output.lstrip('# ').strip()
|
|
||||||
output = output.split('\n')
|
|
||||||
result = output
|
|
||||||
|
|
||||||
for line in result:
|
|
||||||
if 'BACKEND' in line:
|
|
||||||
result = line.split(',')[0]
|
|
||||||
pxname = result
|
|
||||||
cmd = "set weight %s/%s %s" % (pxname, svname, weight)
|
|
||||||
self.execute(cmd)
|
|
||||||
|
|
||||||
else:
|
|
||||||
pxname = backend
|
|
||||||
cmd = "set weight %s/%s %s" % (pxname, svname, weight)
|
|
||||||
self.execute(cmd)
|
|
||||||
|
|
||||||
def act(self):
|
def act(self):
|
||||||
"""
|
"""
|
||||||
Figure out what you want to do from ansible, and then do the
|
Figure out what you want to do from ansible, and then do the
|
||||||
needful (at the earliest).
|
needful (at the earliest).
|
||||||
"""
|
"""
|
||||||
# toggle enable/disbale server
|
# toggle enable/disbale server
|
||||||
if self.action == 'enabled':
|
if self.state == 'enabled':
|
||||||
self.enabled(self.host, self.backend)
|
self.enabled(self.host, self.backend, self.weight)
|
||||||
|
|
||||||
elif self.action == 'disabled':
|
elif self.state == 'disabled':
|
||||||
self.disabled(self.host, self.backend, self.shutdown_sessions)
|
self.disabled(self.host, self.backend, self.shutdown_sessions)
|
||||||
|
|
||||||
# toggle get/set weight
|
|
||||||
elif self.action == 'get_weight':
|
|
||||||
self.get_weight(self.host, self.backend)
|
|
||||||
|
|
||||||
elif self.action == 'set_weight':
|
|
||||||
self.set_weight(self.host, self.backend, self.weight)
|
|
||||||
# wtf?
|
|
||||||
else:
|
else:
|
||||||
self.module.fail_json(msg="unknown action specified: '%s'" % \
|
self.module.fail_json(msg="unknown state specified: '%s'" % \
|
||||||
self.action)
|
self.state)
|
||||||
|
|
||||||
self.module.exit_json(stdout=self.command_results, changed=True)
|
self.module.exit_json(stdout=self.command_results, changed=True)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue