#!/opt/opensvc/bin/python
#
# Copyright (c) 2009 Christophe Varoqui <christophe.varoqui@free.fr>'
# Copyright (c) 2009 Cyril Galibern <cyril.galibern@free.fr>'
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
import sys
import os
import optparse
import string

#
# add project lib to path
#
pathsvc = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
pathetc = os.path.join(pathsvc, 'etc')
sys.path.append(os.path.join(pathsvc, 'lib'))
prog = os.path.basename(__file__)

import svcBuilder
import rcExceptions as ex
from rcUtilities import *
from lock import *
import node

node = node.Node()


try:
    from version import version
except:
    version = "dev"

def svcmon_verbose(svcs):
    for svc in svcs:
        try:
            svc.print_status()
        except:
            pass

def max_len(svcs, attr):
    _len = 7
    for svc in svcs:
        if _len < len(getattr(svc, attr)):
            _len = len(getattr(svc, attr))
    return _len

def svcmon_normal1(svc, upddb=False, fmt=None, queue=None):
    status = svc.group_status()
    print fmt % (
              svc.svcname,
              svc.svctype,
              svc.svcmode,
              status["container"],
              status["ip"],
              status["disk"],
              status["fs"],
              status["app"],
              status["hb"],
              status["sync"],
              status["avail"],
              status["overall"],
              svc.frozen())
    if upddb:
        lockf = 'svcmon.'+svc.svcname+'.lock'
	try:
	    lockfd = monlock(fname=lockf)
	except ex.excError:
	    sys.exit(1)
        except:
            import traceback
            traceback.print_exc()
	    sys.exit(1)

        if queue is None:
            # multiprocess Queue not supported, can't combine results
            g_vars, g_vals, r_vars, r_vals = svc.svcmon_push_lists(status)
            svc.node.collector.call('svcmon_update_combo', g_vars, g_vals, r_vars, r_vals)
        else:
            queue.put(svc.svcmon_push_lists(status))

	try:
	    monunlock(lockfd)
	except ex.excError:
	    sys.exit(1)
        except:
            import traceback
            traceback.print_exc()
	    sys.exit(1)

def svcmon_normal(svcs, upddb=False):
    fmt = '%-' + str(max_len(svcs, "svcname")) + 's'
    fmt += ' %-7s %-9s %-9s %-9s %-10s %-10s %-10s %-9s %-9s %-10s %-10s %-6s'

    print fmt % ("service", "service", "container", "container", "ip    ", "disk  ", "fs    ", "app   ", "hb    ", "sync  ", "avail ", "overall", "      ")
    print fmt % ("name   ", "type   ", "type     ", "status   ", "status", "status", "status", "status", "status", "status", "status", "status ", "frozen")
    print fmt % ("-------", "-------", "---------", "---------", "------", "------", "------", "------", "------", "------", "------", "-------", "------")
    from multiprocessing import Process, Queue
    ps = []
    queues = {}
    for svc in svcs:
        try:
            queues[svc.svcname] = Queue()
        except:
            # some platform don't support Queue's synchronize (bug 3770)
            queues[svc.svcname] = None
        p = Process(target=svcmon_normal1, args=(svc, upddb, fmt, queues[svc.svcname]))
        p.start()
        ps.append(p)
    for p in ps:
        p.join()

    if upddb:
        g_vals = []
        r_vals = []
        if options.delay > 0:
            import random
            import time
            delay = int(random.random()*options.delay)
            time.sleep(delay)

        for svc in svcs:
            if queues[svc.svcname] is None:
                continue
            g_vars, _g_vals, r_vars, _r_vals = queues[svc.svcname].get()
            g_vals.append(_g_vals)
            r_vals.append(_r_vals)
        if len(g_vals) > 0:
            svc.node.collector.call('svcmon_update_combo', g_vars, g_vals, r_vars, r_vals)

__ver = prog + " version " + version
__usage = "%prog [options]\n\nDisplay services status"
parser = optparse.OptionParser(version=__ver, usage=__usage)
parser.add_option("--service", default="", action="store", dest="parm_svcs",
                  help="comma-separated list of service to display status of")
parser.add_option("--updatedb", default=False, action="store_true", dest="upddb",
                  help="update resource status in central database")
parser.add_option("--verbose", default=False, action="store_true", dest="verbose",
                  help="display per-resource status for each selected service")
parser.add_option("--maxdelaydb", default=0, action="store", type="int", dest="delay",
                  help="introduce a random delay before pushing to database to level the load on the collector")

(options, args) = parser.parse_args()

if len(options.parm_svcs) > 0:
    node.build_services(svcnames=options.parm_svcs.split(','))
else:
    node.build_services()

if options.verbose:
    svcmon_verbose(node.svcs)
else:
    svcmon_normal(node.svcs, options.upddb)

node.close()
