#!/usr/bin/python -u
# "-u": Force stdin, stdout and stderr to be  totally  unbuffered.
#       To get more accurate log files
# 
# see also 
# http://www.faqts.com/knowledge_base/entry/versions/index.phtml?aid=4419

from optparse import OptionParser
import os
import sys
sys.path.insert(0, "../DistUpgrade")

import glob
import shutil
import datetime

from UpgradeTestBackend import UpgradeTestBackend

# FIXME: move this into the generic backend code
def login(backend):
    backend.bootstrap()
    d = backend._unpackToTmpdir(backend.tarball)
    print "logging into: '%s'" % d
    backend._runInChroot(d, ["/bin/sh"])
    print "Cleaning up"
    if d:
        shutil.rmtree(d)

def flushBuffer(fd):
    sys.stdout.flush()
    sys.stderr.flush()
    os.fsync(fd)

def createBackend(backend_name, profile, basedir):
    try:
        backend_modul = __import__(backend_name)
        backend_class = getattr(backend_modul, backend_name)
    except (ImportError, AttributeError, TypeError), e:
        print "Can not import: %s (%s) " % (backend_name, e)
        return None
    return backend_class(profile, basedir)
    
def testUpgrade(backend_name, profile, basedir, add_pkgs, to_stdout=False):
    backend = createBackend(backend_name, profile, basedir)
    assert(backend != None)
    os.chdir(basedir)
    if not os.path.exists(profile):
        print "ERROR: Can't find '%s' " % profile
        return False
    # make sure we actually have a resultdir
    resultdir = os.path.join(os.path.dirname(profile),"result")
    if not os.path.exists(resultdir):
        os.makedirs(resultdir)
    fd = os.open(os.path.join(resultdir,"bootstrap.log"),
                              os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0644)
    os.dup2(fd,1)
    os.dup2(fd,2)
    #fd2 = os.open("/dev/null",os.O_RDONLY)
    #os.dup2(fd2,0)
    print "%s log started" % datetime.datetime.now()

    try:
        # init the chroot
        if not backend.bootstrap():
            print "FAILED: bootstrap for '%s'" % profile
            flushBuffer(fd)
            return False
        if add_pkgs:
            if not backend.installPackages(add_pkgs):
                print "FAILED: installPacakges '%s'" % add_pkgs
                return False
        if not backend.upgrade():
            print "FAILED: upgrade for '%s'" % profile
            flushBuffer(fd)
            return False
        if not backend.test():
            print "FAILED: test for '%s'" % profile
            return False
        print "profile: %s worked" % profile
    except Exception, e:
        import traceback
        traceback.print_exc()
        print "Caught exception in testUpgrade for '%s' (%s)" % (profile, e)
        flushBuffer(fd)
        return False
    return True

if __name__ == "__main__":

    parser = OptionParser()
    parser.add_option("-p", "--profile", dest="profile", 
                      default="profile/ubuntu/DistUpgrade.cfg",
                      help="write report to FILE")
    parser.add_option("--additinoal", "--additional-pkgs", dest="add_pkgs", 
                      default="",
                      help="add additional pkgs before running the upgrade")
    parser.add_option("-a", "--auto", dest="auto", default=False,
                      action="store_true",
                      help="run all tests in profile/ dir")
    parser.add_option("--bootstrap-only", "--bootstrap-only",dest="bootstrap_only", 
                      default=False,
                      action="store_true",
                      help="only bootstrap the image")
    parser.add_option("-l", "--login", dest="login", default=False,
                      action="store_true",
                      help="log into the a profile")
    parser.add_option("-b", "--backend", dest="backend",
                      default="UpgradeTestBackendQemu",
                      help="UpgradeTestBackend to use: UpgradeTestBackendChroot, UpgradeTestBackendQemu")
    parser.add_option("-d", "--diff", dest="gen_diff",
                      default=False, action="store_true",
                      help="generate a diff of the upgraded image versus a fresh installed image")
    parser.add_option("--stdout", "--stdout", dest="to_stdout",
                      default=False, action="store_true",
                      help="all output goes to stdout")
    
    
    (options, args) = parser.parse_args()
    basedir = os.getcwd()

    # save for later
    fd1 = os.dup(1)
    fd2 = os.dup(2)

    res = True
    try:
        if options.auto:
            # we have some profiles that have DistUpgrade.cfg.dapper
            for d in glob.glob("./profile/*/DistUpgrade.cfg*"):
                os.dup2(fd1, 1)
                os.dup2(fd2, 2)
                print "Testing '%s'" % d
                res &= testUpgrade(options.backend, d, basedir)
        elif options.login:
            backend = createBackend(options.backend, options.profile, basedir)
            login(backend)
	elif options.bootstrap_only:
            backend = createBackend(options.backend, options.profile, basedir)	
	    backend.bootstrap(force=True)
        elif options.gen_diff:
            backend = createBackend(options.backend, options.profile, basedir)
            backend.genDiff()
        else:
            add_pkgs = []
            if  options.add_pkgs:
                add_pkgs = options.add_pkgs.split(",")
            res &= testUpgrade(options.backend, options.profile, basedir, add_pkgs, options.to_stdout)
    except Exception, e:
        print "ERROR: exception caught '%s' " % e
        import traceback
        traceback.print_exc()
        res = False

    # return error
    sys.exit(not res)
