
import os
import string
import json
from subprocess import *

CI_SCRIPTS_ROOT = '/home/jenkins/ci-scripts/'
SHELL_REFRESH_CMS3 = CI_SCRIPTS_ROOT + 'vmop/RefreshCMS3xVM.sh'
SHELL_REFRESH_CMS4 = CI_SCRIPTS_ROOT + 'vmop/RefreshCMS40VM.sh'

CMD_DEPLOY = 'ssh root@{ip_addr} "' + \
        'cd {pkg_root}; ' + \
        'sh ./deploy.sh {pre_config} << EOF\n{instructions}\nEOF"'

CMD_UPGRADE = 'ssh root@{ip_addr} "' + \
        'cd {pkg_root}; ' + \
        'sh ./upgrade.sh {pre_config} << EOF\n{instructions}\nEOF"'

CMD_ROLLBACK = 'ssh root@{ip_addr} "' + \
        'cd {pkg_root}; ' + \
        'sh ./rollback.sh {pre_config} << EOF\n{instructions}\nEOF"'

CMD_EXPORT = 'ssh root@{ip_addr} "' + \
        'cd {pkg_root}; ' + \
        'python ./utils/Monitor.py -s install_sysInfo.json -e"'

CMD_EXPORT_IMPORTED_TEMPLATE = 'ssh root@{ip_addr} "' + \
        'cd {pkg_root}; ' + \
        'python ./utils/Monitor.py -s install_sysInfo.json -E"'

CMD_COMPARE = 'ssh root@{ip_addr} "' + \
        'cd {pkg_root}; ' + \
        'set -o pipefail; ' + \
        'python ./utils/Monitor.py -s install_sysInfo.json -c -j {exclude_diff_config} ' + \
        '| tee {report_file}"'

CMD_COMPARE_WITH_IMPORTED_TEMPLATE = 'ssh root@{ip_addr} "' + \
        'cd {pkg_root}; ' + \
        'set -o pipefail; ' + \
        'python ./utils/Monitor.py -s install_sysInfo.json -c -C -j {exclude_diff_config} ' + \
        '| tee {report_file}"'

CMD_UPLOAD_FILE = 'scp {local_path} root@{ip_addr}:{remote_path}'

CMD_DOWNLOAD_FILE = 'scp root@{ip_addr}:{remote_path} {local_path}'

LIC_PATH = '/opt/tandbergtv/cms/conf/workflow/prepackLicense.xml'

def deploy(ip_addr, pkg_root, instructions='', pre_config=''):
    """
    Execute deploy script from remote.
    """
    cmd_str = CMD_DEPLOY.format(ip_addr=ip_addr, \
                                pkg_root=pkg_root, \
                                instructions=instructions, \
                                pre_config=pre_config)
    _exe_cmd(cmd_str)

def upgrade(ip_addr, pkg_root, instructions='', pre_config=''):
    """
    Execute upgrade script from remote.
    """
    cmd_str = CMD_UPGRADE.format(ip_addr=ip_addr, \
                                pkg_root=pkg_root, \
                                instructions=instructions, \
                                pre_config=pre_config)
    _exe_cmd(cmd_str)

def rollback(ip_addr, pkg_root, instructions='', pre_config=''):
    """
    Execute rollback script from remote.
    """
    cmd_str = CMD_ROLLBACK.format(ip_addr=ip_addr, \
                                pkg_root=pkg_root, \
                                instructions=instructions, \
                                pre_config=pre_config)
    _exe_cmd(cmd_str)

def refresh_cms3(virt_serv_ip, db_ip, db_domain, app_ip, app_domain, snapshot_name):
    arg_str = ' VIRT_SERVER={virt_server} SNAPSHOT_NAME={snapshot_name} ' + \
              'DB_IP={db_ip} DB_DOMAIN={db_domain} APP_IP={app_ip} APP_DOMAIN={app_domain}'
    cmd_str = SHELL_REFRESH_CMS3 + arg_str.format(virt_server=virt_serv_ip, \
                                                 app_ip=app_ip, \
                                                 app_domain=app_domain, \
                                                 db_ip=db_ip, \
                                                 db_domain=db_domain, \
                                                 snapshot_name=snapshot_name)
    _exe_cmd(cmd_str)

def refresh_cms4(virt_serv_ip, db_ip, db_domain, app_ips, app_domains, \
                 snapshot_name, cs_ip, cs_domain, es_domain, pt_domain=None):
    arg_str = ' VIRT_SERVER={virt_server} SNAPSHOT_NAME={snapshot_name} ' + \
              'CS_IP={cs_ip} CS_DOMAIN={cs_domain} ES_DOMAIN={es_domain} ' + \
              'DB_IP={db_ip} DB_DOMAIN={db_domain} APP_IP={app_ip} APP_DOMAIN={app_domain} '
    # PT_DOMAIN={pt_domain}
    app_ip = string.join(app_ips, ',')
    app_domain = string.join(app_domains, ',')
    
    cmd_str = SHELL_REFRESH_CMS4 + arg_str.format(virt_server=virt_serv_ip, \
                                                 app_ip=app_ip, \
                                                 app_domain=app_domain, \
                                                 db_ip=db_ip, \
                                                 db_domain=db_domain, \
                                                 cs_ip=cs_ip, \
                                                 cs_domain=cs_domain, \
                                                 es_domain=es_domain, \
                                                 snapshot_name=snapshot_name)
    if pt_domain is not None and len(pt_domain.strip()) > 0:
        cmd_str = cmd_str + ' PT_DOMAIN=' + pt_domain
    
    _exe_cmd(cmd_str)

def apply_license(app_ip, local_lic_path):
    cmd_str = CMD_UPLOAD_FILE.format(ip_addr=app_ip, \
                                     local_path=local_lic_path, \
                                     remote_path=LIC_PATH)
    _exe_cmd(cmd_str)

def export(ip_addr, pkg_root, with_imported_templates=False):
    cmd_str = CMD_EXPORT.format(ip_addr=ip_addr, pkg_root=pkg_root)
    _exe_cmd(cmd_str)
    
    if with_imported_templates:
        cmd_str = CMD_EXPORT_IMPORTED_TEMPLATE.format(ip_addr=ip_addr, pkg_root=pkg_root)
        _exe_cmd(cmd_str)

def compare(ip_addr, pkg_root, ex_diff_config, report_file, with_imported_templates=False):
    if with_imported_templates:
        cmd_str = CMD_COMPARE_WITH_IMPORTED_TEMPLATE.format( \
                                        ip_addr=ip_addr, \
                                        pkg_root=pkg_root, \
                                        exclude_diff_config=ex_diff_config, \
                                        report_file=report_file)
        _exe_cmd(cmd_str)
    else:
        cmd_str = CMD_COMPARE.format(ip_addr=ip_addr, \
                                     pkg_root=pkg_root, \
                                     exclude_diff_config=ex_diff_config, \
                                     report_file=report_file)
        _exe_cmd(cmd_str)

def dump_exclusion_json(cnf_object, remote_ip):
    filePath = "/tmp/exclude_diff_config." + str(os.getpid()) + ".json"
    configObj = cnf_object if cnf_object else {}
    with open(filePath, 'w') as f:
        json.dump(configObj, f, indent=4)
    cmd_str = CMD_UPLOAD_FILE.format(ip_addr=remote_ip, local_path=filePath, remote_path=filePath)
    _exe_cmd(cmd_str)
    os.remove(filePath)
    return filePath

def upload_installation_package(ip_addr, pkg_folder, pkg_name=None, pkg_file_suffix='-release.tar.gz'):
    # if no pkg_name is passed in, find the latest one
    if pkg_name is None:
        p = Popen("ls -1tr %s | grep '%s$' | tail -1"%(pkg_folder, pkg_file_suffix), \
                  shell=True, stdout=PIPE).stdout
        fn = p.read().strip()
        pkg_name = fn[0:fn.index(pkg_file_suffix)]
    
    full_path = os.path.join(pkg_folder, pkg_name + pkg_file_suffix)
    cmd_str = 'cat {pkg_file} | ssh root@{ip_addr} "tar -xzf -"'.format(pkg_file=full_path, ip_addr=ip_addr)
    _exe_cmd(cmd_str)

def download_file_to_local(ip_addr, remote_path, local_path, skip_not_found=False):
    if skip_not_found:
        if not _remote_file_exists(ip_addr, remote_path):
            return
    
    local_dir = os.path.dirname(local_path)
    if not os.path.exists(local_dir):
        os.makedirs(local_dir)
    
    cmd_str = CMD_DOWNLOAD_FILE.format(ip_addr=ip_addr, remote_path=remote_path, local_path=local_path)
    _exe_cmd(cmd_str)

def upload_file_to_remote(ip_addr, local_path, remote_path, skip_not_found=False):
    if skip_not_found:
        if not os.path.exists(local_path):
            return
    
    remote_dir = os.path.dirname(remote_path)
    rmt_mkdir = 'ls -ld {remote_path} || mkdir -p {remote_path}'.format(remote_path=remote_dir)
    exe_generic_remote_cmd(ip_addr, rmt_mkdir)
    
    cmd_str = CMD_UPLOAD_FILE.format(ip_addr=ip_addr, remote_path=remote_path, local_path=local_path)
    _exe_cmd(cmd_str)

def exe_generic_remote_cmd(ip_addr, command):
    cmd_str = 'ssh root@%s "%s"' % (ip_addr, command.replace('"', '\\"'))
    _exe_cmd(cmd_str)

###  internals...

def _remote_file_exists(ip_addr, remote_path):
    cmd_str = 'ssh root@{ip_addr} "ls -ld {remote_path}"'
    status_code = os.system(cmd_str.format(ip_addr=ip_addr, remote_path=remote_path))
    return status_code == 0

def _exe_cmd(cmd_str):
    print('> ' + cmd_str)
    pipe = Popen(cmd_str, shell=True, stdout=PIPE).stdout
    print(pipe.read())

