#!/usr/bin/python
#
# Registration client for the Red Hat Network for useage with kickstart 
# Copyright (c) 1999-2002 Red Hat, Inc.  Distributed under GPL.
#
# Author: Adrian Likins <alikins@redhat.com>
#
#  see the output of "--help" for the valid options. 
#
#  The contact info is in the form or a "key: value" one per line.
#  valid keys are:
#       reg_num, title, first_name, last_name, company,
#       position, address1, address2, city, state, zip,
#       country, phone, fax, contact_email, contact_mail,
#       contact_phone, contact_fax, contact_special,
#       contact_newsletter
#
#
#
import getopt
import sys

sys.path.insert(0, "/usr/share/rhn/")
sys.path.insert(1,"/usr/share/rhn/up2date_client")
import rhnreg
from rhpl.translate import _, N_
import hardware
import string
import rpmUtils
import up2dateErrors
import os
import sourcesConfig


# XXX: convert to use Optik
def printUsage():
    print _("Usage: rhnreg_ks [options]")
    print ""
    print _("Available command line options:")
    print _("-h, --help                     - this help ")
    print _("    --profilename=<value>      - specify a profilename")
    print _("    --username=<value>         - specify a username ")
    print _("    --password=<value>         - specify a password ")
    print _("    --orgid=<value>            - specify a organizational id ")
    print _("    --orgpassword=<value>      - specify a organizational password")
    print _("    --noSSLServerURL=<url>     - specify a url for a non ssl server")
    print _("    --useNoSSLForPackages      - dont use ssl to download packages")
    print _("    --sslCACert=<path>         - specify a file to use as the ssl CA cert")
    print _("    --serverUrl=<URL>          - specify a url to use as a server") 
    print _("    --email=<value>            - specify a email address ")
    print _("    --activationkey=<value>    - specify an activation key ")
    print _("    --subscription=<value>     - specify a subscription number to use ")
    print _("    --contactinfo              - read contact info from stdin ")
    print _("    --nohardware               - do not probe or upload any hardware info ")
    print _("    --nopackages               - do not profile or upload any package info ")
    print _("    --force                    - register the system even if it is already registered")
    print _("    --version                  - display the version ")
    print _("    --proxy                    - specify an http proxy to use ")
    print _("    --proxyUser=<value>        - specify a username to use with an authenticated http proxy")
    print _("    --proxyPassword=<value>    - specify a password to use with an authenticated http proxy")
    print ""


def showVersion():
        print "Red Hat Network Registration Agent "\
              "(Kickstart Version) v%s" % rhnreg.version()
        print "Copyright (c) 1999-2002 Red Hat, Inc."
        print _("Licensed under terms of the GPL.")


def readContactInfo():
    productInfo = [
        "reg_num",
        "title",
        "first_name",
        "last_name",
        "company",
        "position",
        "address1",
        "address2",
        "city",
        "state",
        "zip",
        "country",
        "phone",
        "fax",
        "contact_email",
        "contact_mail",
        "contact_phone",
        "contact_fax",
        "contact_special",
        "contact_newsletter"]
    
    # read a file from standard in or filename if specified
    L = sys.stdin.readlines()

    # parse it and build a dict
    info = {}
    for i in L:
        (key, value) = string.split(i, ':')
        info[key] = string.strip(value)

    #cleanse the hash for just the values we care about
    for i in info.keys():
        if i not in productInfo:
            del info[i]

    return info

def generateProfileName(hardwareList):
    hostname = None
    ipaddr = None
    profileName = None
    for hw in hardwareList:
        if hw['class'] == 'NETINFO':
            hostname = hw.get('hostname')
            ipaddr = hw.get('ipaddr')
            
    if hostname:
        profileName = hostname
    else:
        if ipaddr:
            profileName = ipaddr
            
    if not profileName:
        print _("A profilename was not specified, "\
                "and hostname and IP address could not be determined "\
                "to use as a profilename, please specify one.")
        sys.exit(-1)

    return profileName


def runRhnCheck():
    os.system("/usr/sbin/rhn_check")


def main(arglist=[]):
    
    if not len(arglist):
        arglist = sys.argv[1:]
    try:
        optlist, args = getopt.getopt(arglist,
                                      'h',
                                      ['help',
                                       'version',
                                       'username=','password=',
                                       'cryptedpassword=',
                                       'orgid=','orgpassword=',
                                       'profilename=',
                                       'nopackages',
                                       'nohardware',
                                       'norhnsd',
                                       'activationkey=',
                                       'serialnumber=',
				       'subscription=',
                                       'serverUrl=',
                                       'noSSLServerURL=', 
                                       'useNoSSLForPackages',
                                       'proxy=',
                                       'proxyUser=',
                                       'proxyPassword=',
                                       'sslCACert=', 
                                       'contactinfo',
                                       'email=',"force",])
    except getopt.error, e:
        print _("Error parsing command list arguments: %s") % e
        printUsage()
        sys.exit(1)

    username = password = orgid = orgPassword = profilename = email = None
    force = None
    nopackages = None
    nohardware = None
    serialnumber = None
    subscription = None
    contactinfo = None
    norhnsd = 0
    oemInfo = {}
    ca_certs = []

    # to indicate we've potentially ran some sort of setup
    # to prevent up2date from asking this on first run in
    # the "rhnregks;up2date -u" case
    rhnreg.cfg.set("networkSetup", 1)
    rhnreg.cfg.save()
    
    save_cfg = 0
    for opt in optlist:
        if opt[0] in ['-h', "--help"]:
            printUsage()
            sys.exit(-1)
        if opt[0] == "--username":
            username = str(opt[1])
        if opt[0] == "--password":
            password = str(opt[1])
        if opt[0] == "--orgid":
            orgid = str(opt[1])
        if opt[0] == "--orgpassword":
            orgPassword = str(opt[1])
        if opt[0] == "--cryptedorgpassword":
            cryptOrgPassword = str(opt[1])
        if opt[0] == "--cryptedpassword":
            cryptPassword = str(opt[1])
        if opt[0] == "--profilename":
            profilename = str(opt[1])
        if opt[0] == "--email":
            email = str(opt[1])
        if opt[0] == "--force":
            force = 1
        if opt[0] == "--nopackages":
            nopackages = 1
        if opt[0] == "--nohardware":
            nohardware = 1
        if opt[0] == "--norhnsd":
            norhnsd = 1  
        if opt[0] == "--serialnumber":
            print "--serialnumber is deprecated, please use --activationkey"
            serialnumber = str(opt[1])
        if opt[0] == "--activationkey":
            serialnumber = str(opt[1])
	if opt[0] == "--subscription":
	    subscription = str(opt[1])
        if opt[0] == "--serverUrl":
            rhnreg.cfg.set("serverURL", opt[1])
            save_cfg = 1
        if opt[0] == "--noSSLServerURL":
            rhnreg.cfg.set("noSSLServerURL", opt[1])
            save_cfg = 1
        if opt[0] == "--useNoSSLForPackages":
            rhnreg.cfg.set("useNoSSLForPackages", 1)
            save_cfg = 1
        if opt[0] == "--proxy":
            rhnreg.cfg.set("httpProxy", opt[1])
	    rhnreg.cfg.set("enableProxy", 1)
            save_cfg = 1
        if opt[0] == "--proxyUser":            
            rhnreg.cfg.set("proxyUser", opt[1])
            rhnreg.cfg.set("enableProxyAuth", 1)
            save_cfg = 1
        if opt[0] == "--proxyPassword":
            rhnreg.cfg.set("proxyPassword", opt[1])
            rhnreg.cfg.set("enableProxyAuth", 1)
            save_cfg = 1
        if opt[0] == "--sslCACert":
            ca_certs.append(opt[1])
#            rhnreg.cfg.set("sslCACert", opt[1])
            save_cfg = 1
        if opt[0] == "--contactinfo":
            contactinfo = readContactInfo()
        if opt[0] == "--version":
            showVersion()
            sys.exit(-1)

    # see if we need to update the sources list
    useRhn = 0
    sources = sourcesConfig.getSources()
    for source in sources:
        if source['type'] == "up2date":
            useRhn = 1
    # if your souces wasnt pointing at RHN before you
    # ran rhnreg_ks, it is now...
    if not useRhn:
         sourcesFile = sourcesConfig.SourcesConfigFile(filename="/etc/sysconfig/rhn/sources")
         sourcesFile.writeUp2date()
    

    if ca_certs:
        rhnreg.cfg.set("sslCACert", ca_certs)

    if save_cfg:
        rhnreg.cfg.save()
        
    if rhnreg.registered() and not force:
        print _("This system is already registered. Use --force to override")
        sys.exit(-1)

    if not serialnumber and (not username or not password and not email):
        print _("A username, password and email address are required "\
                "to register a system.")
        sys.exit(-1)

    rhnreg.getCaps()
    
    if not serialnumber:
        # reserver the username
        ret = rhnreg.reserveUser(username, password)
        rhnreg.registerUser(username, password, email, orgid, orgPassword)

    if not nopackages:
        getInfo = 0
        if rhnreg.cfg['supportsExtendedPackageProfile']:
            getInfo = 1
        packageList = rpmUtils.getInstalledPackageList(getInfo=getInfo)
    else:
        packageList = []

    # collect oemInfo 
    oemInfo = rhnreg.getOemInfo()
    
    hardwareList = hardware.Hardware()
    
    if not profilename:
        profilename = generateProfileName(hardwareList)

    other = {}
    if subscription:
	other['registrationNumber'] = subscription

    try:
        if serialnumber:
            systemId = rhnreg.registerSystem(token = serialnumber,
                                             profileName = profilename,
					     other = other)
        else:
            systemId = rhnreg.registerSystem(username, password,
					     profilename,
					     other = other)
    except up2dateErrors.AuthenticationTicketError, e:
        print "%s" % e.errmsg
        sys.exit(1)
    except up2dateErrors.RhnUuidUniquenessError, e:
        print "%s" % e.errmsg
        sys.exit(1)
    except up2dateErrors.CommunicationError, e:
        print "%s" % e.errmsg
        sys.exit(1)
        
        
    if serialnumber:
        rhnreg.sendSerialNumber(systemId, serialnumber)

    # collect hardware info, inluding hostname
    if not nohardware:
        rhnreg.sendHardware(systemId, hardwareList)

    if not nopackages:
        rhnreg.sendPackages(systemId, packageList)

    if contactinfo:
        if rhnreg.cfg['supportsUpdateContactInfo']:
            if username and password:
                rhnreg.updateContactInfo(username, password, oemInfo)
        else:
            rhnreg.registerProduct(systemId, contactinfo, oemInfo)

    if not norhnsd:
        rhnreg.startRhnsd()

    # write out the new id
    rhnreg.writeSystemId(systemId)

    runRhnCheck()


if __name__ == "__main__":
    main()
