#!/usr/bin/env python """ This is a helper program for the MoltenIron server. """ # Copyright (c) 2016 IBM Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # pylint: disable-msg=C0103 # pylint: disable=redefined-outer-name import argparse from daemonize import Daemonize from molteniron import moltenirond import os from pkg_resources import resource_filename import signal import sys import yaml PID = "/var/run/moltenirond.pid" YAML_CONF = None ERROR_LOGFILE = "/tmp/MoltenIron-error-logfile" class MoltenIronPIDNotFound(RuntimeError): """os.path.isfile() error: The PID file does not exist""" class MoltenIronKillError(RuntimeError): """os.kill() error""" class MoltenIronReadLinesError(RuntimeError): """fobj.readlines() error""" def get_moltenirond_pid(): """Return the PID of the MoltenIron server process.""" if not os.path.isfile(PID): raise MoltenIronPIDNotFound("isfile error %s" % (PID, )) with open(PID) as fobj: lines = fobj.readlines() try: pid = int(lines[0]) try: # Send harmless kill signal in order to test existance os.kill(pid, 0) except Exception as e: raise MoltenIronKillError("os.kill error: %s" % (e, )) return pid except Exception as e: raise MoltenIronReadLinesError("readlines error: %s" % (e, )) def moltenirond_main(): """This is the main routine for the MoltenIron server.""" with open(YAML_CONF, "r") as fobj: conf = yaml.load(fobj) moltenirond.listener(conf) def log_error(s): """Log an error to stderr and to a file.""" with open(ERROR_LOGFILE, "a+") as fobj: fobj.writelines(s + "\n") print(s, file=sys.stderr) if __name__ == "__main__": parser = argparse.ArgumentParser(description="Molteniron daemon helper") parser.add_argument("-c", "--conf-dir", action="store", type=str, dest="conf_dir", help="The directory where configuration is stored") parser.add_argument("-p", "--pid-dir", action="store", type=str, dest="pid_dir", help="The directory where PID information is stored") parser.add_argument("-v", "--verbose", action="store", type=bool, dest="verbose", help="Set a verbose information mode") parser.add_argument("command", type=str, nargs=1, help="the command") args = parser.parse_args() if args.conf_dir: if not os.path.isdir(args.conf_dir): msg = "Error: %s is not a valid directory" % (args.conf_dir, ) print(msg, file=sys.stderr) sys.exit(1) YAML_CONF = os.path.realpath("%s/conf.yaml" % (args.conf_dir, )) else: YAML_CONF = resource_filename("molteniron", "conf.yaml") # Test for read ability fobj = open(YAML_CONF, "r") fobj.close() if args.pid_dir: if not os.path.isdir(args.pid_dir): msg = "Error: %s is not a valid directory" % (args.pid_dir, ) print(msg, file=sys.stderr) sys.exit(1) PID = os.path.realpath("%s/moltenirond.pid" % (args.pid_dir, )) if args.verbose: print("YAML_CONF = %s" % (YAML_CONF, )) print("PID = %s" % (PID, )) if len(args.command) != 1: msg = "Error: Expecting one command? Received: %s" % (args.command, ) log_error(msg) sys.exit(1) if args.command[0].upper().lower() == "start": try: pid = get_moltenirond_pid() except MoltenIronPIDNotFound: pid = -1 if pid > 0: log_error("Error: The daemon is already running") sys.exit(1) daemon = Daemonize(app="moltenirond", pid=PID, action=moltenirond_main) daemon.start() elif args.command[0].upper().lower() == "stop": try: pid = get_moltenirond_pid() except MoltenIronPIDNotFound: pid = -1 if pid > 0: os.remove(PID) os.kill(pid, signal.SIGTERM) else: log_error("Error: The daemon doesn't exist?") log_error("Error: pid = %d" % (pid, )) sys.exit(1) else: msg = "Error: Unknown command: %s" % (args.command[0], ) log_error(msg) sys.exit(1)