#!/usr/bin/env python2
# -*- encoding: utf-8 -*-

import os
import sys
import argparse
import mysql_backup_mds.mds as mds
import mysql_backup_mds.support as support
import json

DEFAULT_CONFIG = "/etc/mysql-backup-mds/main.yaml"
USAGE = '''Программа для создания, просмотра и скачивания бекапов MySQL из MDS-S3.

%(prog)s command [instance1 [instance2] ...] <optional arguments>

--- создание бекапов БД ---
%(prog)s create ppcdata1 ppcdata2
%(prog)s create ppcdata3

--- просмотр бекапов в виде списка ---
%(prog)s list

--- просмотр только бекапов ppcdata1 и ppcdata2 в виде списка ---
%(prog)s list ppcdata1 ppcdata2

--- просмотр бекапов в виде таблицы ---
%(prog)s list -t

--- восстановление бекапа по ключу(дирректория /opt/mysql.{instance}.tmp) ---
%(prog)s restore -n ppcdata1_08092017_ppcstandby01i_yandex_ru

--- восстановление бекапа по ключу с сохранением в кастомную дирректорию ---
%(prog)s restore -n ppcdata1_08092017_ppcstandby01i -o /opt/mysql.ppcdata1.tmp2

--- удаление бекапа из хранилища ---
%(prog)s remove -n ppcdata1_08092017_ppcstandby01i - удаление бекапа из хранилища

--- чистка хранилища от старых бекапов(по-умолчанию количество равно 10) ---
%(prog)s clean

--- чистка хранилища от дубликатов(на основе количества бекапов за день)
%(prog)s clean --remove-duplicates

'''

def run(config):
    logger = config.get('logger')
    logger.debug(config)
    config['dbh'] = mds.connect(**config)
    cmd = config['command']
    if cmd == 'list': 
        support.list_backup(config)
    elif cmd == 'create': 
        support.create_backup(config)
    elif cmd == 'restore':
        support.restore_backup(config)
    elif cmd == 'remove':
        support.remove_backup(config)
    elif cmd == 'clean':
        support.clean_backup(config)
    elif cmd == 'ps':
        support.process_backup(config)
    elif cmd == 'prepare':
        support.prepare_backup(config)
    elif cmd == 'download':
        support.download_backup(config)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(usage=USAGE)
    parser.add_argument("-d", "--debug", action='store_true',
			dest='debug', help="enable debug mode")
    parser.add_argument("-f", "--config", action='store', default=DEFAULT_CONFIG,
                        dest='file', help="path for config file")
    parser.add_argument("-n", "--backups", nargs='*', type=str, action='store',
                        dest='name_backups', help="name(keys) backups in mds. Working with [restore|remove]")
    parser.add_argument("command", nargs='?', type=str, action='store',
                        help="command for execute. Example: [create|list|restore|remove|clean|ps]")
    parser.add_argument("instances", nargs='*', type=str, action='store',
                        help="command for execute. Example: [instance1] [instance2]")
    parser.add_argument("-t", "--table", action='store_true',
                        dest="list_table", help="table mode for listing. Working with [list]")
    parser.add_argument("-j", "--json", action='store_true',
                        dest="list_json", help="json mode for listing. Working with [list]")
    parser.add_argument("--interactive", action='store_true',
                        dest="interactive", help="interactive mode/no fork. Working with [restore|prepare|download]")
    parser.add_argument("--remove-duplicates", action='store_true',
                        dest="remove_duplicates", help="remove duplicate backups per day. Working with [clean]")
    parser.add_argument("-s", "--simulate", action='store_true',
                        dest="simulate", help="simulate mode. Working with [remove|clean]")
    parser.add_argument("-o", "--mysql-directory", nargs='?', type=str, action='store',
                        dest="mysql_directory", help="directory for save/restore mysql backup")
    parser.add_argument("-e", "--enviroment", nargs='?', type=str, action='store',
                        dest="enviroment", help="enviroment type: [production|testing|development|prod|pr|test|ts|dev|dv]")
    parser.add_argument("--stop-replication", action='store_true',
                        dest="stop_replication", help="stop replication before start innobackupex and start after")
    parser.add_argument("--remove-data", action='store_true',
                        dest="remove_data", help="force remove old data")
    parser.add_argument("--memory-prepare", action='store', default="20G",
                        dest="memory_prepare", help="max memory for stage prepare data")
    parser.add_argument("--walg", action='store_true',
                        dest="walg", help="use walg utils")
    parser.add_argument("--force", action='store_true',
                        dest="force", help="force mode")
    opts = parser.parse_args()


    if len(opts.command) == 0 or opts.command not in ('list', 'create', 'remove', 'clean', 
                                                      'restore', 'ps', 'download', 'prepare'):
        parser.print_help()
        sys.exit(1)
    if opts.command == 'remove' and opts.name_backups is None:
        parser.print_help()
        sys.exit(1)

    config = opts.__dict__
    
    config['interactive'] = True if config['interactive'] else False #sys.stdout.isatty()
    support.load_config(config)
  
    support.start_logging(config)
    logger = config.get('logger')

    support.clean_old_hashfiles()

    if (config['mysql_directory'] is not None) and (len(config['instances']) != 1 and len(config['name_backups']) != 1):
        logger.critical("option --mysql-directory requires ONE instance")
        sys.exit(1)
    
    if  (config['command'] in ['restore', 'prepare', 'download']) and (config['name_backups'] is None):
        logger.critical("option --backups for restore not specified")
        parser.print_help()
        sys.exit(1)
   
    support.generate_hash_file(config)
    if ( (config['command'] in ('list', 'remove', 'clean', 'ps')) or
         (config['command'] in ('restore', 'prepare', 'download', 'create') and config['interactive']) ):
        run(config)
    else:
        pid = os.fork()
        run_status = {  "msg": "run process with pid {0}. Show logs in {1}".format(pid, config['log_file']),
                        "hashid": config["id"]
        }
        if pid != 0:
            jstatus = json.dumps(run_status)
            logger.warning(jstatus)
            print jstatus
            sys.stdout.flush()
            sys.exit(0)
        sys.stdout.flush()
        os.setsid()
        os.umask(0)
        os.chdir("/")
        pid = os.fork()
        if pid != 0:
            sys.exit(0)
        run(config)
