From 5a1abd235d05809bc7a5c4b94ae7bb51add6fc9c Mon Sep 17 00:00:00 2001 From: Aravinda VK Date: Wed, 31 Aug 2016 08:33:44 +0530 Subject: eventsapi: Add Init scripts for different distributions Added init scripts for - SysvInit(CentOS 6 or Red Hat 6) - rc.d (FreeBSD) Most of the latest distributions are using systemd. Support to be added for other distributions which are not using systemd. Removed systemctl wrapper functions(start/stop/status) from gluster-eventsapi CLI(peer_eventsapi.py). Status and Reload re-implemented using pid file check. Added pid file support for glustereventsd. Following dependencies removed python-flask - Only used for example dashboard. User can install if required. python-fasteners - Not available for EPEL 6, added custom code using fcntl as replacement. BUG: 1365395 Change-Id: I26792eae9b11e93304f70b3997cd7d8d03b067f4 Signed-off-by: Aravinda VK Reviewed-on: http://review.gluster.org/15367 Smoke: Gluster Build System CentOS-regression: Gluster Build System Reviewed-by: Niels de Vos NetBSD-regression: NetBSD Build System Reviewed-by: Kaleb KEITHLEY --- events/src/utils.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'events/src/utils.py') diff --git a/events/src/utils.py b/events/src/utils.py index 386e8f28449..db8ebfe29a9 100644 --- a/events/src/utils.py +++ b/events/src/utils.py @@ -12,6 +12,8 @@ import json import os import logging +import fcntl +from errno import ESRCH, EBADF import requests from eventsapiconf import (LOG_FILE, @@ -168,3 +170,78 @@ def plugin_webhook(message): url=url, event=message_json, status_code=resp.status_code)) + + +class LockedOpen(object): + + def __init__(self, filename, *args, **kwargs): + self.filename = filename + self.open_args = args + self.open_kwargs = kwargs + self.fileobj = None + + def __enter__(self): + """ + If two processes compete to update a file, The first process + gets the lock and the second process is blocked in the fcntl.flock() + call. When first process replaces the file and releases the lock, + the already open file descriptor in the second process now points + to a "ghost" file(not reachable by any path name) with old contents. + To avoid that conflict, check the fd already opened is same or + not. Open new one if not same + """ + f = open(self.filename, *self.open_args, **self.open_kwargs) + while True: + fcntl.flock(f, fcntl.LOCK_EX) + fnew = open(self.filename, *self.open_args, **self.open_kwargs) + if os.path.sameopenfile(f.fileno(), fnew.fileno()): + fnew.close() + break + else: + f.close() + f = fnew + self.fileobj = f + return f + + def __exit__(self, _exc_type, _exc_value, _traceback): + self.fileobj.close() + + +class PidFileLockFailed(Exception): + pass + + +class PidFile(object): + def __init__(self, filename): + self.filename = filename + self.pid = os.getpid() + self.fh = None + + def cleanup(self, remove_file=True): + try: + if self.fh is not None: + self.fh.close() + except IOError as exc: + if exc.errno != EBADF: + raise + finally: + if os.path.isfile(self.filename) and remove_file: + os.remove(self.filename) + + def __enter__(self): + self.fh = open(self.filename, 'a+') + try: + fcntl.flock(self.fh.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) + except IOError as exc: + self.cleanup(remove_file=False) + raise PidFileLockFailed(exc) + + self.fh.seek(0) + self.fh.truncate() + self.fh.write("%d\n" % self.pid) + self.fh.flush() + self.fh.seek(0) + return self + + def __exit__(self, _exc_type, _exc_value, _traceback): + self.cleanup() -- cgit