#!/opt/alt/python27/bin/python2.7

#
# Copyright CloudLinux Zug GmbH 2010-2013 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENCE.TXT
#

import datetime
import getopt
import socket
import sys

from clcommon.utils import is_root_or_exit
is_root_or_exit()

import cldetectlib as detect
import cllicenselib as license

from cldiaglib import (
    runner,
    fake_cagefs_checker,
    check_cp_diag,
    check_symlinksifowner,
    check_suexec,
    check_suphp,
    check_use_pam,
    check_symlinkowngid,
    check_existance_of_all_users_packages,
    check_phpselector,
    check_php_conf,
    check_defaults_cfg,
)

CAGEFS_SOURCES = '/usr/share/cagefs'
cagefs_installed = detect.is_cagefs_installed()


EMAIL_TPL = """\
Subject: Your CloudLinux Installation has issues: [{host}] - {date}
From: noreply@cloudlinux.com
To: {to}
<html>
<head></head>
<body>
<center><h4>We have detected following issues with your system:</h4></center>
<pre>
{content}
</pre>
</body>
</html>
"""


# Show help
def print_usage():
    print '-h | --help                              show this message'
    print '--json                                   print output as json'
    print '-a | --all                               prints all diag'
    print "     --diag-cp                           prints control panel and it's version (CP_NAME, CP_VERSION)"
    print '     --symlinksifowner                   prints fs.enforce_symlinksifowner from sysctl conf'
    print '     --check-suexec                      prints warning if suexec binary without CageFS'
    print '     --check-suphp                       prints warning if suphp binary without CageFS'
    print '     --check-usepam                      prints warnings if SSHd UsePAM from /etc/ssh/sshd_config'
    print '     --check-phpselector                 prints warnings if current PHP engine is not supported by CloudLinux PHP Selector'
    print "     --check-cagefs                      runs same checks as cagefsctl --sanity-check and print it's result"
    print "     --check-symlinkowngid               prints warning if Apache user is not protected with fs.enforce_symlinksifowner"
    print '     --check-cpanel-packages             print packages from /var/cpanel/users that do not exist in /var/cpanel/packages'
    print '     --check-php-conf                    print warnings if /etc/cl.selector/php.conf has wrong format'
    print '     --check-defaults-cfg                print warnings if /etc/cl.selector/defaults.cfg has wrong format'
    print '     --generate-email                    will run most of the checks, generate HTML report and send it via email to admin'
    print '     --cron-check                        For cPnanel only. Do the same as --generate-email but taking into account /etc/sysconfig/cloudlinux ENABLE_CLDIAG setting'
    print ''


def check_all_and_send_email():
    if not detect.is_cpanel():
        return
    ENABLE_CLDIAG = detect.get_param_from_file('/etc/sysconfig/cloudlinux',
                                               'ENABLE_CLDIAG', '=')
    if ENABLE_CLDIAG.lower() not in ('1', 'on', 'true'):
        return
    checkers = prepare_checkers()
    e, o = runner(checkers, do_exit=False)
    if e:
        license.send_email(generate_email(o))


def generate_email(all_output_list):
    return EMAIL_TPL.format(host=socket.gethostname(),
                            date=datetime.date.today(),
                            to=detect.getCPAdminEmail(),
                            content=''.join(all_output_list))


def prepare_checkers(scope='all'):
    # TODO we may wish to add scope "cron"
    if scope not in ('all', 'cagefs',):
        raise ValueError('Unknown checkers scope')

    all_checkers = (
        check_cp_diag,
        check_symlinksifowner,
        check_suexec,
        check_suphp,
        check_use_pam,
        check_symlinkowngid,
        check_existance_of_all_users_packages,
        check_phpselector,
        check_defaults_cfg,
        check_php_conf,
    )

    CAGEFS_CHECKERS = (fake_cagefs_checker,)

    if cagefs_installed:
        sys.path.append(CAGEFS_SOURCES)
        try:
            from sanity_check import CAGEFS_CHECKERS
        except ImportError:
            pass
        all_checkers = all_checkers + CAGEFS_CHECKERS

    if scope == 'all':
        return all_checkers
    if scope == 'cagefs' and cagefs_installed:
        return CAGEFS_CHECKERS
    return []


def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'ha', [
            'help',
            'all',
            'diag-cp',
            'symlinksifowner',
            'check-suexec',
            'check-suphp',
            'check-usepam',
            'generate-email',
            'cron-check',
            'check-cagefs',
            'check-symlinkowngid',
            'check-cpanel-packages',
            'check-phpselector',
            'json',
            'check-php-conf',
            'check-defaults-conf',
        ])

    except getopt.GetoptError:
        print 'error: unknown command'
        print_usage()
        sys.exit(1)

    executed = False
    to_json = False

    if ('--json', '') in opts:
        to_json = True

    for o, a in opts:

        if o in ('--help', '-h'):
            executed = True
            print_usage()

        elif o in ('--all', '-a'):
            executed = True
            checkers = prepare_checkers()
            runner(checkers, to_json)

        elif o in ('--diag-cp', ):
            executed = True
            runner(check_cp_diag, to_json)

        elif o in ('--symlinksifowner', ):
            executed = True
            runner(check_symlinksifowner, to_json)

        elif o in ('--check-suexec', ):
            executed = True
            runner(check_suexec, to_json)

        elif o in ('--check-suphp', ):
            executed = True
            runner(check_suphp, to_json)

        elif o in ('--check-usepam',):
            executed = True
            runner(check_use_pam, to_json)

        elif o in ('--generate-email',):
            executed = True
            checkers = prepare_checkers()
            _, o = runner(checkers, do_exit=False)
            license.send_email(generate_email(o))

        elif o in ('--check-cagefs',):
            executed = True
            if not cagefs_installed:
                print 'Cagefs is not installed. Skipping check'
                exit(0)
            checkers = prepare_checkers('cagefs')
            runner(checkers, to_json)

        elif o in ('--check-symlinkowngid',):
            executed = True
            runner(check_symlinkowngid, to_json)

        elif o in ('--cron-check',):
            executed = True
            check_all_and_send_email()

        elif o in ('--check-phpselector',):
            executed = True
            runner(check_phpselector, to_json)

        elif o in ('--check-cpanel-packages',):
            executed = True
            runner(check_existance_of_all_users_packages, to_json)

        elif o in ('--check-php-conf',):
            executed = True
            runner(check_php_conf, to_json)

        elif o in ('--check-defaults-cfg',):
            executed = True
            runner(check_defaults_cfg, to_json)

    if not executed:    # TODO looks like useless and never happens
        print 'error: argument required'
        print_usage()
        sys.exit(1)


if __name__ == "__main__":
    main()
