#!/usr/bin/python
# @package      hubzero-vncproxyd-ws
# @file         hzvncproxyd-ws-config
# @author       Nicholas J. Kisseberth <nkissebe@purdue.edu>
# @copyright    Copyright (c) 2014-2015 HUBzero Foundation, LLC.
# @license      http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
#
# Copyright (c) 2014-2015 HUBzero Foundation, LLC.
#
# This file is part of: The HUBzero(R) Platform for Scientific Collaboration
#
# The HUBzero(R) Platform for Scientific Collaboration (HUBzero) is free
# software: you can redistribute it and/or modify it under the terms of
# the GNU Lesser General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# HUBzero 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# HUBzero is a registered trademark of HUBzero Foundation, LLC.
#

import re, glob, string, ConfigParser, sys, MySQLdb, time, warnings, argparse, os, pwd, grp, subprocess

debug = False

os.umask(0027)

def configureVncproxyd_ws(args):

    uid = os.geteuid()

    if uid != 0:            
        print 'hzvncproxyd-ws-config configure: must be run with root privileges'
        return 1

    print args

    if args.enable:
        return enableVncproxyd_ws(args)
    else:
        return disableVncproxyd_ws()


def enableVncproxyd_ws(args):

    print "Configuring hubzero-vncproxyd-ws"

    try:
        grp.getgrnam('hzvncproxy')
    except KeyError:
        print 'Creating hzvncproxy group'

        adduser = ["/usr/sbin/groupadd", "--system", "hzvncproxy"]

        try:
            proc = subprocess.Popen(adduser, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    
            procStdOut, procStdErr = proc.communicate()

            rc = proc.returncode

        except Exception, ex:   
            print ex
            raise
            #raise Exception('exShellCommand error ' + str(argArray) + ' ' + str(ex) + "\n" + traceback.format_exc())

        if rc != 0:
            print procStdOut
            print procStdErr
            return 1

    try:
        pwd.getpwnam('hzvncproxy')
    except KeyError:
        print 'Creating hzvncproxy user'

        adduser = ["/usr/sbin/useradd", "--system", "--home-dir" , "/var/lib/hzvncproxy", "--gid", "hzvncproxy", "--shell", "/bin/false", "--comment", "HUBzero VNC Proxy Service", "hzvncproxy"]

        try:
            proc = subprocess.Popen(adduser, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    
            procStdOut, procStdErr = proc.communicate()

            rc = proc.returncode

        except Exception, ex:   
            print ex
            raise
            #raise Exception('exShellCommand error ' + str(argArray) + ' ' + str(ex) + "\n" + traceback.format_exc())

        if rc != 0:
            print procStdOut
            print procStdErr
            return 1

    try:
        h_uid = pwd.getpwnam('hzvncproxy').pw_uid
        h_gid = grp.getgrnam('hzvncproxy').gr_gid

        if not os.path.exists('/var/lib/hzvncproxy'):
            os.mkdir('/var/lib/hzvncproxy',0750)
        if not os.path.exists('/etc/hzvncproxyd-ws'):
            os.mkdir('/etc/hzvncproxyd-ws',0750)
        if not os.path.exists('/etc/hzvncproxyd-ws/targets'):
            os.mkdir('/etc/hzvncproxyd-ws/targets',0750)
        if not os.path.exists('/var/log/hzvncproxyd-ws'):
            os.mkdir('/var/log/hzvncproxyd-ws',0750)
        if not os.path.exists('/var/log/hzvncproxyd-ws/daily'):
            os.mkdir('/var/log/hzvncproxyd-ws/daily',0750)

        os.chown('/var/lib/hzvncproxy', h_uid, h_gid)
        os.chown('/etc/hzvncproxyd-ws', h_uid, h_gid)
        os.chown('/etc/hzvncproxyd-ws/targets', h_uid, h_gid)
        os.chown('/var/log/hzvncproxyd-ws', h_uid, h_gid)
        os.chown('/var/log/hzvncproxyd-ws/daily', h_uid, h_gid)

    except Exception as e:
        print "Unable to configure required directories"
        print e
        if debug:
            raise
        return 1

    # read default.conf file
    #   remove comment lines
    #   remove blank lines
    #   if anything left leave it alone
    #   otherwise:
    #       append blank line
    #       append "# autoconfig: DO NOT MODIFY BELOW THIS LINE"
    #       attempt to autoconfig

    filename = '/etc/hzvncproxyd-ws/targets/default.conf'

    print "Autoconfiguring %s " % (filename)

    try:
        if not os.path.exists(filename):
            mode = 'w'
        else:
            mode = 'r+'

        with open(filename, mode) as f:
            ftxt = f.read()

            (txt, count) = re.subn(r'^(?:[\t ]*(?:\r?\n|\r))+' ,'',ftxt)
            (txt, count) = re.subn(r'^\s*#',r'',txt)

            if len(txt) == 0:

                hzconfig = ConfigParser.ConfigParser()

                if hzconfig.read('/etc/hubzero.conf') == []:
                    print "Unable to continue, failed to read /etc/hubzero.conf."
                    return 1

                if hzconfig.has_option('DEFAULT','site'):
                    site = hzconfig.get('DEFAULT','site')
                else:
                    print "Unable to continue, failed to find default hub site in /etc/hubzero.conf"
                    return 2

                if hzconfig.has_option(site,'documentroot'):
                    document_root = hzconfig.get(site,'documentroot')
                else:
                    print "Unable to continue, no document root set for default site in /etc/hubzero.conf"
                    return 3

                data = { 'cmsconfig' : {} }

                try:
                    for m in re.finditer("\s*(?:var|public)\s+\$(\w+)\s*=\s*\'*(.*?)\'*\s*\;\s*", open(document_root + '/configuration.php','r').read()):
                        data['cmsconfig'][m.group(1)] = m.group(2).strip(" \'\"\t")
                except Exception as e:
                    print "Unable to continue, failed to read '" +  document_root + "/configuration.php'"
                    return 4

                if 'db' not in data['cmsconfig'] or 'user' not in data['cmsconfig'] or 'password' not in data['cmsconfig']:
                    print "Unable to continue, missing configuration in  '" +  document_root + "/configuration.php'"
                    return 5

                if data['cmsconfig']['db'] == '' or data['cmsconfig']['user']  == '' or data['cmsconfig']['password'] == '':
                    print "Unable to continue, invalid configuration in  '" +  document_root + "/configuration.php'"
                    return 6

                f.seek(0)
                f.write(ftxt)
                #f.write("\n# autoconfig: DO NOT MODIFY BELOW THIS LINE")
                f.write("*:%s:mysql:host=%s;user=%s;password=%s;db=%s\n") % (site, data['cmsconfig']['host'], data['cmsconfig']['user'], data['cmsconfig']['password'], data['cmsconfig']['db'])

                # @TODO: password needs ';' escaped

                f.truncate()
                print "%s autoconfiguration complete." % (filename)
            else:
                print "%s was already configured." % (filename)

    except Exception as e:
            print "Unable to autoconfigure %s" % (filename)
            print e
            if debug:
                raise
            return 1
         

    filename = '/etc/default/hzvncproxyd-ws'

    print "Configuring %s " % (filename)

    try:

        if not os.path.exists(filename):
            mode = 'w+'
        else:
            mode = 'r+'

        with open(filename, mode) as f:
            ftxt = f.read()
            txt = ftxt.split("\n")

            if args.sslcert == '':
                if os.path.exists('/etc/hzvncproxys-ws/ssl-cert-hzvncproxyd-ws.pem'):
                    sslcert = ''
                elif os.path.exists('/etc/ssl/certs/ssl-cert-server.pem'):
                    sslcert = "SSL_CERTFILE=/etc/ssl/certs/ssl-cert-server.pem"
                elif os.path.exists('/etc/ssl/certs/ssl-cert-server.crt'):
                    sslcert = "SSL_CERTFILE=/etc/ssl/certs/ssl-cert-server.crt"
                elif os.path.exists('/etc/ssl/certs/server.pem'):
                    sslcert = "SSL_CERTFILE=/etc/ssl/certs/server.pem"
                elif os.path.exists('/etc/ssl/certs/server.crt'):
                    sslcert = "SSL_CERTFILE=/etc/ssl/certs/server.crt"
                elif os.path.exists('/etc/apache2/ssl/ssl-cert-server.pem'):
                    sslcert = "SSL_CERTFILE=/etc/apache2/ssl/ssl-cert-server.pem"
                elif os.path.exists('/etc/apache2/ssl/ssl-cert-server.crt'):
                    sslcert = "SSL_CERTFILE=/etc/apache2/ssl/ssl-cert-server.crt"
                elif os.path.exists('/etc/apache2/ssl/server.pem'):
                    sslcert = "SSL_CERTFILE=/etc/apache2/ssl/server.pem"
                elif os.path.exists('/etc/apache2/ssl/server.crt'):
                    sslcert = "SSL_CERTFILE=/etc/apache2/ssl/server.crt"
                else:
                    sslcert = ''
            elif args.sslcert == False:
                sslcert = ''
            else:
                sslcert = "SSL_CERTFILE=" + args.sslcert

            if args.sslkey == '':
                if os.path.exists('/etc/hzvncproxys-ws/ssl-cert-hzvncproxyd-ws.key'):
                    sslkey = ''
                elif os.path.exists('/etc/ssl/certs/ssl-cert-server.key'):
                    sslkey = "SSL_KEYFILE=/etc/ssl/certs/ssl-cert-server.key"
                elif os.path.exists('/etc/ssl/certs/server.key'):
                    sslkey = "SSL_KEYFILE=/etc/ssl/certs/server.key"
                elif os.path.exists('/etc/apache2/ssl/ssl-cert-server.key'):
                    sslkey = "SSL_KEYFILE=/etc/apache2/ssl/ssl-cert-server.key"
                elif os.path.exists('/etc/apache2/ssl/server.key'):
                    sslkey = "SSL_KEYFILE=/etc/apache2/ssl/server.pem"
                else:
                    sslkey = ''
            elif args.sslkey == False:
                sslkey = ''
            else:
                sslkey = "SSL_KEYFILE=" + args.sslcert

            if args.listen == None:
                listen = None
            elif args.listen == False:
                listen = '';
            else:
                listen = "LISTEN=%s" % (listen)

            last_listen = -1
            last_certfile = -1
            last_keyfile = -1

            for i in range(0,len(txt)):
                if re.match(r'^SSL_CERTFILE\s*=\s*(.*)$',txt[i]):
                    last_certfile = i
                if re.match(r'^SSL_KEYFILE\s*=\s*(.*)$',txt[i]):
                    last_keyfile = i
                if re.match(r'^LISTEN\s*=\s*(.*)$',txt[i]):
                    last_listen = i

            #print "last_certfile = %d" % last_certfile
            #print "last_keyfile = %d" % last_keyfile
            #print "last_listen = %d" % last_listen
            #print "last line= [%s]" % txt[len(txt)-1]

            if txt[len(txt)-1] <> "":
                txt.append("")

            if sslcert <> None and sslcert <> '':
                if last_certfile > -1:
                    txt[last_certfile] = sslcert
                else:
                    txt.append(sslcert)

            if sslkey <> None and sslkey <> '':
                if last_keyfile > -1:
                    txt[last_keyfile] = sslkey
                else:
                    txt.append(sslkey)

            if listen <> None and listen <> '':
                if last_listen > -1:
                    txt[last_listen] = listen
                else:
                    txt.append(listen)

            txt = '\n'.join(txt)

            if sslcert == '':
                txt = re.sub(r'(?im)^SSL_CERTFILE\s*=\s*(.*)(\n|$)','',txt)
            if sslkey == '':
                txt = re.sub(r'(?im)^SSL_KEYFILE\s*=\s*(.*)(\n|$)','',txt)
            if listen == '':
                txt = re.sub(r'(?im)^LISTEN\s*=\s*(.*)(\n|$)','',txt)

            #print "============"
            #print txt,
            #print "============"

            if txt == ftxt:
                print "%s was already configured." % (filename)
            else:
                f.seek(0)
                f.write(txt)
                f.truncate()
                print "%s configuration complete." % (filename)

    except Exception as e:
            print "Unable to configure %s" % (filename)
            print e
            if debug:
                raise
            return 1


def disableVncproxyd_ws():
    print "Unconfiguring hubzero-vncproxyd-ws"

    filename = '/etc/default/hzvncproxyd-ws'

    print "Configuring %s " % (filename)

    try:

        if not os.path.exists(filename):
            mode = 'w+'
        else:
            mode = 'r+'

        with open(filename, mode) as f:
            ftxt = f.read()
            txt = ftxt.split("\n")

            if args.enable == None:
                enabled = None
            elif args.listen == False:
                enabled = '';
            else:
                enabled = "ENABLED=0"

            last_enable = -1

            for i in range(0,len(txt)):
                if re.match(r'^ENABLED\s*=\s*(.*)$',txt[i]):
                    last_enabled = i

            print "last_enabled = %d" % last_enabled
            print "last line= [%s]" % txt[len(txt)-1]

            if txt[len(txt)-1] <> "":
                txt.append("")

            if enabled <> None and enabled <> '':
                if last_enabled > -1:
                    txt[last_enabled] = enabled
                else:
                    txt.append(enabled)

            txt = '\n'.join(txt)

            if enabled == '':
                txt = re.sub(r'(?im)^ENABLED\s*=\s*(.*)(\n|$)','',txt)

            #print "============"
            #print txt,
            #print "============"

            if txt == ftxt:
                print "%s was already configured disabled." % (filename)
            else:
                f.seek(0)
                f.write(txt)
                f.truncate()
                print "%s configuration complete (disabled)." % (filename)

    except Exception as e:
            print "Unable to disable package through configuration file %s " % (filename)
            print e
            if debug:
                raise
            return 1

    return 0


parser = argparse.ArgumentParser(prog="hzvncproxyd-ws-config")
parser.add_argument('--debug', dest='debug', action='store_true', help='enable debugging output', default=False)

subparsers = parser.add_subparsers()

parser_configure = subparsers.add_parser('configure', help='configure hubzero-vncproxyd-ws package')
parser_configure.set_defaults(func=configureVncproxyd_ws)
action = parser_configure.add_mutually_exclusive_group(required=True)
action.add_argument('--enable', dest='enable', action='store_true', help='enable hubzero-vncproxyd-ws',default=True)
action.add_argument('--disable', dest='enable', action='store_false', help='disable hubzero-vncproxyd-ws configuration',default=False)
parser_configure.add_argument('--listen', dest='listen', action='store', help='host:port to lisent on',default=None)
parser_configure.add_argument('--ssl-cert', dest='sslcert', action='store', help='SSL Certificate File',nargs='?',const='')
parser_configure.add_argument('--ssl-key', dest='sslkey', action='store', help='SSL Certificate Key',nargs='?',const='')
parser_configure.add_argument('--no-ssl-key', dest='sslkey', action='store_false', help='SSL Certificate Key')
parser_configure.add_argument('--no-ssl-cert', dest='sslcert', action='store_false', help='SSL Certificate Key')
args =  parser.parse_args()

debug = args.debug

ret = args.func(args)

sys.exit(ret)
