#!/usr/bin/env python
# -*- coding: utf-8 -*-
##
#
# Vaisala software source code file
#
# Copyright (c) Vaisala Oyj 2015. All rights reserved.
#
##
"""
Tool for upgrading from PostgreSQL 9.2 provided by CentOS 7 out of the box to
PostgreSQL 9.4 provided by PostgreSQL Yum Repository.
"""
from __future__ import print_function
import os
import sys
import subprocess
import time

def log(*args, **kwargs):
    kwargs["file"] = sys.stderr
    return print(*args, **kwargs)

WORK_DIR = "/srv/vaisala/radarsw/postgresql-94-upgrade"
DUMP = os.path.join(WORK_DIR, "dump.sql.gz")

for bin in ["rsw-postgresql-94-configure", "rsw-postgresql-configure-auth"]:
    try:
        subprocess.check_call([bin, "--test"])
    except Exception, ex:
        log(u"Cannot call {}, bailing out! Check that it's on the PATH.".format(bin))
        raise ex

if len(sys.argv) > 1 and sys.argv[1] == '--test':
    sys.exit(0)


# Sanity checks for PostgreSQL versions, this script only handles clean 9.2 =>
# 9.4 migration.
non_empty_lines = [line.strip()
                   for line in
                   subprocess.check_output("rpm -qa --qf '%{NAME}\t%{VERSION}\n'",
                                           shell=True).split("\n")
                   if len(line.strip()) > 0]

postgres_lines = [line for line in non_empty_lines if 'postgres' in line]
package_version_pairs = [line.split("\t") for line in postgres_lines]

postgres_92_packages = []
other_postgres_packages = []
for package_name, version in package_version_pairs:
    if '9.2' in version:
        postgres_92_packages.append(package_name)
    else:
        other_postgres_packages.append(package_name)

if len(postgres_92_packages) == 0:
    sys.exit("No PostgreSQL 9.2 packages found!")
if len(other_postgres_packages) > 0:
    log("Following non-9.2 PostgreSQL packages were found:")
    for pkg in other_postgres_packages:
        log(pkg)
    log("You may try removing the package and re-running this script.")
    sys.exit("Exiting rsw-postgresql-upgrade-92-to-94.")
# End of sanity checks.


if os.path.exists(DUMP):
    log(u"{} exists. You must remove it first to retry running this script.".format(DUMP))
    sys.exit(1)

log(u"# Attempting to dump all data from PostgreSQL 9.2 to '{}'.".format(DUMP))
os.makedirs(WORK_DIR)
DUMP_COMMAND = u'set -xeo pipefail; su - postgres -c "pg_dumpall" | gzip > "{}"'.format(DUMP)
subprocess.check_call(DUMP_COMMAND, shell=True)
log("# Data from PostgreSQL 9.2 dumped.")


assert os.path.exists(DUMP)
assert os.path.isfile(DUMP)
assert os.path.getsize(DUMP) > 10000
log("# Database dump seems to be healthy.")

log("# Database dumped. Preparing to remove PostgreSQL 9.2. You can quit the upgrade now by pressing Ctrl+c.")
time.sleep(3)

subprocess.check_call(["service", "postgresql", "stop"])
log("# PostgreSQL 9.2 stopped.")

for pkg in postgres_92_packages:
    if subprocess.call(["rpm", "-q", "--quiet", pkg]) == 0:
        CMD = ["rpm", "-e", "--nodeps", pkg]
        log(u"# Removing package '{}'...".format(pkg))
        subprocess.check_call(CMD)
    else:
        log(u"# Not removing package '{}'...".format(pkg))
log("# PostgreSQL 9.2 removed.")
try:
    subprocess.check_call(["systemctl", "disable", "postgresql"])
except:
    pass


subprocess.check_call(["yum", "-y", "install", "postgresql94-server", "postgresql94-contrib"])
log("# PostgreSQL 9.4 installed.")


subprocess.check_call(["rsw-postgresql-94-configure"])
subprocess.check_call(["systemctl", "start", "postgresql-9.4"])
log("# PostgreSQL 9.4 configured and started.")


RESTORE_COMMAND = u'set -xeo pipefail; cat "{}" | gunzip | su - postgres -c "psql"'.format(DUMP)
subprocess.check_call(RESTORE_COMMAND, shell=True)
log("# Data restored to PostgreSQL 9.4.")


VACUUM_COMMAND = 'su - postgres -c "vacuumdb -a -z"'
subprocess.check_call(VACUUM_COMMAND, shell=True)
log("# PostgreSQL 9.4 databases optimized and table statistics updated.")
log("# Upgrade done.")
