Merge pull request #622 from ggermis/devel

haproxy module wait
This commit is contained in:
Greg DeKoenigsberg 2015-06-18 09:17:29 -04:00
commit bd177bcb62

View file

@ -68,6 +68,24 @@ options:
- When disabling server, immediately terminate all the sessions attached to the specified server. This can be used to terminate long-running sessions after a server is put into maintenance mode, for instance. - When disabling server, immediately terminate all the sessions attached to the specified server. This can be used to terminate long-running sessions after a server is put into maintenance mode, for instance.
required: false required: false
default: false default: false
wait:
description:
- Wait until the server reports a status of 'UP' when state=enabled, or status of 'MAINT' when state=disabled
required: false
default: false
version_added: "2.0"
wait_retries:
description:
- number of times to check for status after changing the state
required: false
default: 20
version_added: "2.0"
wait_interval:
description:
- number of seconds to wait between retries
required: false
default: 1
version_added: "2.0"
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -82,12 +100,21 @@ examples:
# disable server, provide socket file # disable server, provide socket file
- haproxy: state=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 server, provide socket file, wait until status reports in maintenance
- haproxy: state=disabled host={{ inventory_hostname }} socket=/var/run/haproxy.sock backend=www wait=yes
# disable backend server in 'www' backend pool and drop open sessions to it # disable backend server in 'www' backend pool and drop open sessions to it
- haproxy: state=disabled host={{ inventory_hostname }} backend=www socket=/var/run/haproxy.sock shutdown_sessions=true - haproxy: state=disabled host={{ inventory_hostname }} backend=www socket=/var/run/haproxy.sock shutdown_sessions=true
# enable server in 'www' backend pool # enable server in 'www' backend pool
- haproxy: state=enabled host={{ inventory_hostname }} backend=www - haproxy: state=enabled host={{ inventory_hostname }} backend=www
# enable server in 'www' backend pool wait until healthy
- haproxy: state=enabled host={{ inventory_hostname }} backend=www wait=yes
# enable server in 'www' backend pool wait until healthy. Retry 10 times with intervals of 5 seconds to retrieve the health
- haproxy: state=enabled host={{ inventory_hostname }} backend=www wait=yes wait_retries=10 wait_interval=5
# enable server in 'www' backend pool with change server(s) weight # enable server in 'www' backend pool with change server(s) weight
- haproxy: state=enabled host={{ inventory_hostname }} socket=/var/run/haproxy.sock weight=10 backend=www - haproxy: state=enabled host={{ inventory_hostname }} socket=/var/run/haproxy.sock weight=10 backend=www
@ -95,11 +122,15 @@ author: "Ravi Bhure (@ravibhure)"
''' '''
import socket import socket
import csv
import time
DEFAULT_SOCKET_LOCATION="/var/run/haproxy.sock" DEFAULT_SOCKET_LOCATION="/var/run/haproxy.sock"
RECV_SIZE = 1024 RECV_SIZE = 1024
ACTION_CHOICES = ['enabled', 'disabled'] ACTION_CHOICES = ['enabled', 'disabled']
WAIT_RETRIES=20
WAIT_INTERVAL=1
###################################################################### ######################################################################
class TimeoutException(Exception): class TimeoutException(Exception):
@ -126,10 +157,12 @@ class HAProxy(object):
self.weight = self.module.params['weight'] self.weight = self.module.params['weight']
self.socket = self.module.params['socket'] self.socket = self.module.params['socket']
self.shutdown_sessions = self.module.params['shutdown_sessions'] self.shutdown_sessions = self.module.params['shutdown_sessions']
self.wait = self.module.params['wait']
self.wait_retries = self.module.params['wait_retries']
self.wait_interval = self.module.params['wait_interval']
self.command_results = [] self.command_results = []
def execute(self, cmd, timeout=200): def execute(self, cmd, timeout=200, capture_output=True):
""" """
Executes a HAProxy command by sending a message to a HAProxy's local Executes a HAProxy command by sending a message to a HAProxy's local
UNIX socket and waiting up to 'timeout' milliseconds for the response. UNIX socket and waiting up to 'timeout' milliseconds for the response.
@ -144,10 +177,35 @@ class HAProxy(object):
while buf: while buf:
result += buf result += buf
buf = self.client.recv(RECV_SIZE) buf = self.client.recv(RECV_SIZE)
if capture_output:
self.command_results = result.strip() self.command_results = result.strip()
self.client.close() self.client.close()
return result return result
def wait_until_status(self, pxname, svname, status):
"""
Wait for a service to reach the specified status. Try RETRIES times
with INTERVAL seconds of sleep in between. If the service has not reached
the expected status in that time, the module will fail. If the service was
not found, the module will fail.
"""
for i in range(1, self.wait_retries):
data = self.execute('show stat', 200, False).lstrip('# ')
r = csv.DictReader(data.splitlines())
found = False
for row in r:
if row['pxname'] == pxname and row['svname'] == svname:
found = True
if row['status'] == status:
return True;
else:
time.sleep(self.wait_interval)
if not found:
self.module.fail_json(msg="unable to find server %s/%s" % (pxname, svname))
self.module.fail_json(msg="server %s/%s not status '%s' after %d retries. Aborting." % (pxname, svname, status, self.wait_retries))
def enabled(self, host, backend, weight): def enabled(self, host, backend, weight):
""" """
Enabled action, marks server to UP and checks are re-enabled, Enabled action, marks server to UP and checks are re-enabled,
@ -170,6 +228,8 @@ class HAProxy(object):
if weight: if weight:
cmd += "; set weight %s/%s %s" % (pxname, svname, weight) cmd += "; set weight %s/%s %s" % (pxname, svname, weight)
self.execute(cmd) self.execute(cmd)
if self.wait:
self.wait_until_status(pxname, svname, 'UP')
else: else:
pxname = backend pxname = backend
@ -177,6 +237,8 @@ class HAProxy(object):
if weight: if weight:
cmd += "; set weight %s/%s %s" % (pxname, svname, weight) cmd += "; set weight %s/%s %s" % (pxname, svname, weight)
self.execute(cmd) self.execute(cmd)
if self.wait:
self.wait_until_status(pxname, svname, 'UP')
def disabled(self, host, backend, shutdown_sessions): def disabled(self, host, backend, shutdown_sessions):
""" """
@ -200,6 +262,8 @@ class HAProxy(object):
if shutdown_sessions: if shutdown_sessions:
cmd += "; shutdown sessions server %s/%s" % (pxname, svname) cmd += "; shutdown sessions server %s/%s" % (pxname, svname)
self.execute(cmd) self.execute(cmd)
if self.wait:
self.wait_until_status(pxname, svname, 'MAINT')
else: else:
pxname = backend pxname = backend
@ -207,6 +271,8 @@ class HAProxy(object):
if shutdown_sessions: if shutdown_sessions:
cmd += "; shutdown sessions server %s/%s" % (pxname, svname) cmd += "; shutdown sessions server %s/%s" % (pxname, svname)
self.execute(cmd) self.execute(cmd)
if self.wait:
self.wait_until_status(pxname, svname, 'MAINT')
def act(self): def act(self):
""" """
@ -236,6 +302,9 @@ def main():
weight=dict(required=False, default=None), weight=dict(required=False, default=None),
socket = dict(required=False, default=DEFAULT_SOCKET_LOCATION), socket = dict(required=False, default=DEFAULT_SOCKET_LOCATION),
shutdown_sessions=dict(required=False, default=False), shutdown_sessions=dict(required=False, default=False),
wait=dict(required=False, default=False),
wait_retries=dict(required=False, default=WAIT_RETRIES),
wait_interval=dict(required=False, default=WAIT_INTERVAL),
), ),
) )