Viewing file: Launcher.py (7.16 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
import sys, signal, time, os
from Ft.Server.Server import Ipc
PID_RUNNING = 0 PID_DEAD = 1 PID_STOPPED = 2 PID_NOT_OWNER = 3
# This get mapped to the appropriate platform launcher # (will be set later) Launcher = None
def RemovePid(pidFile): try: if os.path.exists(pidFile): os.remove(pidFile) except: pass return
def WaitPid(pidFile, seconds=30): timeout = time.time() + seconds while os.path.exists(pidFile) and time.time() < timeout: time.sleep(0.1) return os.path.exists(pidFile)
def _GetExecutable(name): """ This function is for private usage of Ft/Server/Server implementation only. It returns the location of the 4ssd program which is not in the default search PATH for executable applications due to its pre-dependency on 4ss_manager. Please do _not_ use it as general purpose function to determine the location of other executable applications on your platform. """ from Ft import GetConfigVar executable = os.path.join(GetConfigVar('BINDIR'), name) if sys.platform == 'win32': # Determine if we are running a debug Python if sys.executable.endswith('_d.exe'): executable += '_d.exe' else: executable += '.exe' return executable
class LauncherBase:
name = '4ssd'
def __init__(self, username, password, properties): # username, password will provided from the commands authentication # properties refer to the configuration used in the command
self.pidFile = properties['PidFile'] if not os.path.exists(os.path.dirname(self.pidFile)): raise Exception("Unable to use pid file '%s', path is invalid" % self.pidFile)
logfile = properties['LogFile'] if not os.path.exists(os.path.dirname(logfile)): raise Exception("Unable to use log file '%s', path is invalid" % logfile)
executable = _GetExecutable(self.name)
args = [self.name]
# Create the sub-process environment # os.environ is a UserDict, we need a real dictionary environ = os.environ.data.copy()
data = (username, password, properties['CoreId']) environ['FTSS_ENVIRONMENT'] = repr(data) environ['FTSERVER_CONFIG_FILE'] = properties['ConfigFile']
self.process = Ipc.Process(executable, args, environ) return
def info(self, msg): sys.stdout.write(msg + '\n') return
def error(self, msg): msg = '[ERROR] ' + msg sys.stderr.write(msg + '\n') raise Exception(msg)
def _remove_pid(self): if os.path.exists(self.pidFile): try: os.remove(self.pidFile) except Exception, error: sys.stderr.write("Unable to remove pid file '%s': %s\n" % (self.pidFile, str(error))) return
def stop(self): (pid, status) = self.status() self._remove_pid() if status == PID_RUNNING: self.info('Stopping %s' % self.name) self._stop(pid) elif status == PID_DEAD: self.info('%s (pid %d?) not running' % (self.name, pid)) else: self.info('%s (no pid file) is not running' % self.name) return 0
def start(self): (pid, status) = self.status() if status == PID_RUNNING: self.info('%s (pid %s) is already running' % (self.name, pid)) return # Make sure there is a clean slate self._remove_pid() cwd = os.getcwd() exited = 1 try: os.chdir(os.path.dirname(__file__)) pid = self.process.start() exited, code = self.process.wait(0.5) while not exited and not os.path.exists(self.pidFile): exited, code = self.process.wait(0.5) finally: os.chdir(cwd)
if not exited: self.info('%s started (pid %s)' % (self.name, pid)) else: self.info('Error starting %s' % self.name) return pid
def restart(self): (pid, status) = self.status() if status == PID_RUNNING: self.info('Restarting %s...' % self.name) self._stop(pid) elif status == PID_DEAD: self._remove_pid() if WaitPid(self.pidFile): self.error('Unable to stop %s. If you know it\'s not already running, stop and then start again' % self.name) pid = 0 else: pid = self.start() return pid
def reload(self): (pid, status) = self.status() if status == PID_RUNNING: self.info('Reloading %s configuration' % self.name) self._reload(pid) elif status == PID_DEAD: self._remove_pid() else: self.info('%s not running' % self.name) return pid
def status(self): pid, status = 0, PID_STOPPED
if os.path.exists(self.pidFile): try: fd = open(self.pidFile) except Exception, error: sys.stderr.write("Unable to open pid file '%s': %s\n" % (self.pidFile, str(error))) return (pid, status)
try: content = fd.read() except Exception, error: sys.stderr.write("Unable to read pid file '%s': %s\n" % (self.pidFile, str(error))) try: fd.close() except: sys.stderr.write("Error closing file descriptor\n") return (pid, status)
try: fd.close() except: sys.stderr.write("Error closing file descriptor\n")
try: pid = int(content.strip()) except: sys.stderr.write("Invalid pid file '%s'\n" % self.pidFile) else: status = self._status(pid) return (pid, status)
def _stop(self, pid): return
def _reload(self, pid): return
def _status(self, pid): return PID_RUNNING
class PosixLauncher(LauncherBase):
def _stop(self, pid): try: os.kill(pid, signal.SIGTERM) except: pass return
def _reload(self, pid): try: os.kill(pid, signal.SIGHUP) except: pass return
def _status(self, pid): try: os.kill(pid, 0) except: return PID_DEAD return PID_RUNNING
class WindowsLauncher(LauncherBase):
def _stop(self, pid): event = Ipc.Event('ap%dshutdown' % pid) event.set() return
def _reload(self, pid): event = Ipc.Event('ap%drestart' % pid) event.set() return
def _status(self, pid): try: Ipc.OpenEvent('ap%dshutdown' % pid) except: return PID_DEAD return PID_RUNNING
if os.name == 'nt': Launcher = WindowsLauncher
elif os.name == 'posix': Launcher = PosixLauncher
else: raise SystemExit("I don't know how to start servers this platform!")
|