#!/usr/bin/env python
#  -*- mode: python; -*-
#============================================================================
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
#============================================================================

"""Xen management daemon. Lives in /usr/sbin.
   Provides console server and HTTP management api.

   Run:
   xend start

   Restart:
   xend restart

   The daemon is stopped with:
   xend stop

   The daemon should reconnect to device control interfaces
   and recover its state when restarted.
"""
import os
import sys
import socket
import signal
import time
import commands

XCS_PATH    = "/var/lib/xen/xcs_socket"
XCS_EXEC    = "/usr/sbin/xcs"
XCS_PIDFILE = "/var/run/xcs.pid"
XCS_ARGS    = (XCS_EXEC, "-p", XCS_PIDFILE)

# add fallback path for non-native python path installs if needed
sys.path.append('/usr/lib/python')
sys.path.append('/usr/lib64/python')
from xen.xend.server import SrvDaemon

class CheckError(ValueError):
    pass

def hline():
    print >>sys.stderr, "*" * 70

def msg(message):
    print >>sys.stderr, "*" * 3, message

def check_logging():
    """Check python logging is installed and raise an error if not.
    Logging is standard from Python 2.3 on.
    """
    try:
        import logging
    except ImportError:
        hline()
        msg("Python logging is not installed.")
        msg("Use 'make install-logging' at the xen root to install.")
        msg("")
        msg("Alternatively download and install from")
        msg("http://www.red-dove.com/python_logging.html")
        hline()
        raise CheckError("logging is not installed")

def check_user():
    """Check that the effective user id is 0 (root).
    """
    if os.geteuid() != 0:
        hline()
        msg("Xend must be run as root.")
        hline()
        raise CheckError("invalid user")

def xcs_running():
    """ See if the control switch is running.
    """	
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    try:
        s.connect( (XCS_PATH) )
        s.close()
    except:
        try:
            os.remove(XCS_PIDFILE)
        except:
            pass
	return 0
    return 1
    
def start_xcs():
    if (not xcs_running()):
        if os.fork() == 0 :
            if not os.path.isdir(os.path.dirname(XCS_PATH)):
                os.makedirs(os.path.dirname(XCS_PATH))
            try:
                os.execvp(XCS_EXEC, XCS_ARGS)
            except:
                hline()
                msg("Tried to start xcs, but failed. Is it installed?")
                hline()
                raise CheckError("couldn't start xcs")
        for n in range(10) :
            if (xcs_running()):
                break
            time.sleep(0.1)
        else :
                hline()
                msg("Failed to start the control interface switch.")
                hline()
                raise CheckError("xcs not running")
            
def stop_xcs():
    try:
	xcs_pidfile = open(XCS_PIDFILE)
        xcs_pid = int(xcs_pidfile.read().strip())
        os.kill(xcs_pid, signal.SIGTERM)
        xcs_pidfile.close()
    except:
	return    

def start_xenstored():
    XENSTORED_TRACE = os.getenv("XENSTORED_TRACE")
    cmd = "/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid"
    if XENSTORED_TRACE:
        cmd += " -T /var/log/xenstored-trace.log"
    s,o = commands.getstatusoutput(cmd)

def start_consoled():
    if os.fork() == 0:
        os.execvp('/usr/sbin/xenconsoled', ['/usr/sbin/xenconsoled'])
            
def main():
    try:
        check_logging()
        check_user()
    except CheckError:
        sys.exit(1)
    
    daemon = SrvDaemon.instance()
    if not sys.argv[1:]:
        print 'usage: %s {start|stop|restart}' % sys.argv[0]
    elif os.fork():
        pid, status = os.wait()
        return status >> 8
    elif sys.argv[1] == 'start':
        start_xcs()
        start_xenstored()
        start_consoled()
        return daemon.start()
    elif sys.argv[1] == 'trace_start':
        start_xcs()
        start_xenstored()
        start_consoled()
        return daemon.start(trace=1)
    elif sys.argv[1] == 'stop':
        stop_xcs()
        return daemon.stop()
    elif sys.argv[1] == 'restart':
        stop_xcs()
        start_xcs()
        start_xenstored()
        start_consoled()
        return daemon.stop() or daemon.start()
    elif sys.argv[1] == 'status':
        return daemon.status()
    else:
        print 'not an option:', sys.argv[1]
    return 1

if __name__ == '__main__':
    sys.exit(main())
