#!/usr/bin/python
#
# Copyright 2011 SUSE Linux Products GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 


import getopt
import sys
import os
import os.path
import getpass

# Package comes to /usr/share/suse/smdba by default
PACKAGE_PATH="/usr/share/suse/smdba"
if os.path.exists(PACKAGE_PATH):
    sys.path.append(PACKAGE_PATH)

try:
    from de.suse.lib.saferun.SMUtils import OpConfig, \
                                            SMPlatform

    from de.suse.lib.saferun.SMRegistrar import SMScenarioRunner, \
                                                SMLogger, \
                                                SMGarbageCollector, \
                                                SMChangeManagement

    from de.suse.lib.saferun.SMPackageManager import SMPackageManager

    from de.suse.lib.saferun.SMRegTasks import DownloaderTask, \
                                               ZypperRepoInstallTask, \
                                               ConfigUpdateTask, \
                                               SanityCheckTask, \
                                               PackageManagerTask, \
                                               PackageGPGKeyImporter, \
                                               RegisterTask, \
                                               SSLCertInstall, \
                                               ResourceLinkTask, \
                                               ResourceCopyTask
except Exception, ex:
    print >> sys.stderr, "Fatal error:", ex
    print >> sys.stderr, "Is \"saferun\" installed?.."
    sys.exit(1)


__author__="bo@suse.de"
__date__ ="$May 26, 2011 1:54:15 PM$"


def header(out=sys.stderr):
    print >> out, "SUSE Manager Client Tools, v1.0\n"

    
def usage():
    usageText = """Usage:
     %s [options] <command>

Options:
     -c                    Use Change Management.
                           Limitations:
                           1. Change Management is possible only with XML output.
                           2. Depending on the amount of installed packages,
                              registration may take more than 10 minutes.

     --hostname            Host name of the SUSE Manager.
     --activation-keys     ID of the activation key in SUSE Manager.
     --ssl-fingerprint     Specify SSL key fingerprint to download over insecure HTTP.
     --profile-name        Name of the profile. Default is used if omitted.
     --output-format       Output format: xml or text. Default is "text".
     --debug               Debug the registration process.
     --help                This text.

Environment Variables:
     SM_PROXY_USER         User name for a proxy authentication.
     SM_PROXY_PASSWORD     Password for a proxy authentication."""

    header()
    print >> sys.stderr, (usageText % sys.argv[0].split("/")[-1])


class SMRegisterScenario(SMScenarioRunner):
    """
    Batch scenario.
    """

    def __init__(self, host, actkey, profile, ssl_key_fingerprint, httpProxyHost=None, useChangeManagement=False, log_mode=False):
        cfm = {
            "enableProxy": "%s" % (httpProxyHost and 1 or 0),
            "enableProxyAuth": "%s" % (os.environ.get("SM_PROXY_USER", "") and 1 or 0),
            "httpProxy": httpProxyHost and httpProxyHost or "",
            "proxyPassword": os.environ.get("SM_PROXY_PASSWORD", ""),
            "proxyUser": os.environ.get("SM_PROXY_USER", ""),
            "noSSLServerURL": "http://%s/XMLRPC" % host,
            "serverURL": "https://%s/XMLRPC" % host,
            "sslCACert": "/usr/share/rhn/RHN-ORG-TRUSTED-SSL-CERT",
            "useGPG": "1",
        }

        distro = SMPlatform().getLinuxRelease()

        self.scenario = []

        if ssl_key_fingerprint:
            cert_name = "RHN-ORG-TRUSTED-SSL-CERT"
            self.scenario.append((SSLCertInstall("https://" + host + "/pub/" + cert_name, ssl_key_fingerprint), None, None,))
            if distro.product in ['sles', 'suse']:
                self.scenario.append((ResourceCopyTask("/etc/ssl/certs/%s.pem" % cert_name, "/usr/share/rhn/", cert_name), None, None,))

        # Sanity check if system is healthy in general
        self.scenario.append((SanityCheckTask(), None, None,))

        # Add Zypper repo
        if distro.product == 'sles' and ((distro.version == 11 and distro.update == 1) or distro.version == 10):
            self.scenario.append((ZypperRepoInstallTask("https://" + host + "/pub/repositories/susemanager-client-setup", "susemanager-client-setup"), None, None,))

        # Install rhn-setup package
        self.scenario.append((PackageManagerTask()
             .setPackagesForInstall(SMPackageManager.LINUX_ZYPPER, "spacewalk-check", "spacewalk-client-setup", "spacewalk-client-tools", "zypp-plugin-spacewalk")
             .setPackagesForInstall(SMPackageManager.LINUX_YUM, "rhn-setup"), None, None,))

        # RHN pre-configuration
        self.scenario.append((ConfigUpdateTask("/etc/sysconfig/rhn/rhn_register", cfm, weak=True).setConfigSuffixes("[comment]"), None, None,))
        self.scenario.append((ConfigUpdateTask("/etc/sysconfig/rhn/up2date", cfm).setConfigSuffixes("[comment]"), None, None,))

        # Import GPG keys
        #(PackageGPGKeyImporter("https://" + host + "/pub/security/"), None, None),

        # Enable Actions
        self.scenario.append((RegisterTask(host, actkey, profileName=profile)
            .setPackagesForUpgrade(SMPackageManager.LINUX_ZYPPER, "yum", "yum-rhn-plugin")
            .setPackagesForUpgrade(SMPackageManager.LINUX_YUM, "zypper", "zypp-plugin-spacewalk"), None, None,))

        # Lock the object
        SMScenarioRunner.__init__(self, SMLogger(), SMGarbageCollector(), SMChangeManagement(), useChangeManagement=useChangeManagement)


def oops(problem):
    """
    Print error and quit.
    """
    oopsText = """Run with "--help" option will get you a list of options.
    
    Error: %s
    
"""
    header()
    print >> sys.stderr, oopsText % problem
    sys.exit(1)


if __name__ == "__main__":
    if getpass.getuser() != 'root':
        oops("Root privileges required.")

    op_config = OpConfig()
    opts, args = (None, None)
    try:
        opts, args = getopt.getopt(sys.argv[1:], "c", ["help", "activation-keys=", "output-format=", "hostname=", "ssl-fingerprint=", "debug"])
    except Exception, ex:
        oops(str(ex))

    if not opts:
        oops("Required parameters missing.")

    # Help?
    if "--help" in map(lambda optset:optset[0], opts):
        usage()
        sys.exit(1)

    # Ask for stuff
    activationKeys = None
    ssl_key_fingerprint = None
    profile = None
    hostname = None
    outputFormat = "text"
    changeManagement = False
    for optkey, optval in opts:
        if optkey == "--activation-keys":
            activationKeys = optval
        elif optkey == "--hostname":
            hostname = optval
        elif optkey == "--output-format":
            outputFormat = optval
        elif optkey == "--profile-name":
            profile = optval
        elif optkey == "--ssl-fingerprint":
            ssl_key_fingerprint = optval
        elif optkey == "--debug":
            op_config.set("debug_mode", False)
        elif optkey == "-c":
            changeManagement = True

    if changeManagement and outputFormat != "xml":
        oops("Change Management is possible only with XML format output.")

    # Check
    if not (activationKeys and hostname):
        oops("Activation key or SUSE Manager hostname is missing.")
    elif not outputFormat:
        oops("You tried to specify an output format, but missed it.")
    elif ("text" not in outputFormat) and ("xml" not in outputFormat):
        oops('The "%s" is an unknown output format. Try "xml" or remove the option at all. Or read man, perhaps.' % outputFormat)

    
    # Run
    print >> sys.stdout, SMRegisterScenario(hostname,
                                            activationKeys,
                                            profile,
                                            ssl_key_fingerprint,
                                            useChangeManagement=changeManagement)().logger.formatAs(outputFormat)
