#!/usr/libexec/isilon/isi_ph_rpcd
# ex: set shiftwidth=4 tabstop=4 expandtab:
# Copyright C 2002-2008 by Isilon Systems, Inc. All rights not expressly
# granted herein are reserved.
# Created in the United States of America.
#
# This digital media is protected by U.S. and international copyright and
# intellectual property laws. Unless otherwise specified, all information
# and screens appearing as part of this digital medium, including
# software, services, documents, text, images, icons, and logos design;
# the selection, assembly, arrangement, and design thereof; and the code
# that enables its presentation, are the sole property of Isilon Systems,
# Inc.
#
# Except as otherwise required by applicable law, no part of any
# copyrighted material may be reproduced, modified, translated,
# distributed, published, or transmitted by any means, electronic or
# mechanical, for any purpose, without the prior written consent of Isilon
# Systems.
#
# Isilon and Isilon Systems are registered trademarks of Isilon Systems,
# Inc.  "Isilon IQ" is a trademark of Isilon Systems, Inc.  All other
# trademarks and registered trademarks are the property of their
# respective holders.

import errno
import getopt
import os
import signal
import socket
import sys
import time

try:
    import isi.ph.comms as comms
    import isi.ph.handlers as handlers
    import isi.ph.util as util
    from isi.ph.util import Log
    from isi.ph.util import err
except ImportError:
    try:
        # old-style, from ph directory
        import comms as comms
        import handlers as handlers
        import util as util
        from util import Log
        from util import err
    except ImportError:
        print "Either run on a node or from within the ph library directory."
        sys.exit(1)


def Version():
    return "$Revision: 260035 $".split(" ")[1]

def usage():
    print"""Usage %s [-hlps]

    -h: Show this help message
    -l: Log file; default /var/log/isi_ph_rpcd.log
    -p: Port for isi_ph_rpcd
    -s: Run in foreground
    --version: Print module versions and exit\n""" % sys.argv[0]
    sys.exit(1)


if __name__ == "__main__" :
    try:
        import isi.ph.handlers as handlers
        import isi.ph.createfilecommand as createfilecommand
        import isi.ph.fsxslave as fsxslave
        import isi.ph.getarrayinfo as getarrayinfo
        import isi.ph.mkdircommand as mkdircommand
        import isi.ph.nodeconfcommand as nodeconfcommand
        import isi.ph.perfcollector as perfcollector
        import isi.ph.readstream as readstream
        import isi.ph.readthread as readthread
        import isi.ph.resumeprocesses as resumeprocesses
        import isi.ph.setproccommand as setproccommand
        import isi.ph.shellcommand as shellcommand
        import isi.ph.suspendprocesses as suspendprocesses
        import isi.ph.synccommand as synccommand
        import isi.ph.sysctlcommand as sysctlcommand
        import isi.ph.timecommand as timecommand
        import isi.ph.timedsysctlcommand as timedsysctlcommand
        import isi.ph.umountifscommand as umountifscommand
        import isi.ph.unamecommand as unamecommand
        import isi.ph.versioncommand as versioncommand
        import isi.ph.writestream as writestream
        import isi.ph.writethread as writethread
        import isi.ph.createpool as createpool
        import isi.ph.edafindcreatedataset as edafindcreatedataset
        import isi.ph.edabuildcreatedataset as edabuildcreatedataset
        import isi.ph.backupcreatedataset as backupcreatedataset
        import isi.ph.flushcache as flushcache
        import isi.ph.snapshotcommand as snapshotcommand
        import isi.ph.nodecommand as nodecommand
        import isi.ph.microbenchthreads as microbenchthreads
        import isi.ph.streaming_write_test_thread_handler as swtt
        import isi.app.daemon as daemon
    except ImportError:
        # old-style
        import handlers
        import createfilecommand
        import fsxslave
        import getarrayinfo
        import mkdircommand
        import nodeconfcommand
        import perfcollector
        import readstream
        import readthread
        import resumeprocesses
        import setproccommand
        import shellcommand
        import suspendprocesses
        import synccommand
        import sysctlcommand
        import timecommand
        import timedsysctlcommand
        import umountifscommand
        import unamecommand
        import versioncommand
        import writestream
        import writethread
        import edafindcreatedataset
        import edabuildcreatedataset
        import backupcreatedataset
        import flushcache
        import nodecommand
        import snapshotcommand
        import microbenchthreads
        import streaming_write_test_thread_handler as swtt
        daemon = None

    createfilecommand.Register()
    fsxslave.Register()
    getarrayinfo.Register()
    mkdircommand.Register()
    nodeconfcommand.Register()
    perfcollector.Register()
    readstream.Register()
    readthread.Register()
    resumeprocesses.Register()
    setproccommand.Register()
    shellcommand.Register()
    suspendprocesses.Register()
    synccommand.Register()
    sysctlcommand.Register()
    timecommand.Register()
    timedsysctlcommand.Register()
    umountifscommand.Register()
    unamecommand.Register()
    versioncommand.Register()
    writestream.Register()
    writethread.Register()
    createpool.Register()
    edafindcreatedataset.Register()
    edabuildcreatedataset.Register()
    backupcreatedataset.Register()
    flushcache.Register()
    snapshotcommand.Register()
    nodecommand.Register()
    microbenchthreads.Register()
    swtt.Register()

    program = os.path.basename(sys.argv[0])

    daemonize  = True
    logfile = "/var/log/isi_ph_rpcd.log"
    pidfile = None

    flags, others = getopt.getopt(sys.argv[1:], "hl:p:sv",
                                  [ "help", "port=", "version" ])
    for opt in flags:
        flag = opt[0]
        if flag == "-h" or flag == "--help":
            usage()
        elif flag == "-l":
            logfile = opt[1]
        elif flag == "-p" or flag == "--port":
            util.SetServerPort(opt[1])
        elif flag == "-s":
            daemonize = False
        elif flag == "-v" or flag == "--version":
            util.PrintVersions(program, Version())

    # this is only needed to coax MCP along
    if others and others[0] in ("stop", "restart"):
        if not daemon:
            err("stop and restart only supported on OneFS")

        pidfile = daemon.PidFile()
        pid = pidfile.getpid()
        if pid:
            from commands import getstatusoutput as run
            code, out = run("/bin/ps -w '%s' 2>&1" % pid)

            kill = False
            if program in out:
                kill = True
            elif code == 0:
                lines = out.split("\n")
                if len(lines) == 2:
                    print "Stale pid %s names '%s'" % (pid, lines[1][26:])
                else:
                    err("Unknown output from ps: " + out)

            if kill:
                print "Stopping pid: %s" % pid
                try:
                    os.kill(pid, signal.SIGTERM)
                    time.sleep(0.25)
                    os.kill(pid, signal.SIGKILL)
                except OSError, e:
                    if e.errno != errno.ESRCH:
                        raise

            pidfile.remove()
            del pidfile

        if others[0] == "stop":
            sys.exit(0)

    if daemonize:
        error = util.Daemonize(logfile)
        if error:
            err(error)
    elif sys.platform == "win32":
        # otherwise it will hang waiting for a keypress
        sin = os.open('nul', os.O_RDONLY)

    cs = None
    try:
        cs = handlers.CommandServer(handlers.OvtResourceMapper)
    except socket.error:
        Log("%s already running on port %s" % (program, util.GetServerPort()))
        sys.exit(1)

    # if running on the nodes, want a pid file for MCP to use
    # will be removed automatically on exit
    if daemonize and daemon:
        pidfile = daemon.PidFile()
        pidfile.write(os.getpid())

        def terminated(sig, frame, pid=pidfile):
            del pid
            Log("SIGTERM")
            sys.exit(0)

        signal.signal(signal.SIGTERM, terminated)

    Log(program + " starting")

    try:
        comms.GetQueueSelector().Run()
    finally:
        del pidfile

