#!/usr/bin/python2
#
# Copyright (c) 2013-2014 Rafael Martinez Guerrero / PostgreSQL-es
# rafael@postgresql.org.es / http://www.postgresql.org.es/
#
# Copyright (c) 2014 USIT-University of Oslo
#
# This file is part of PgBackman
# https://github.com/rafaelma/pgbackman
#
# PgBackMan 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 3 of the License, or
# (at your option) any later version.
#
# PgBackMan 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PgBck.  If not, see <http://www.gnu.org/licenses/>.

import subprocess
import tempfile
import datetime
import sys
import os
import time
import signal
import argparse

from pgbackman.logs import *
from pgbackman.database import * 
from pgbackman.config import *

'''
This program is used by PgBackMan to restore backups from the pgbackman catalog.
'''

global_parameters = {}
backup_server_cache_data = {}
pgsql_node_cache_data = {}


# ############################################
# Function restore_roles()
# ############################################

def restore_roles(db):
    '''Restore roles'''

    global global_parameters

    try:
        pg_restore_roles_temp_file = tempfile.NamedTemporaryFile(delete=True,dir=global_parameters['tmp_dir'])
        logs.logger.debug('Restore roles temp file created %s',pg_restore_roles_temp_file.name)
        
        with open(global_parameters['pgdump_roles_file'], 'r') as sqldump_in:
            with open(pg_restore_roles_temp_file.name, 'w') as sqldump_out:
                sqldump_out.write('BEGIN;\n')
                                
                for line in sqldump_in:
                                        
                    for role in global_parameters['role_list']:
                         
                        #
                        # CREATE ROLE statements
                        #
                        if 'CREATE ROLE ' + role + ';' in line:
                            sqldump_out.write(line)

                        #
                        # ALTER ROLE statements
                        #
                        if 'ALTER ROLE ' + role + ' ' in line:
                            sqldump_out.write(line)

                        #
                        # Role membership statements
                        #
                        if 'GRANT ' in line:
                            if ' TO ' + role + ' GRANTED BY ' in line:
                                sqldump_out.write(line)
                                
                sqldump_out.write('COMMIT;\n')
                logs.logger.debug('Role restore file generated.')
                sqldump_out.flush()

                role_restore_command = global_parameters['backup_server_pgsql_bin_dir'] + '/psql' + \
                    ' -e ' + \
                    ' -h ' + global_parameters['pgsql_node_fqdn'] + \
                    ' -p ' + global_parameters['pgsql_node_port'] + \
                    ' -U ' + global_parameters['pgsql_node_admin_user'] + \
                    ' -d template1' + \
                    ' -f ' + pg_restore_roles_temp_file.name

                with open(global_parameters['restore_log_file'],'a') as restore_log_file:
            
                    restore_log_file.write('------------------------------------\n')
                    restore_log_file.write('Timestamp:' + str(datetime.datetime.now()) + '\n')
                    restore_log_file.write('Command: ' + role_restore_command + '\n')
                    restore_log_file.write('------------------------------------\n\n')
                    
                    restore_log_file.flush()

                    proc = subprocess.Popen([role_restore_command],stdout=restore_log_file,stderr=subprocess.STDOUT,shell=True)
                    proc.wait()

                    if proc.returncode != 0:
                        logs.logger.critical('The command used to restore the roles needed by the target database has a return value != 0')
                    
                        global_parameters['execution_status'] = 'ERROR'
                        global_parameters['error_message'] = 'Roles returncode: ' + str(proc.returncode)
                        register_restore_catalog(db)
                        sys.exit(1)
        
                    else:
                        logs.logger.info('Roles for database restored.')

    except Exception as e:
        logs.logger.critical('Could not restore the roles needed by the database - %s',e)
        
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Problems restoring roles - ' + str(e)
        register_restore_catalog(db)
        sys.exit(1)
           


# ############################################
# Function restore_dbconfig()
# ############################################

def restore_dbconfig(db):
    '''Restore dbconfig'''

    global global_parameters

    try:
        pg_restore_dbconfig_temp_file = tempfile.NamedTemporaryFile(delete=True,dir=global_parameters['tmp_dir'])
        logs.logger.debug('Temp dbconfig restore file created %s',pg_restore_dbconfig_temp_file.name)
        
        with open(global_parameters['pgdump_dbconfig_file'], 'r') as sqldump_in:
            with open(pg_restore_dbconfig_temp_file.name, 'w') as sqldump_out:
                 
                for line in sqldump_in:

                    #
                    # CREATE DATABASE statements
                    #
                    if 'CREATE DATABASE ' + global_parameters['source_dbname']  in line:

                        if global_parameters['source_dbname'] == global_parameters['target_dbname']:
                            sqldump_out.write(line)
                            
                        elif global_parameters['source_dbname'] != global_parameters['target_dbname']:
                            sqldump_out.write(line.replace('CREATE DATABASE ' + global_parameters['source_dbname'],'CREATE DATABASE ' + global_parameters['target_dbname']))

                        sqldump_out.write('BEGIN;\n')

                    #
                    # GRANT / REVOKE statements
                    #
                    elif ' ON DATABASE ' + global_parameters['source_dbname']  in line:

                        if global_parameters['source_dbname'] == global_parameters['target_dbname']:
                            sqldump_out.write(line)
                            
                        elif global_parameters['source_dbname'] != global_parameters['target_dbname']:
                            sqldump_out.write(line.replace(' ON DATABASE ' + global_parameters['source_dbname'],' ON DATABASE ' + global_parameters['target_dbname']))
                        
                    #
                    # ALTER DATABASE statements
                    #
                    elif 'ALTER DATABASE ' + global_parameters['source_dbname']  in line:

                        if global_parameters['source_dbname'] == global_parameters['target_dbname']:
                            sqldump_out.write(line)
                            
                        elif global_parameters['source_dbname'] != global_parameters['target_dbname']:
                            sqldump_out.write(line.replace('ALTER DATABASE ' + global_parameters['source_dbname'],'ALTER DATABASE ' + global_parameters['target_dbname']))
                        

                sqldump_out.write('COMMIT;\n')    

                logs.logger.debug('Temp dbconfig restore file generated.')
                sqldump_out.flush()

                dbconfig_restore_command = global_parameters['backup_server_pgsql_bin_dir'] + '/psql' + \
                    ' -e ' + \
                    ' -h ' + global_parameters['pgsql_node_fqdn'] + \
                    ' -p ' + global_parameters['pgsql_node_port'] + \
                    ' -U ' + global_parameters['pgsql_node_admin_user'] + \
                    ' -d template1' + \
                    ' -f ' + pg_restore_dbconfig_temp_file.name

                with open(global_parameters['restore_log_file'],'a') as restore_log_file:
            
                    restore_log_file.write('------------------------------------\n')
                    restore_log_file.write('Timestamp:' + str(datetime.datetime.now()) + '\n')
                    restore_log_file.write('Command: ' + dbconfig_restore_command + '\n')
                    restore_log_file.write('------------------------------------\n\n')

                    restore_log_file.flush()
                
                    proc = subprocess.Popen([dbconfig_restore_command],stdout=restore_log_file,stderr=subprocess.STDOUT,shell=True)
                    proc.wait()

                    if proc.returncode != 0:
                        logs.logger.critical('The command used to restore the global database statements needed by the target database has a return value != 0')
                    
                        global_parameters['execution_status'] = 'ERROR'
                        global_parameters['error_message'] = 'DBconfig for database returncode: ' + str(proc.returncode)
                        register_restore_catalog(db)
                        sys.exit(1)
        
                    else:
                        logs.logger.info('DBconfig for database restored.')

    except Exception as e:
        logs.logger.critical('Could not restore the global database statements needed by the database - %s',e)
        
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Problems restoring DBconfig - ' + str(e)
        register_restore_catalog(db)
        sys.exit(1)
           

# ############################################
# Function restore_database()
# ############################################

def restore_database(db):
    '''Restore database'''
    
    global global_parameters

    try:
        database_restore_command = global_parameters['backup_server_pgsql_bin_dir'] + '/pg_restore' + \
            ' -v ' + \
            ' -h ' + global_parameters['pgsql_node_fqdn'] + \
            ' -p ' + global_parameters['pgsql_node_port'] + \
            ' -U ' + global_parameters['pgsql_node_admin_user'] + \
            ' -d ' + global_parameters['target_dbname'] + \
            ' ' + global_parameters['extra_restore_parameters'] + \
            ' ' + global_parameters['pgdump_file']

        with open(global_parameters['restore_log_file'],'a') as restore_log_file:
            
            restore_log_file.write('------------------------------------\n')
            restore_log_file.write('Timestamp:' + str(datetime.datetime.now()) + '\n')
            restore_log_file.write('Command: ' + database_restore_command + '\n')
            restore_log_file.write('------------------------------------\n\n')
            
            restore_log_file.flush()

            proc = subprocess.Popen([database_restore_command],stdout=restore_log_file,stderr=subprocess.STDOUT,shell=True)
            proc.wait()
                    
            if proc.returncode != 0:
                logs.logger.critical('The command used to restore the database has a return value != 0')
                
                global_parameters['execution_status'] = 'ERROR'
                global_parameters['error_message'] = 'Database restore returncode: ' + str(proc.returncode)
                register_restore_catalog(db)
                sys.exit(1)
        
            else:
                logs.logger.info('Database restored.')

    except Exception as e:
        logs.logger.critical('Could not restore the database - %s',e)
        
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Problems restoring Database - ' + str(e)
        register_restore_catalog(db)
        sys.exit(1)


# ############################################
# Function get_pgsql_node_dsn()
# ############################################
    
def get_pgsql_node_dsn():
    '''Get the DSN values needed to connect to a PgSQL node'''

    global global_parameters

    dsn_value = 'host=' + global_parameters['pgsql_node_fqdn'] + ' port=' + global_parameters['pgsql_node_port'] + ' dbname=template1 user=' + global_parameters['pgsql_node_admin_user']

    logs.logger.debug('DSN value for PgSQL node is %s',dsn_value)
    return dsn_value


# ############################################
# Function get_pgsql_node_release()
# ############################################
    
def get_pgsql_node_release(db,db_pgnode):
    '''Get the postgreSQL release version a PgSQL node is running'''
    
    pgsql_node_version = ''

    try:
        db_pgnode.pg_connect()
        pgsql_node_version = str(db_pgnode.get_server_version())[0:3]
        db_pgnode.pg_close()
    except Exception as e:
        logs.logger.critical('Problems getting the postgreSQL version running on Pgsql node - %s',e)
             
    logs.logger.debug('PgSQL node version: %s',pgsql_node_version)

    if pgsql_node_version == '905':
        pgsql_node_release = '9_5'
    elif pgsql_node_version == '904':
        pgsql_node_release = '9_4'
    elif pgsql_node_version == '903':
        pgsql_node_release = '9_3'
    elif pgsql_node_version == '902':
        pgsql_node_release = '9_2'
    elif pgsql_node_version == '901':
        pgsql_node_release = '9_1'
    elif pgsql_node_version == '900':
        pgsql_node_release = '9_0'
    else:
        pgsql_node_release = None

    if  pgsql_node_release != None:
        logs.logger.debug('PgSQL node is running postgreSQL %s',pgsql_node_release)
        return pgsql_node_release
    else:
        logs.logger.critical('Could not get the postgreSQL release for this PgSQL node')
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Problems getting pgsql release'
        register_restore_catalog(db)
        sys.exit(1)
    

# ############################################
# Function get_backup_server_pgsql_bin_dir()
# ############################################
    
def get_backup_server_pgsql_bin_dir(db):
    '''Get the directory with postgreSQL binaries to use'''

    global global_parameters

    try:
        pgsql_bin_dir = db.get_backup_server_config_value(global_parameters['backup_server_id'],'pgsql_bin_' + global_parameters['pg_release'])
        logs.logger.debug('pgsql bin directory to use: %s',pgsql_bin_dir)
        
        return pgsql_bin_dir

    except Exception as e:

        pgsql_bin_dir = backup_server_cache_data['pgsql_bin_' + global_parameters['pg_release']]
        logs.logger.debug('pgsql bin directory to use: %s',pgsql_bin_dir)
        
        return pgsql_bin_dir
        

# ##################################################
# Function get_backup_server_parameters_from_cache()
# ##################################################

def get_backup_server_parameters_from_cache(db,backup_server_fqdn):  
    '''Get backup server parameters from cache file'''

    global backup_server_cache_data
    global global_parameters

    try:
        backup_server_cache_file = global_parameters['root_backup_dir'] + '/cache_dir/backup_server_' + backup_server_fqdn + '.cache'
        
        with open(backup_server_cache_file,'r') as backup_server_cache:
            for line in backup_server_cache:
                (key, val) = line.split('::')
                backup_server_cache_data[key] = val.replace('\n','')
                
    except Exception as e:
        logs.logger.error('Could not read the cache file for the backup server: %s - %s',backup_server_fqdn,e)
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Problems getting backup server cache data'
        register_restore_catalog(db)

        sys.exit(1)


# ###############################################
# Function get_pgsql_node_parameters_from_cache()
# ###############################################

def get_pgsql_node_parameters_from_cache(db):  
    '''Get pgsql_node parameters from cache file'''

    global pgsql_node_cache_data

    try:
        pgsql_node_cache_file = global_parameters['root_backup_dir'] + '/cache_dir/pgsql_node_' + global_parameters['pgsql_node_id'] + '.cache'


        with open(pgsql_node_cache_file,'r') as pgsql_node_cache:
            for line in pgsql_node_cache:
                (key, val) = line.split('::')
                pgsql_node_cache_data[key] = val.replace('\n','')
                    
    except Exception as e:
        logs.logger.critical('Could not read the cache file for the PgSQL node - %s',e)
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Problems getting pgsql node cache data'
        register_restore_catalog(db)

        sys.exit(1)

# ###############################################
# Function rename_existing_database()
# ###############################################
def rename_existing_database(db,db_pgnode):
    '''Rename an existing database before restoring a backup'''

    try:
        db_pgnode.rename_existing_database(global_parameters['target_dbname'],global_parameters['renamed_dbname'])

    except Exception as e:
        logs.logger.critical('Could not rename the database %s to %s - %s',global_parameters['target_dbname'],global_parameters['renamed_dbname'],e)
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Problems renaming an existing database'
        register_restore_catalog(db)
        
        sys.exit(1)
        
        
# ############################################
# Function register_restore_catalog()
# ############################################
  
def register_restore_catalog(db):
    '''Update the restore catalog information in the database'''

    global global_parameters

    global_parameters['restore_stop'] = datetime.datetime.now()
    duration = global_parameters['restore_stop'] - global_parameters['restore_start']

    restore_log_file = global_parameters['restore_log_file']

    #
    # Updating database
    #

    try:
        procpid = os.getpid()
        db.register_restore_catalog(global_parameters['restore_def'],
                                    procpid,
                                    global_parameters['backup_server_id'],  
                                    global_parameters['pgsql_node_id'],
                                    global_parameters['source_dbname'],
                                    global_parameters['target_dbname'],
                                    global_parameters['renamed_dbname'],
                                    global_parameters['restore_start'],
                                    global_parameters['restore_stop'],
                                    duration,
                                    restore_log_file,
                                    global_parameters['global_log_file'],
                                    global_parameters['execution_status'],
                                    global_parameters['error_message'],
                                    global_parameters['role_list'],
                                    global_parameters['target_pgsql_node_release'].replace('_','.'),
                                    global_parameters['pg_release'].replace('_','.')
                                    )
    

        logs.logger.info('Restore job catalog for RestoreDef: %s updated in the database',str(global_parameters['restore_def']))
        
    except Exception as e:

        #
        # We create a pending log file if we can not update the
        # database.  This file will be processed by
        # pgbackman_maintenance later.
        # 

        logs.logger.warning('Problems updating the restore job catalog for RestoreDef: %s in the database - %s',str(global_parameters['restore_def']),e)

        pending_log_file = ''
        
        try:
            procpid = os.getpid()
            pending_log_file = global_parameters['backup_server_pending_registration_dir'] + '/restore_jobs_pending_log_updates_nodeid_' + str(global_parameters['pgsql_node_id']) + '_' + str(procpid) + '.log'
                
            with open(pending_log_file,'w+') as catalog_pending:
                catalog_pending.write(str(global_parameters['restore_def']) + '::' +
                                      str(procpid) + '::' +
                                      str(global_parameters['backup_server_id']) + '::' +   
                                      str(global_parameters['pgsql_node_id']) + '::' +
                                      global_parameters['source_dbname'] + '::' +
                                      global_parameters['target_dbname'] + '::' +
                                      global_parameters['renamed_dbname'] + '::' +
                                      str(global_parameters['restore_start']) + '::' +
                                      str(global_parameters['restore_stop']) + '::' +
                                      str(duration) + '::' +
                                      restore_log_file + '::' +
                                      global_parameters['global_log_file'] + '::' +
                                      global_parameters['execution_status'] + '::' +
                                      global_parameters['error_message'] + '::' +
                                      " ".join(global_parameters['role_list']) + '::' +
                                      global_parameters['target_pgsql_node_release'].replace('_','.') + '::' +
                                      global_parameters['pg_release'].replace('_','.') + '\n')
                
                logs.logger.info('Restore catalog pending log file: %s created',pending_log_file)
        
        except Exception as e:
            logs.logger.error('Could not generate the restore catalog pending log file: %s - %s',pending_log_file,e)

# ############################################
# Function get_logfile_id()
# ############################################
    
def get_logfile_id():
    '''Generate the filename used for the log files of a restore job'''
    
    global global_parameters
    timestamp = datetime.datetime.now().strftime('%Y%m%dT%H%M%S')

    logfile_id =  global_parameters['pgsql_node_backup_dir'] + '/log/' + global_parameters['target_dbname'] + '-' + global_parameters['pgsql_node_fqdn'] + '-v' + global_parameters['pg_release'] + '-restoredef' + global_parameters['restore_def'] + '.log'

    return logfile_id


# ##############################################
# Function check_pgbackman_database_connection()
# ##############################################
  
def check_pgbackman_database_connection(db):
    '''Check if we can connect to the pgbackman database'''

    try:
        db.pg_connect()
        db.pg_close()

        return True
    except Exception as e: 
        logs.logger.error('The pgbackman database is not available - %s',e)
        return False


# ###############################################
# Function check_pgsql_node_database_connection()
# ###############################################
  
def check_pgsql_node_database_connection(db_pgnode):
    '''Check if we can connect to the pgsql node database'''

    try:
        db_pgnode.pg_connect()
        db_pgnode.pg_close()

        return True
    except Exception as e: 
        logs.logger.critical('The PgSQL node is not available - %s',e)
        return False    


# ############################################
# Function Main()
# ############################################
   
def main():
    '''Main function'''
    
    global global_parameters

    conf = PgbackmanConfiguration()
    pgbackman_dsn = conf.dsn

    global_parameters['tmp_dir'] = conf.tmp_dir
    global_parameters['global_log_file'] = conf.log_file
    global_parameters['restore_start'] = datetime.datetime.now()

    global_parameters['error_message'] = ''

    global_parameters['target_pgsql_node_release'] = ''

    db = PgbackmanDB(pgbackman_dsn, 'pgbackman_restore')
 
    pgsql_node_dsn = get_pgsql_node_dsn()
    db_pgnode = PgbackmanDB(pgsql_node_dsn, 'pgbackman_restore')

    # 
    # The backup server FQDN to be used can be defined in the
    # pgbackman configuration file.  If the configuration parameter
    # 'backup_server' is not defined, the return value of
    # socket.getfqdn() will be used.
    #
    # The FQDN of the backup server will be used to find out the
    # internal pgbackman ID of the backup server
    #

    if conf.backup_server != '':
        backup_server_fqdn = conf.backup_server
    else:
        backup_server_fqdn = socket.getfqdn()

    try:
        backup_server_id = db.get_backup_server_id(backup_server_fqdn)
        logs.logger.info('Backup server: %s is registered in pgbackman',backup_server_fqdn)

    except psycopg2.Error as e:
        get_backup_server_parameters_from_cache(db,backup_server_fqdn)
        backup_server_id = backup_server_cache_data['backup_server_id']
        logs.logger.info('Backup server: %s is registered in the cache',backup_server_fqdn)

    global_parameters['backup_server_id'] = backup_server_id

    global_parameters['backup_server_pending_registration_dir'] = global_parameters['root_backup_dir'] + '/pending_updates'
    global_parameters['backup_server_cache_dir'] =  global_parameters['root_backup_dir'] + '/cache_dir'

    get_pgsql_node_parameters_from_cache(db)

    #
    # Check before starting if the PgSQL node where we are going to
    # restore the database is available.  If it is not available, stop
    # the backup job with an error
    #

    check_pgnode_db = check_pgsql_node_database_connection(db_pgnode)

    if not check_pgnode_db:
        logs.logger.critical('The PgSQL node is not available. Shutting down the restore job with RestoreID: %s',str(global_parameters['restore_def']))
        
        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Target PgSQL node not available'
        register_restore_catalog(db)
        sys.exit(1) 
        
    try:
        global_parameters['pgsql_node_backup_dir'] = db.get_pgsql_node_config_value(global_parameters['pgsql_node_id'],'pgnode_backup_partition')

    except psycopg2.Error as e:
        global_parameters['pgsql_node_backup_dir'] = pgsql_node_cache_data['pgnode_backup_partition']
    

    global_parameters['backup_server_pgsql_bin_dir'] = get_backup_server_pgsql_bin_dir(db)
    global_parameters['target_pgsql_node_release'] = get_pgsql_node_release(db,db_pgnode)

    global_parameters['restore_log_file'] = get_logfile_id()

    target_pgsql_node_release = int(global_parameters['target_pgsql_node_release'].replace('_',''))
    backup_release = int(global_parameters['pg_release'].replace('_',''))

    #
    # Check if the postgreSQL version of the tools used for the backup
    # is newer than the version running in the target pgsql node. stop
    # the backup job with an error if it is newer
    #

    if backup_release > target_pgsql_node_release:
        logs.logger.critical('The postgreSQL version (%s) of the tools used for the backup is newer than the version (%s) running in the target pgsql node. Stopping restore process.',
                             global_parameters['pg_release'],
                             global_parameters['target_pgsql_node_release'].replace('_','.'))

        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'Backup pgsql release > Target pgsql node release'
        register_restore_catalog(db)
        sys.exit(1) 

    if global_parameters['renamed_dbname'] != '':
        rename_existing_database(db,db_pgnode)
        logs.logger.info('Renaming an existing database to %s before restoring the backup in the target database',global_parameters['renamed_dbname'])
        
    #
    # Check if the target database already exists in the target PgSQL
    # node. Stop the backup with an error it it exists.
    #
        
    if db_pgnode.database_exists(global_parameters['target_dbname']):
        logs.logger.critical('The target database already exists in the target PgSQL node')

        global_parameters['execution_status'] = 'ERROR'
        global_parameters['error_message'] = 'The target database already exists in the target PgSQL node'
        register_restore_catalog(db)
        sys.exit(1) 

    restore_roles(db)
    restore_dbconfig(db)
    restore_database(db)

    global_parameters['execution_status'] = 'SUCCEEDED'
    register_restore_catalog(db)


# ############################################
# Function signal_handler()
# ############################################
    
def signal_handler(signum, frame):
    logs.logger.info('**** pgbackman_dump stopped. ****')
    sys.exit(0)


# ############################################
# 
# ############################################

if __name__ == '__main__':

    signal.signal(signal.SIGINT,signal_handler)
    signal.signal(signal.SIGTERM,signal_handler)

    parser = argparse.ArgumentParser(prog=sys.argv[0])
    parser.add_argument('--node-fqdn', metavar='PGSQL-NODE-FQDN', required=True, help='PgSQL node FQDN', dest='pgsql_node_fqdn')
    parser.add_argument('--node-id', metavar='PGSQL-ID', required=True, help='PgSQL node ID', dest='pgsql_node_id')
    parser.add_argument('--node-port', metavar='PGSQL-NODE-PORT', required=True, help='PgSQL node port', dest='pgsql_node_port')
    parser.add_argument('--node-user', metavar='PGSQL-NODE_ADMIN-USER', required=True, help='PgSQL node admin user', dest='pgsql_node_admin_user')
    parser.add_argument('--restore-def', metavar='RESTORE-DEF', required=True, help='Restore ID', dest='restore_def')
    parser.add_argument('--pgdump-file', metavar='PGDUMP-FILE', required=True, help='Pg_dump file', dest='pgdump_file')
    parser.add_argument('--pgdump-roles-file', metavar='PGDUMP-ROLES-FILE', required=True, help='Pg_dump role file', dest='pgdump_roles_file')
    parser.add_argument('--pgdump-dbconfig-file', metavar='PGDUMP-DBCONFIG-FILE', required=True, help='Pg_dump dbconfig file', dest='pgdump_dbconfig_file')
    parser.add_argument('--source-dbname', metavar='SOURCE-NAME', required=True, help='Source database name', dest='source_dbname')
    parser.add_argument('--target-dbname', metavar='TARGET-NAME', required=True, help='Target database name', dest='target_dbname')
    parser.add_argument('--renamed-dbname', metavar='RENAMED-DBNAME', required=False, help='Renamed database', dest='renamed_dbname')
    parser.add_argument('--extra-restore-parameters', metavar='EXTRA-RESTORE-PARAMETERS', required=False, help='extra pg_restore parameters', dest='extra_restore_parameters')
    parser.add_argument('--role-list', metavar='ROLE-LIST', required=False, help='Roles to restore', dest='role_list')
    parser.add_argument('--pg-release', metavar='PG-RELEASE', required=True, help='PG release from backup', dest='pg_release')
    parser.add_argument('--root-backup-dir', metavar='ROOT-BACKUP-DIR', default=True, required=True, help='Root backup dir', dest='root_backup_dir')

    args = parser.parse_args()    

    if args.pgsql_node_fqdn:
        global_parameters['pgsql_node_fqdn'] = args.pgsql_node_fqdn
    else:
        print('PgSQL node fqdn parameter not defined')
        sys.exit(1)

    if args.pgsql_node_id:
        global_parameters['pgsql_node_id'] = args.pgsql_node_id
    else:
        print('PgSQL node id parameter not defined')
        sys.exit(1)

    if args.pgsql_node_port:
        global_parameters['pgsql_node_port'] = args.pgsql_node_port
    else:
        print('PgSQL node port parameter not defined')
        sys.exit(1)
    
    if args.pgsql_node_admin_user:
        global_parameters['pgsql_node_admin_user'] = args.pgsql_node_admin_user
    else:
        print('PgSQL node admin user parameter not defined')
        sys.exit(1)
    
    if args.restore_def:
        global_parameters['restore_def'] = args.restore_def
    else:
        print('RestoreID parameter not defined')
        sys.exit(1)
        
    if args.pgdump_file:
        global_parameters['pgdump_file'] = args.pgdump_file
    else:
        print('pg_dump file parameter not defined')
        sys.exit(1)

    if args.pgdump_roles_file:
        global_parameters['pgdump_roles_file'] = args.pgdump_roles_file
    else:
        print('pg_dump role file parameter not defined')
        sys.exit(1)

    if args.pgdump_dbconfig_file:
        global_parameters['pgdump_dbconfig_file'] = args.pgdump_dbconfig_file
    else:
        print('pg_dump dbconfig file parameter not defined')
        sys.exit(1)

    if args.source_dbname:
        global_parameters['source_dbname'] = args.source_dbname
    else:
        print('Source dbname parameter not defined')
        sys.exit(1)   

    if args.target_dbname:
        global_parameters['target_dbname'] = args.target_dbname
    else:
        print('Target dbname parameter not defined')
        sys.exit(1)

    if args.renamed_dbname:
        global_parameters['renamed_dbname'] = args.renamed_dbname
    else:
        global_parameters['renamed_dbname'] = ''

    if args.extra_restore_parameters:
        global_parameters['extra_restore_parameters'] = args.extra_restore_parameters.replace("'","")
    else:
        global_parameters['extra_restore_parameters'] = ''

    if args.role_list:
        global_parameters['role_list'] = args.role_list.replace(' ','').split(',')
    else:
        global_parameters['role_list'] = []

    if args.pg_release:
        global_parameters['pg_release'] = args.pg_release.replace('.','_')
    else:
        print('PG release parameter not defined')
        sys.exit(1)

    if args.root_backup_dir:
        global_parameters['root_backup_dir'] = args.root_backup_dir
    else:
        print('Root backup directory parameter not defined')
        sys.exit(1)

    #
    # Initializing logging
    #

    logs = PgbackmanLogs("pgbackman_restore", "[" + global_parameters['pgsql_node_fqdn'] + "]", "[" + global_parameters['target_dbname'] + "]")
    logs.logger.info('**** pgbackman_restore started. ****')
    
    main()

    logs.logger.info('**** pgbackman_restore finished. ****')
    
