#!/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.
# -----------------------------------------------------------------------


import os
import sys
import getopt

import shutil
import subprocess
from  stat import *

import string
import random

from ducc_util import DuccUtil

from ducc_base import Properties
from ducc_base import Property

from ducc_base import find_ducc_home
from ducc_base import find_localhost

from ducc import Ducc

import db_util as dbu

# 
# Create and initialize the DUCC database.  In a new installation this is handled by
# ducc_post_install.  Older installations need to run db_create as one of the steps
# of migration to the DB.
#
class DbCreate(DuccUtil):

    def usage(self, msg):

        if ( msg != None ):
            print ' '.join(msg)

              
        print 'DbCreate configures the database and installs the schema.'
        print ''
        print "Usage:"
        print "   db_create [options]"
        print "        If no options defaults are used for expected parameters."
        print ""
        print "Options:"
        print "   [-d, --db-password] <root password for database>"
        print "        This is the password DUCC uses to manage the database."
        print ""
        print "   [-h, -? --help]"
        print "        Prints this message."
        print ""
        sys.exit(1) 
                                    
    def main(self, argv):                    

        self.database_pw = None

        try:
            opts, args = getopt.getopt(argv, 'd:n:h?', ['db-password=', 'help'])
        except:
            self.usage("Invalid arguments " + ' '.join(argv))


        for ( o, a ) in opts:
            if o in ('-d', '--db-password'):
                self.database_pw = a
            elif o in ('-h', '-?', '--help'):
                self.usage(None)
        
        # abort db create if db already running
        status = 'unknown'
        cmd = self.DUCC_HOME+'/cassandra-server/bin/nodetool'
        p = subprocess.Popen([cmd, 'info'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()
        if ((err != None) and (err != '')):
            if (err.startswith(self.cmd_name_nodetool+': Failed to connect')):
                status = 'down'
        elif ((out != None) and (out != '')):
            for line in out.splitlines():
                if(line.startswith('Uptime')):
                    status = 'up'
                    break
        if(status != 'down'):
            print 'unsafe to proceed, database status: '+status
            return
    
        if ( self.database_pw == None ):
            self.database_pw = self.generate_pw()

        # start with merged properties
        self.merge_properties();

        # configure the database for local system and initialize the schema
        db_node = self.ducc_properties.get("ducc.head")
        if ( dbu.configure_database(self.DUCC_HOME, db_node, self.jvm, self.database_pw)):
            private_props_name = self.DUCC_HOME + '/resources.private/ducc.private.properties'

            print 'Writing database password to', private_props_name
            ducc_site_properties = Properties();
            site_props_name = self.DUCC_HOME + '/resources/site.ducc.properties'
            ducc_site_properties.load(site_props_name)
            ducc_site_properties.put('ducc.database.host', db_node);
            ducc_site_properties.put('ducc.service.persistence.impl', 'org.apache.uima.ducc.database.StateServicesDb'   , ['# Service manager persistence'])
            ducc_site_properties.put('ducc.job.history.impl'        , 'org.apache.uima.ducc.database.HistoryManagerDb'  , ['# History and checkpoint'])
            ducc_site_properties.put('ducc.rm.persistence.impl'     , 'org.apache.uima.ducc.database.RmStatePersistence', ['# RM state persistence'])

            # if we don't die before this we need to enable db in site.ducc.properties and set the
            # db password into resources.private/ducc.private.properties
            ducc_site_properties.write(site_props_name)

            private_props_name = self.DUCC_HOME + '/resources.private/ducc.private.properties'
            private_properties = Properties()
            private_properties.load(private_props_name)
            private_properties.delete('db_password')
            private_properties.put('db_password', self.database_pw, ['#Db password, default is randomly generated']);
            private_properties.write(private_props_name)

        # remerge to insure it's all correct and ready to go
        self.merge_properties();
    
    # generate a random string between 8 and 16 characters long
    def generate_pw(self):
        pwlen = random.randrange(8,16)
        reply = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(pwlen)])
        return reply
        
if __name__ == "__main__":

    postinstall = DbCreate()
    postinstall.main(sys.argv[1:])
