Created
February 10, 2015 23:39
-
-
Save ryancurrah/88a4a7c42cb96d054dc3 to your computer and use it in GitHub Desktop.
Start cloudify celeryd services on cloudify clients
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
""" | |
This script will start services found in the INIT_DIR for Ubuntu or Redhat. | |
The services found can be filtered by using the SERVICE_STARTS_WITH parameter. | |
Required services will be started before the services found using the list parameter REQUIRED_SERVICES. | |
""" | |
from subprocess import Popen, PIPE | |
import time | |
import sys | |
import threading | |
import signal | |
import os | |
import datetime | |
import multiprocessing as mp | |
# Public vars | |
INIT_DIR = '/etc/init.d' # String - No trailing slashes please | |
SERVICE_STARTS_WITH = 'celeryd-' # String | |
REQUIRED_SERVICES = [] # List of Strings | |
# Private vars | |
_REQUIRED_PYTHON_VERSION = (2, 6) | |
_OS_FLAVOR = 'redhat' if os.path.isfile('/etc/redhat-release') else \ | |
'ubuntu' if os.path.isfile('/etc/lsb-release') else \ | |
'ubuntu' | |
_STARTED_MESSAGE = "datetime: {0}, service name: {1}, started: {2}" | |
_FOUND_SERVICES = [] | |
def main(): | |
# Exit script with error if Python is not correct version | |
_check_version() | |
# Get list of services | |
if SERVICE_STARTS_WITH: | |
print "\nfinding services that start with '{0}'...".format(SERVICE_STARTS_WITH) | |
else: | |
print "\nfinding services..." | |
_FOUND_SERVICES.extend(_get_files(INIT_DIR, SERVICE_STARTS_WITH)) | |
# If no services found exit and let user know | |
if not _FOUND_SERVICES and SERVICE_STARTS_WITH: | |
print "...done no services found starting with '{0}' exiting.\n".format(SERVICE_STARTS_WITH) | |
sys.exit(0) | |
elif not _FOUND_SERVICES: | |
print "...done no services found exiting.\n" | |
sys.exit(0) | |
print "...done found {0} services\n".format(len(_FOUND_SERVICES)) | |
# Start required services | |
print "starting required services..." | |
start_required_services() | |
print "...done\n" | |
# Start found services | |
print "starting found services..." | |
async_start_found_services() | |
print "...done\n" | |
return | |
def worker(service): | |
""" | |
Async worker/task that starts specified service name | |
""" | |
if is_service_running(service): | |
print _STARTED_MESSAGE.format(get_datetime(), service, "already started") | |
else: | |
print _STARTED_MESSAGE.format(get_datetime(), service, start_service(service)) | |
return | |
def async_start_found_services(): | |
""" | |
Start found services asynchronously, up to 5 workers maximum | |
""" | |
pool = mp.Pool(processes=10) | |
for service in _FOUND_SERVICES: | |
pool.apply_async(worker, args=(service,)) | |
pool.close() | |
pool.join() | |
return | |
def start_required_services(): | |
for required_service in REQUIRED_SERVICES: | |
if os.path.isfile("{0}/{1}".format(INIT_DIR.rstrip('/'), required_service)): | |
if not is_service_running(required_service): | |
print _STARTED_MESSAGE.format(get_datetime(), required_service, start_service(required_service)) | |
else: | |
print _STARTED_MESSAGE.format(get_datetime(), required_service, "already started") | |
else: | |
print _STARTED_MESSAGE.format(get_datetime(), required_service, "service not found") | |
sys.exit(1) | |
def get_datetime(): | |
""" | |
Returns a datetime object | |
""" | |
return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') | |
def is_service_running(service_name): | |
""" | |
Checks if service is active returns True for running or False for stopped | |
""" | |
# Choose which command to use based on OS FLAVOR, defaults to Ubuntu | |
if _OS_FLAVOR == 'ubuntu': | |
command = ['service', service_name, 'status'] | |
elif _OS_FLAVOR == 'redhat': | |
command = ['service', service_name, 'status'] | |
else: | |
command = ['service', service_name, 'status'] | |
# Execute! | |
stdout, stderr, returncode = _execute_command(command, retry_count=2, command_sleep=1, command_timeout=20) | |
if returncode == 0: | |
running = True | |
else: | |
running = False | |
return running | |
def start_service(service_name): | |
""" | |
Starts service returns True for started or False for stopped | |
""" | |
# Choose which command to use based on OS FLAVOR, defaults to Ubuntu | |
if _OS_FLAVOR == 'ubuntu': | |
command = ['service', service_name, 'start'] | |
elif _OS_FLAVOR == 'redhat': | |
command = ['service', service_name, 'start'] | |
else: | |
command = ['service', service_name, 'start'] | |
# Execute! | |
stdout, stderr, returncode = _execute_command(command, retry_count=2, command_sleep=1, command_timeout=20) | |
if returncode == 0: | |
started = True | |
else: | |
started = False | |
return started | |
def _get_files(directory='/etc/init.d', starts_with=''): | |
""" | |
Returns filenames as a list | |
""" | |
directory = directory.rstrip('/') | |
filenames = [] | |
for filename in os.listdir(directory): | |
if os.path.isfile("{0}/{1}".format(directory, filename)): | |
if starts_with: | |
if filename.startswith(starts_with): | |
filenames.append(filename) | |
else: | |
filenames.append(filename) | |
return filenames | |
def _execute_command(command, | |
environment=None, | |
retry_count=0, | |
command_sleep=0, | |
command_timeout=0): | |
""" | |
:param command: Command and it's parameters as a List of Strings | |
:param environment: Key value list of environment variables to set | |
:param retry_count: Integer number of retries that will execute run() again on failure | |
:param command_sleep: Integer number of seconds to sleep for after executing command | |
:param command_timeout: Integer number of seconds to wait before killing the run() function | |
:return: results as Tuple stdout, stderr, returncode | |
""" | |
def run(): | |
if command_timeout: | |
kill_check = threading.Event() | |
def _kill_process_after_a_timeout(process_id): | |
os.kill(process_id, signal.SIGTERM) | |
kill_check.set() # tell the main routine that we had to kill | |
# use SIGKILL if hard to kill... | |
return | |
process = Popen(command, stdout=PIPE, stderr=PIPE, env=environment) | |
pid = process.pid | |
watchdog = threading.Timer(command_timeout, _kill_process_after_a_timeout, args=(pid, )) | |
watchdog.start() | |
stdout, stderr = process.communicate() | |
watchdog.cancel() # if it's still waiting to run | |
returncode = process.returncode | |
if kill_check.isSet(): | |
returncode = 1 | |
stdout = "executing {0} took to long and timedout. " \ | |
"the timeout limit is {1} seconds".format(' '.join(command), command_timeout) | |
stderr = stdout | |
else: | |
process = Popen(command, stdout=PIPE, stderr=PIPE, env=environment) | |
stdout, stderr = process.communicate() | |
returncode = process.returncode | |
return stdout, stderr, returncode | |
retry_count += 1 # number of retries plus the initial execution | |
stdout = None | |
stderr = None | |
returncode = None | |
for retry in range(retry_count): | |
stdout, stderr, returncode = run() | |
time.sleep(command_sleep) | |
if returncode == 0: | |
break | |
return stdout, stderr, returncode | |
def _check_version(): | |
""" | |
Exits out of program if running python version out of date | |
""" | |
req_version = _REQUIRED_PYTHON_VERSION | |
cur_version = sys.version_info | |
if not cur_version >= req_version: | |
print "your Python interpreter is too old. Please consider upgrading. " \ | |
"this script requires {0} or higher.".format(req_version) | |
sys.exit(1) | |
return | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment