#!/usr/bin/python
#
# Copyright (c) 2010 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public License,
# version 2 (GPLv2). There is NO WARRANTY for this software, express or
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
# along with this software; if not, see
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
#
# Red Hat trademarks are not licensed under GPLv2. No permission is
# granted to use or replicate Red Hat trademarks that are incorporated
# in this software or its documentation.
#

import os
import re
import platform
import sys
import glob
import shutil
import rhsm.config as config
from instnum import InstallationNumber, InstallationNumberError
from datetime import datetime

_LIBPATH = "/usr/share/rhsm"
# add to the path if need be
if _LIBPATH not in sys.path:
    sys.path.append(_LIBPATH)

from rhsm import ourjson as json
from subscription_manager.i18n import configure_i18n
from subscription_manager.i18n_optparse import OptionParser, \
     WrappedIndentedHelpFormatter, USAGE
from subscription_manager import logutil

configure_i18n()

import gettext
_ = gettext.gettext

logutil.init_logger()

cfg = config.initConfig()
PRODUCT_CERT_DIR = cfg.get('rhsm', 'productcertdir')

# Error messages in instnum that need to be translated.
_("Not a valid hex string")
_("Not a string")
_("Unsupported string length")
_("Checksum verification failed")

# Set up command line options
parser = OptionParser(usage=USAGE,
                      formatter=WrappedIndentedHelpFormatter())
parser.add_option('-i',
                  '--instnumber',
                  help=_("install number to run against"))
parser.add_option('-d',
                  '--dryrun', action="store_true",
                  default=False,
                  help=_("only print the files which would be copied over"))
(options, args) = parser.parse_args()


def getRelease():
    f = open('/etc/redhat-release')
    lines = f.readlines()
    f.close()
    release = "RHEL-" + str(lines).split(' ')[6].split('.')[0]
    return release


def writeMigrationFacts(instnumber):
    migration_date = datetime.now().isoformat()

    FACT_FILE = "/etc/rhsm/facts/migration.facts"
    if not os.path.exists(FACT_FILE):
        f = open(FACT_FILE, 'w')
        json.dump({"migration.migrated_from": "install_number",
                   "migration.migration_date": migration_date,
                   "migration.install_number": instnumber.strip()}, f)
        f.close()


def determine_arch():
    platform_machine = platform.machine()
    parser = re.compile(r'i[\d]86')
    if parser.match(platform_machine):
        # make all x86 arches map to i386 to match the proper cert
        platform_machine = 'i386'
    elif getRelease() == 'RHEL-5' and platform_machine == 'ppc64':
        # 786450: map ppc64 to ppc for RHEL 5
        platform_machine = 'ppc'
    return platform_machine


def main():
    #quick check to see if you are a super-user.
    if os.getuid() != 0:
        print _("Must be root user to execute\n")
        sys.exit(8)

    #get the instnum
    instnumber = options.instnumber
    if not instnumber:
        try:
            f = open('/etc/sysconfig/rhn/install-num', 'r')
            instnumber = f.readline()
            f.close()
        except IOError:
            print _("Could not read installation number from /etc/sysconfig/rhn/install-num.  Aborting.")
            sys.exit(1)

    #parse the instnum
    try:
        instnum = InstallationNumber(instnumber)
    except InstallationNumberError, e:
        print _("Could not parse the installation number: %s") % (_(str(e)))
        sys.exit(1)

    repo_dict = instnum.get_repos_dict()

    platform_machine = determine_arch()

    sourcepath = "/usr/share/rhsm/product/" + getRelease()
    globs = []
    #generate globs to potentially match the name of the certs under sourcepath
    for key in repo_dict.keys():
        globs.append(repo_dict['Base'] + '-' + repo_dict[key] + '-' + platform_machine + '*')

    paths = [glob.glob(sourcepath + '/' + x) for x in globs]

    #flatten the list of lists
    paths = [item for sublist in paths for item in sublist]

    path_dict = {}
    for path in paths:
        dest = path.split('-')[-1]
        path_dict[dest] = path

    # Hack for BZ #853233: 68.pem and 71.pem should never coexist.
    if "68.pem" in path_dict.keys() and "71.pem" in path_dict.keys():
        del path_dict["68.pem"]

    for dest_file, path in path_dict.items():
        dest_file = os.path.join(PRODUCT_CERT_DIR, dest_file)
        print _("Installing %s to %s") % (path, dest_file)
        if not os.path.isdir(PRODUCT_CERT_DIR):
            print _("No such directory: %s") % PRODUCT_CERT_DIR
            sys.exit(1)

        if not options.dryrun:
            try:
                shutil.copyfile(path, dest_file)
            except IOError, e:
                print e
                sys.exit(1)

    if not options.dryrun:
        writeMigrationFacts(instnumber)

if __name__ == "__main__":
    main()
