#!/usr/bin/python # Copyright (c) 2009-2011 by Bjoern Kolbeck, Zuse Institute Berlin # Licensed under the BSD License, see LICENSE file for details. from time import sleep from optparse import OptionParser import os import traceback import subprocess import sys import signal class Server: def __init__(self, start_stop_retries, config_file_path, run_dir_path, xtreemfs_dir, service_name): self._start_stop_retries = start_stop_retries self._config_file_path = config_file_path self._run_dir_path = run_dir_path self._xtreemfs_dir = xtreemfs_dir self._service_name = service_name def _get_pid_file_path(self): return self._run_dir_path def get_config_file_path(self): return self._config_file_path def is_running(self): pid_file_path = self._get_pid_file_path() if os.path.exists(pid_file_path): pid = open(pid_file_path).read().strip() try: pid = int(pid) except ValueError: return False print "xtestenv: checking if server is running with pid", pid # Use 'waitpid' to touch any zombies and ensure that these are # cleaned up first. try: # We dont care about the actual result of waitpid. os.waitpid(int(pid), os.WNOHANG) except OSError: pass return os.path.exists("/proc/" + str(pid)) else: return False def start(self, log_file_path=None): if sys.platform == "win32" or not self.is_running(): pid_file_path = self._get_pid_file_path() java_args = [os.path.join(os.environ["JAVA_HOME"], "bin", "java")] # Enable assertions. java_args.append("-ea") # Construct the -cp classpath XtreemFS_jar_file_path = os.path.abspath(os.path.join(self._xtreemfs_dir, "java", "servers", "dist", "XtreemFS.jar")) if os.path.exists(XtreemFS_jar_file_path): classpath = ( XtreemFS_jar_file_path, os.path.abspath(os.path.join(self._xtreemfs_dir, "java", "lib", "BabuDB.jar")), os.path.abspath(os.path.join(self._xtreemfs_dir, "java", "lib", "protobuf-java-2.5.0.jar")), os.path.abspath(os.path.join(self._xtreemfs_dir, "java", "flease", "dist", "Flease.jar")), os.path.abspath(os.path.join(self._xtreemfs_dir, "java", "foundation", "dist", "Foundation.jar")), os.path.abspath(os.path.join(self._xtreemfs_dir, "java", "lib", "jdmkrt.jar")), os.path.abspath(os.path.join(self._xtreemfs_dir, "java", "lib", "commons-codec-1.3.jar")), ) if sys.platform.startswith("win"): classpath = ";".join(classpath) else: classpath = ":".join(classpath) java_args.extend(("-cp", classpath)) # Name of the class to start java_args.append("org.xtreemfs." + self._service_name.lower() + "." + self._service_name.upper()) # .config file java_args.append(self.get_config_file_path()) # Don't .join java_args, since Popen wants a sequence when shell=False if log_file_path is None: stderr = sys.stderr stdout = sys.stdout else: # Redirect stderr and stdout to a log file stderr = stdout = open(log_file_path, "a") #print "xctl: starting", self.__class__.__name__, "server with UUID", self.get_uuid(), "on port", self.get_rpc_port(), "with", " ".join(java_args) p = subprocess.Popen(java_args, stdout=stdout, stderr=stderr) # No shell=True: we only want one process (java), not two (/bin/sh and java) if p.returncode is not None: raise RuntimeError(self.get_uuid() + " failed to start: " + str(p.returncode)) pidfile = open(pid_file_path, "w+") pidfile.write(str(p.pid)) pidfile.close() print "xtestenv: started", self._service_name, "server with pid", p.pid sleep(2.0) if not self.is_running(): raise RuntimeError, "server failed to start" else: print "xtestenv:", self._service_name, "server is already running" def stop(self): pid_file_path = self._get_pid_file_path() if os.path.exists(pid_file_path): pid = int(open(pid_file_path).read().strip()) if sys.platform.startswith("win"): subprocess.call("TASKKILL /PID %(pid)u /F /T" % locals()) killed = True else: killed = False for signo in (signal.SIGTERM, signal.SIGKILL): for try_i in xrange(self._start_stop_retries): print "xtestenv: stopping", self._service_name, "server with pid", pid, "with signal", str(signo) + ", try", try_i try: os.kill(pid, signo) except: pass sleep(1) # Use 'waitpid' to touch any zombies and ensure that these are # cleaned up first. try: # We dont care about the actual result of waitpid. os.waitpid(int(pid), os.WNOHANG) except OSError: pass killed = not os.path.exists("/proc/" + str(pid)) if killed: break if killed: break if killed: os.unlink(pid_file_path) else: print "FAILED to stop", self._service_name, "server with pid", pid else: print "xtestenv: no pid file for", self._service_name, "server found" START_STOP_SERVICE_RETRIES = 3 if __name__ == "__main__": xtreemfs_dir = os.path.join(os.path.dirname( os.path.abspath( sys.modules[__name__].__file__ ) ), "..") option_parser = OptionParser( "usage: %prog [options]") option_parser.add_option( "-b", "--base-dir", action="store", dest="base_dir", default='/tmp/xtreemfs_xstartserv/') option_parser.add_option( "-c", "--config-file-path", action="store", dest="config_file_path") option_parser.add_option( "--start-dir", action="store_true", dest="dir_start") option_parser.add_option( "--stop-dir", action="store_true", dest="dir_stop") option_parser.add_option( "--start-mrc", action="store_true", dest="mrc_start") option_parser.add_option( "--stop-mrc", action="store_true", dest="mrc_stop") option_parser.add_option( "--start-osd", action="store_true", dest="osd_start") option_parser.add_option( "--stop-osd", action="store_true", dest="osd_stop") option_parser.add_option( "--dir-suffix", action="store", dest="dir_suffix") option_parser.add_option( "--mrc-suffix", action="store", dest="mrc_suffix") option_parser.add_option( "--osd-suffix", action="store", dest="osd_suffix") options, positional_args = option_parser.parse_args() if options.dir_suffix: dir_string = "dir" + options.dir_suffix else: dir_string = "dir" if options.mrc_suffix: mrc_string = "mrc" + options.mrc_suffix else: mrc_string = "mrc" if options.osd_suffix: osd_string = "osd" + options.osd_suffix else: osd_string = "osd" if options.dir_start or options.mrc_start or options.osd_start: try: os.mkdir(options.base_dir) except: pass try: os.mkdir(os.path.join(options.base_dir, "run")) except: pass try: os.mkdir(os.path.join(options.base_dir, "log")) except: pass if options.dir_start: if not options.config_file_path: config_file = os.path.join(xtreemfs_dir, "etc/xos/xtreemfs/" + dir_string + "config.properties") else: config_file = options.config_file_path print "Starting DIR with config:", config_file dir = Server(1, config_file, os.path.join(options.base_dir, "run", "xtreemfs_" + dir_string + ".pid"), xtreemfs_dir, 'DIR') dir.start(os.path.join(options.base_dir, "log", dir_string + ".log")) elif options.dir_stop: print "Stopping DIR..." dir = Server(1, '', os.path.join(options.base_dir, "run", "xtreemfs_" + dir_string + ".pid"), xtreemfs_dir, 'DIR') dir.stop() if options.mrc_start: if not options.config_file_path: config_file = os.path.join(xtreemfs_dir, "etc/xos/xtreemfs/" + mrc_string + "config.properties") else: config_file = options.config_file_path print "Starting MRC with config:", config_file mrc = Server(1, config_file, os.path.join(options.base_dir, "run", "xtreemfs_" + mrc_string + ".pid"), xtreemfs_dir, 'MRC') mrc.start(os.path.join(options.base_dir, "log", mrc_string + ".log")) elif options.mrc_stop: print "Stopping MRC..." mrc = Server(1, '', os.path.join(options.base_dir, "run", "xtreemfs_" + mrc_string + ".pid"), xtreemfs_dir, 'MRC') mrc.stop() if options.osd_start: if not options.config_file_path: config_file = os.path.join(xtreemfs_dir, "etc/xos/xtreemfs/" + osd_string + "config.properties") else: config_file = options.config_file_path print "Starting OSD with config:", config_file osd = Server(1, config_file, os.path.join(options.base_dir, "run", "xtreemfs_" + osd_string + ".pid"), xtreemfs_dir, 'OSD') osd.start(os.path.join(options.base_dir, "log", osd_string + ".log")) elif options.osd_stop: print "Stopping OSD..." osd = Server(1, '', os.path.join(options.base_dir, "run", "xtreemfs_" + osd_string + ".pid"), xtreemfs_dir, 'OSD') osd.stop()