Skip to content

Instantly share code, notes, and snippets.

@DanyHenriquez
Created February 22, 2015 03:14
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 DanyHenriquez/36eb5050176e0daee6a5 to your computer and use it in GitHub Desktop.
Save DanyHenriquez/36eb5050176e0daee6a5 to your computer and use it in GitHub Desktop.
Ansible push daemon
#!/usr/bin/env python
import time, yaml, sys, os, atexit, signal, subprocess
class Daemon(object):
def __init__(self, pidfile, stdin=os.devnull,
stdout=os.devnull, stderr=os.devnull,
home_dir='.', umask=022, verbose=1):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
self.home_dir = home_dir
self.verbose = verbose
self.umask = umask
self.daemon_alive = True
def daemonize(self):
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
sys.stderr.write(
"fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
os.chdir(self.home_dir)
os.setsid()
os.umask(self.umask)
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
sys.stderr.write(
"fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
if sys.platform != 'darwin':
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
if self.stderr:
se = file(self.stderr, 'a+', 0)
else:
se = so
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
def sigtermhandler(signum, frame):
self.daemon_alive = False
signal.signal(signal.SIGTERM, sigtermhandler)
signal.signal(signal.SIGINT, sigtermhandler)
if self.verbose >= 1:
print "Started"
atexit.register(
self.delpid)
pid = str(os.getpid())
file(self.pidfile, 'w+').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self, *args, **kwargs):
if self.verbose >= 1:
print "Starting..."
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
except SystemExit:
pid = None
if pid:
message = "pidfile %s already exists. Is it already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
self.daemonize()
self.run(*args, **kwargs)
def stop(self):
if self.verbose >= 1:
print "Stopping..."
pid = self.get_pid()
if not pid:
message = "pidfile %s does not exist. Not running?\n"
sys.stderr.write(message % self.pidfile)
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
return
try:
i = 0
while 1:
os.kill(pid, signal.SIGTERM)
time.sleep(0.1)
i = i + 1
if i % 10 == 0:
os.kill(pid, signal.SIGHUP)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
if self.verbose >= 1:
print "Stopped"
def restart(self):
self.stop()
self.start()
def get_pid(self):
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
except SystemExit:
pid = None
return pid
def is_running(self):
pid = self.get_pid()
if pid == None:
print 'Process is stopped'
elif os.path.exists('/proc/%d' % pid):
print 'Process (pid %d) is running...' % pid
else:
print 'Process (pid %d) is killed' % pid
return pid and os.path.exists('/proc/%d' % pid)
def run(self):
raise NotImplementedError
class AnsiblePush(Daemon):
def run(self):
while True:
with open('/etc/ansible/andible-daemon.yml') as command_file:
commands = yaml.load(command_file.read())
for command in commands:
subprocess.call('ansible-playbook ' + command, shell=True)
time.sleep(900)
ansible_push = AnsiblePush('/tmp/ansible-push.pid')
if sys.argv[1] == 'start':
ansible_push.start()
if sys.argv[1] == 'stop':
ansible_push.stop()
if sys.argv[1] == 'restart':
ansible_push.restart()
if sys.argv[1] == 'run':
ansible_push.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment