#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# This file is part of Karesansui.
#
# Copyright (C) 2009 HDE, Inc.
#
# 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.
#

import os
import sys
import re
import grp
import traceback
import time
import fcntl
import optparse

from installer.const import *
from installer.trans import _, N_
from installer.utils import *
from installer.rpmlib import RpmLib

env = os._Environ(os.environ)
config = env.get('KARESANSUI_CONF')

class CheckEnvError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

def opt_parser():
    parser = optparse.OptionParser()
    parser.add_option("-c", "--config",
                action="store", dest="config", default=DEFAULT_KARESANSUI_CONF,
                help=_("Config file location"))
    return parser

def main():
    if os.getuid() != 0:
        print _("ERROR: This program must be executed by super user.")
        sys.exit()

    print deco_msg("@==========================================@","bold")
    print deco_msg("@   Karesansui Environment Check Program   @","bold")
    print deco_msg("@==========================================@","bold")

    parser = opt_parser()
    (opts,args) = parser.parse_args()

    if config is not None:
        opts.config = config
    os.environ['KARESANSUI_CONF'] = opts.config

    """ Check if Karesansui RPM packages are installed completely. """
    print _("Checking if Karesansui RPM packages are installed completely..."),
    rpmlib = RpmLib()
    ret = rpmlib.doQuery(CORE_PKGS)
    for pkg in CORE_PKGS:
        try:
            ret[pkg]
        except:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: package '%s' has not been installed yet.") % (pkg,))
    print deco_msg(_("OK"),"green")

    """ Check if Karesansui config parameters are enough. """
    print _("Checking if Karesansui config parameters are enough... "),
    require_params = ["application.search.path",
                      "pysilhouette.conf.path",
                      "database.bind",
                     ]
    for param in require_params:
        try:
            sh_config_read(opts.config)[param]
        except:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: parameter '%s' is not found in %s.") % (param,opts.config,))
    print deco_msg(_("OK"),"green")

    """ Set search paths """
    search_path = sh_config_read(opts.config)["application.search.path"]
    for y in [x.strip() for x in search_path.split(',') if x]:
        if (y in sys.path) is False: sys.path.insert(0, y)

    """ Check if Karesansui modules can be imported. """
    print _("Checking if Karesansui modules can be imported... "),
    try:
        import karesansui
        import karesansui.lib.file.k2v
        from karesansui.lib.const import KARESANSUI_GROUP
    except ImportError, e:
        print deco_msg(_("NG"),"red")
        raise CheckEnvError(_("ERROR: There are not enough libraries. - %s") % ''.join(e.args))
    print deco_msg(_("OK"),"green")

    """ Check whether Karesansui group exists or not. """
    print _("Checking whether Karesansui group exists or not... "),
    try:
        expected_gid = grp.getgrnam(KARESANSUI_GROUP)[2]
    except:
        print deco_msg(_("NG"),"red")
        raise CheckEnvError(_("ERROR: %s group does not exist.") % KARESANSUI_GROUP)
    print deco_msg(_("OK"),"green")

    """ Check if Karesansui configuration file can be loaded. """
    print _("Checking if Karesansui configuration file can be loaded... "),
    karesansui.config = karesansui.lib.file.k2v.K2V(os.path.abspath(opts.config)).read()
    if not karesansui.config:
        print deco_msg(_("NG"),"red")
        raise CheckEnvError(_("ERROR: Failed to load configuration file. - %s") % opts.config)
    print deco_msg(_("OK"),"green")

    """ Check if sqlalchemy modules can be imported. """
    print _("Checking if sqlalchemy modules can be imported... "),
    try:
        import sqlalchemy
    except ImportError, e:
        print deco_msg(_("NG"),"red")
        raise CheckEnvError(_("ERROR: There are not enough libraries. - %s") % ''.join(e.args))
    print deco_msg(_("OK"),"green")

    """ Check if pysilhouette modules can be imported. """
    print _("Checking if pysilhouette modules can be imported... "),
    try:
        import pysilhouette
    except ImportError, e:
        print deco_msg(_("NG"),"red")
        raise CheckEnvError(_("ERROR: There are not enough libraries. - %s") % ''.join(e.args))
    print deco_msg(_("OK"),"green")

    karesansui_database_url = "mysql://scott:tiger@localhost/test?charset=utf8&use_unicode=0"
    karesansui_database_url = karesansui.config['database.bind']
    pysilhouette_config_file = karesansui.config['pysilhouette.conf.path']

    """ Check if pysilhouette config parameters are enough. """
    print _("Checking if pysilhouette config parameters are enough... "),
    require_params = ["database.url",
                      "observer.mkfifo.path",
                     ]
    for param in require_params:
        try:
            sh_config_read(pysilhouette_config_file)[param]
        except:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: parameter '%s' is not found in %s.") % (param,pysilhouette_config_file,))
    print deco_msg(_("OK"),"green")
    pysilhouette_database_url = sh_config_read(pysilhouette_config_file)["database.url"]

    """ Check if pysilhouette configuration file can be loaded. """
    print _("Checking if pysilhouette configuration file can be loaded... "),
    from pysilhouette.prep import readconf
    karesansui.sheconf = readconf(pysilhouette_config_file)
    if karesansui.sheconf is None:
        print deco_msg(_("NG"),"red")
        raise CheckEnvError(_("ERROR: Failed to load configuration file. - %s") % pysilhouette_config_file)
    print deco_msg(_("OK"),"green")

    """ Check if Database API modules can be imported. """
    import installer.database
    database_urls = {
                     "Karesansui"  :karesansui_database_url,
                     "pysilhouette":pysilhouette_database_url,
                    }
    for k,v in database_urls.iteritems():
        print _("Checking if Database API modules for %s can be imported... ") % k,
        try:
            dbtype, value = v.split(':',1)
            installer.database.import_database_module(dbtype)
        except CheckEnvError, e:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: %s") % e.value)
        print deco_msg("%s" % dbtype,"bold")
	#print deco_msg(_("OK"),"green")

        """ Check whether we are able to connect to database. """
        print _("Checking whether we are able to connect to database for %s... ") % k,
        try:
            installer.database.is_connect(v)
        except Exception, e:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: %s") % e.value)
        print deco_msg("%s" % v,"bold")
	#print deco_msg(_("OK"),"green")

        """ Check permission of SQLite database. """
        if v[0:11] == "sqlite:////":
            print _("Checking permission of SQLite database for %s... ") % k,
            sqlitedb_file = v[10:]
            sqlitedb_dir = os.path.dirname(sqlitedb_file)
            for apath in [sqlitedb_file,sqlitedb_dir]:
                if os.path.exists(apath):
                    s = os.stat(apath)
                    gid = s.st_gid
                    mode = stat.S_IMODE(s.st_mode)
                    RW_GRP = stat.S_IRGRP | stat.S_IWGRP

                    if gid != expected_gid:
                        print deco_msg(_("NG"),"red")
                        raise CheckEnvError(_("ERROR: %s has invalid group ownership.\nPlease execute 'chgrp %s %s'.") % (apath,KARESANSUI_GROUP,apath))
                    elif (mode & RW_GRP) != RW_GRP:
                        print deco_msg(_("NG"),"red")
                        raise CheckEnvError(_("ERROR: %s is not writable by %s group.\nPlease execute 'chmod g+rw %s'.") % (apath,KARESANSUI_GROUP,apath))
                else:
                    print deco_msg(_("NG"),"red")
                    raise CheckEnvError(_("ERROR: %s is not found") % apath)
	    print deco_msg(_("OK"),"green")

    """ Check permission of Karesansui files/directories. """
    print _("Checking permission of Karesansui files/directories... "),
    paths = [
                  VENDOR_DATADIR + "/libvirt/",
                  VENDOR_DATADIR + "/libvirt/boot/",
                  VENDOR_DATADIR + "/libvirt/disk/",
                  VENDOR_DATADIR + "/libvirt/images/",
                  VENDOR_DATADIR + "/libvirt/snapshot/",
                  KARESANSUI_SYSCONFDIR,
                  VENDOR_SYSCONFDIR + "/xen/",
                  VENDOR_SYSCONFDIR + "/xen/xml/",
                  KARESANSUI_PREFIX + "/tmp/",
                  KARESANSUI_PREFIX + "/bin/",
                  KARESANSUI_PYTHONPATH + "/karesansui/static/",
                  "/var/log/karesansui/",
                  opts.config,
                  ]
    for apath in paths:
        if os.path.exists(apath):
            s = os.stat(apath)
            gid = s.st_gid
            mode = stat.S_IMODE(s.st_mode)
            RW_GRP = stat.S_IRGRP | stat.S_IWGRP

            if gid != expected_gid:
                print deco_msg(_("NG"),"red")
                raise CheckEnvError(_("ERROR: %s has invalid group ownership.\nPlease execute 'chgrp %s %s'.") % (apath,KARESANSUI_GROUP,apath))
            elif (mode & RW_GRP) != RW_GRP:
                print deco_msg(_("NG"),"red")
                raise CheckEnvError(_("ERROR: %s is not writable by %s group.\nPlease execute 'chmod g+rw %s'.") % (apath,KARESANSUI_GROUP,apath))
        else:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: %s is not found") % apath)
    print deco_msg(_("OK"),"green")

    """ Check permission of Xend files/directories. """
    print _("Checking permission of Xend files/directories... "),
    paths = [
                  "/proc/xen/privcmd",
                  "/var/lib/xend/",
                  "/var/run/xenstored/",
                  ]
    for apath in paths:
        if os.path.exists(apath):
            s = os.stat(apath)
            gid = s.st_gid
            mode = stat.S_IMODE(s.st_mode)
            RW_GRP = stat.S_IRGRP | stat.S_IWGRP

            if gid != expected_gid or (mode & RW_GRP) != RW_GRP:
                print deco_msg(_("NG"),"red")
                raise CheckEnvError(_("ERROR: Can't access xend by %s group.\nPlease execute '/etc/init.d/hde-libvirtd restart'.") % KARESANSUI_GROUP)
        else:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: Not running xend.\nPlease execute '/etc/init.d/xend start; /etc/init.d/hde-libvirtd restart'."))
            raise CheckEnvError(_("ERROR: %s is not found") % apath)
    print deco_msg(_("OK"),"green")

    """ Check if Karesansui services are running. """
    print _("Checking if Karesansui services are running... "),
    services = {
               "hde-libvirt" :"/opt/hde/sbin/libvirtd",
               "hde-lighttpd":"/opt/hde/sbin/lighttpd",
               "silhouetted" :"/usr/bin/python /opt/pysilhouette/bin/silhouette.py",
               }

    (ret,res) = execute_command(["/bin/ps","-eo","cmd"])

    for k,v in services.iteritems():
        flag = False
        for c_proc in res:
            if c_proc[0:len(v)] == v:
                flag = True
                break
        if flag is False:
            print deco_msg(_("NG"),"red")
            raise CheckEnvError(_("ERROR: Not running %s.\nPlease execute '/etc/init.d/%s start'.") % (v,k))
    print deco_msg(_("OK"),"green")


    print ""
    print deco_msg(_("Everything is gonna be alright!!"),"bold")
    print ""
    from installer.utils import get_kss_url
    print deco_msg(_("You can now login through following url.\n%s"),"blue|bold") % (" " + "\n ".join(get_kss_url()))

