#!/usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
try:
    import os, sys, re
    from optparse import Option, OptionParser
    from hawqpylib.hawqlib import HawqXMLParser, parse_hosts_file, remove_property_xml, update_xml_property, local_ssh
    from gppylib.commands.unix import getLocalHostname, getUserName
    from gppylib.db import dbconn
    from pygresql.pg import DatabaseError
    from gppylib.gplog import setup_hawq_tool_logging, quiet_stdout_logging, enable_verbose_logging
    from gppylib.gpsqlUtil import GpsqlUtil
except ImportError, e:
    sys.exit('ERROR: Cannot import modules.  Please check that you '
                 'have sourced greenplum_path.sh.  Detail: ' + str(e))

logger, log_filename = setup_hawq_tool_logging('hawq_config',getLocalHostname(),getUserName())

def parseargs():
    parser = OptionParser(usage="HAWQ config options.")
    parser.add_option('-c', '--change', type='string',
                      help="Change HAWQ Property.")
    parser.add_option('-r', '--remove', type='string',
                      help="Remove HAWQ Property.")
    parser.add_option('-s', '--show', type='string',
                      help="Change HAWQ Property name.")
    parser.add_option('-l', '--list', action='store_true',
                      help="List all HAWQ Properties.")
    parser.add_option('--skipvalidation', action='store_true', default=False)
    parser.add_option('--ignore-bad-hosts', action='store_true', default=False,
                      help='Skips copying configuration files on host on which SSH fails')
    parser.add_option('-q', '--quiet', action='store_true', default=False)
    parser.add_option("-v", "--value",
                      dest="property_value",
                      help="Set HAWQ Property value.")
    (options, args) = parser.parse_args()

    if options.quiet:
        quiet_stdout_logging()

    if options.change and options.remove:
        logger.error("Multiple actions specified.  See the --help info.")
        parser.exit()

    if options.change and not options.property_value:
        logger.error("change requested but value not specified")
        parser.exit()

    if options.show and options.list:
        logger.error("Multiple actions specified.  See the --help info.")
        parser.exit()

    if options.show and (options.change or options.remove):
        logger.error("Multiple actions specified.  See the --help info.")
        parser.exit()

    if options.list and (options.change or options.remove):
        logger.error("Multiple actions specified.  See the --help info.")
        parser.exit()

    if (options.show or options.list) and options.skipvalidation:
        logger.error("--skipvalidation can not be combined with --show/--list.")
        parser.exit()

    return (options, args)


def check_property(hawq_site, property_name, property_value):
    if property_name in hawq_site.hawq_dict:
        print "GUC %s already exist in hawq-site.xml" % property_name
        print "Update it with value: %s" % property_value
        item_exist = True
    else:
        print "GUC %s does not exist in hawq-site.xml" % property_name
        print "Try to add it with value: %s" % property_value
        item_exist = False
    return item_exist


def check_property_valid(hawq_site, property_name = 'None'):
    try:
        dburl = dbconn.DbURL(port=hawq_site.hawq_dict['hawq_master_address_port'], dbname='template1')
        conn = dbconn.connect(dburl, True)
        query = "select name, setting from pg_settings where name='%s';" % property_name
        rows = dbconn.execSQL(conn, query)
        conn.close()
    except DatabaseError, ex:
        print "Failed to connect to database, this script can only be run when the database is up"
        sys.exit(1)

    if rows.rowcount == 0:
        print "This GUC name is not valid, use --skipvalidation to do force update"
        sys.exit(1)


def list_properties(hawq_site):
    property_name = 'None'
    property_value = 'None'
    try:
        dburl = dbconn.DbURL(port=hawq_site.hawq_dict['hawq_master_address_port'], dbname='template1')
        conn = dbconn.connect(dburl, True)
        query = "select name, setting from pg_settings;"
        rows = dbconn.execSQL(conn, query)
        conn.close()
    except DatabaseError, ex:
        print "Failed to connect to database, this script can only be run when the database is up"
        sys.exit(1)
    for row in rows:
        property_name = row[0]
        property_value = row[1] 
        print "GUC\t\t: %s" % property_name
        print "Value\t\t: %s\n" % property_value

    return property_name, property_value


def show_guc(hawq_site, property_name):
    property_value = 'None'
    try:
        query = "show %s;" % property_name

        _sqlUtil = GpsqlUtil()
        rows = _sqlUtil.performQuery(query)

        if rows:
            for row in rows:
                property_value = row[property_name]
        else:
            print("No such GUC exist")
            sys.exit(1)

        print("GUC\t\t: %s" % property_name)
        print("Value\t\t: %s" % property_value)
        return None
    except DatabaseError, ex:
        if re.search("unrecognized configuration parameter", ex.__str__()):
            print "Failed to retrieve GUC information, guc %s does not exist" % property_name
        elif re.search("could not connect to server", ex.__str__()):
            print "Failed to retrieve GUC information, the database is not accesible"
        else:
            print "Failed to retrieve GUC information: %s" % ex.__str__()
        sys.exit(1)


def show_property(hawq_site, property_name):
    if property_name in hawq_site.hawq_dict:
        print "GUC\t\t: %s" % property_name
        print "Value\t\t: %s" % hawq_site.hawq_dict[property_name]
    else:
        print "Failed to retrieve GUC information, guc '%s' does not exist in hawq-site.xml" % property_name
    return None


def update_hawq_site(org_config_file, hawq_site, property_name, property_value):
    result = check_property(hawq_site, property_name, property_value)
    update_xml_property(org_config_file, property_name, property_value)


def sync_hawq_site(config_dir, host_list, ignore_bad_hosts):
    sync_host_str = ""
    for node in host_list:
        sync_host_str += " -h %s" % node
    result = local_ssh("hawq scp %s %s %s/etc/hawq-site.xml =:%s/etc/" % (sync_host_str, ignore_bad_hosts, config_dir, config_dir), logger)
    if result != 0:
        sys.exit("sync hawq-site.xml failed.")

if __name__ == '__main__':
    options, args = parseargs()

    GPHOME = os.getenv('GPHOME')
    if not GPHOME:
        sys.exit("GPHOME environment variable not set, exit")
    hawq_site = HawqXMLParser(GPHOME)
    hawq_site.get_all_values()
    org_config_file = "%s/etc/hawq-site.xml" % GPHOME
    segment_list = parse_hosts_file(GPHOME)
    master_host = hawq_site.hawq_dict['hawq_master_address_host']
    host_list = segment_list + [master_host]
    ignore_bad_hosts = '--ignore-bad-hosts' if options.ignore_bad_hosts else ''
    if 'hawq_standby_address_host' in hawq_site.hawq_dict:
        standby_host = hawq_site.hawq_dict['hawq_standby_address_host']
        if standby_host not in ('None', 'none', ''):
            host_list = host_list + [standby_host]

    # Update hawq-site.xml
    if options.change:
        if not options.property_value:
            print "Please specify GUC value"
            sys.exit(1)
        if not options.skipvalidation:
            check_property_valid(hawq_site, options.change)

        update_hawq_site(org_config_file, hawq_site, options.change, options.property_value)
        sync_hawq_site(GPHOME, host_list, ignore_bad_hosts)

        if not options.quiet:
            latest_hawq_site = HawqXMLParser(GPHOME)
            latest_hawq_site.get_all_values()
            show_property(latest_hawq_site, options.change)
    elif options.show:
        latest_hawq_site = HawqXMLParser(GPHOME)
        latest_hawq_site.get_all_values()
        show_guc(latest_hawq_site, options.show)
    elif options.list:
        latest_hawq_site = HawqXMLParser(GPHOME)
        latest_hawq_site.get_all_values()
        list_properties(latest_hawq_site)
    elif options.remove:
        except_list = ['hawq_master_address_host', 'hawq_master_directory', 'hawq_segment_directory']
        if options.remove in except_list:
            print "Remove %s is not allowed" % options.remove
            sys.exit(1)
        remove_property_xml(options.remove, org_config_file, options.quiet)
        sync_hawq_site(GPHOME, host_list, ignore_bad_hosts)
    else:
        print "Please input correct options"
        sys.exit(1)
