Skip to content

Instantly share code, notes, and snippets.

@andelf
Created December 27, 2016 12:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andelf/a3cfe26efb71801fb36377a61be6b882 to your computer and use it in GitHub Desktop.
Save andelf/a3cfe26efb71801fb36377a61be6b882 to your computer and use it in GitHub Desktop.
Ansible task: wait for pid and threads
#!/usr/bin/python
# -*- coding: utf-8 -*-
import binascii
import datetime
import math
import re
import select
import socket
import sys
import time
import os
from ansible.module_utils._text import to_native
def main():
module = AnsibleModule(
argument_spec = dict(
pid=dict(default=None, type='int'),
pid_file=dict(default=None, type='path'),
timeout=dict(default=300, type='int'),
delay=dict(default=0, type='int'),
thread_name_regex=dict(default=None, type='str'),
thread_num=dict(default=1, type='int'),
state=dict(default='present', choices=['present', 'absent']),
sleep=dict(default=1, type='int')
),
)
params = module.params
pid = params['pid']
pid_file = params['pid_file']
timeout = params['timeout']
delay = params['delay']
thread_name_regex = params['thread_name_regex']
thread_num = params['thread_num']
state = params['state']
sleep = params['sleep']
if thread_name_regex is not None:
compiled_search_re = re.compile(thread_name_regex, re.MULTILINE)
else:
compiled_search_re = None
if pid and pid_file:
module.fail_json(msg="pid and pid_file parameter can not both be passed to wait_for_pid")
start = datetime.datetime.now()
if delay:
time.sleep(delay)
if not pid and not pid_file:
time.sleep(timeout)
elif state == 'absent':
### first wait for the stop condition
end = start + datetime.timedelta(seconds=timeout)
while datetime.datetime.now() < end:
try:
if pid_file:
f = open(pid_file)
pid = f.read().strip()
f.close()
f = open("/proc/%s/comm' %s pid")
f.close()
except IOError:
break
except:
break
# Conditions not yet met, wait and try again
time.sleep(params['sleep'])
else:
elapsed = datetime.datetime.now() - start
if pid_file:
module.fail_json(msg="Timeout when waiting for PID:%s to stop." % (pid_file), elapsed=elapsed.seconds)
elif pid:
module.fail_json(msg="Timeout when waiting for PID:%s to be absent." % (pid), elapsed=elapsed.seconds)
elif state == 'present':
### wait for start condition
end = start + datetime.timedelta(seconds=timeout)
while datetime.datetime.now() < end:
try:
if pid_file:
f = open(pid_file)
pid = f.read().strip()
f.close()
f = open('/proc/%s/comm' % pid)
f.close()
except (OSError, IOError):
e = get_exception()
# If anything except file not present, throw an error
if e.errno != 2:
elapsed = datetime.datetime.now() - start
module.fail_json(msg="Failed to stat %s, %s" % (path, e.strerror), elapsed=elapsed.seconds)
# file doesn't exist yet, so continue
else:
# process exists. Are there additional things to check?
if not compiled_search_re:
# nope, succeed!
break
try:
matches = 0
for thread in os.listdir('/proc/%s/task' % pid):
f = open('/proc/%s/task/%s/comm' % (pid, thread))
try:
if re.search(compiled_search_re, f.read()):
matches += 1
finally:
f.close()
if matches >= thread_num:
# found, success!
break
except (OSError, IOError):
pass
# Conditions not yet met, wait and try again
time.sleep(params['sleep'])
else: # while-else
# Timeout expired
elapsed = datetime.datetime.now() - start
if pid_file:
module.fail_json(msg="Timeout when waiting for PID:%s to stop." % (pid_file), elapsed=elapsed.seconds)
elif pid:
module.fail_json(msg="Timeout when waiting for PID:%s to be absent." % (pid), elapsed=elapsed.seconds)
elapsed = datetime.datetime.now() - start
module.exit_json(state=state, pid=pid, thread_name_regex=thread_name_regex, pid_file=pid_file, elapsed=elapsed.seconds)
# import module snippets
from ansible.module_utils.basic import *
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment