#!/usr/bin/env python

import os
import re
import sys

from version import version

# function to write something to the install log
#
def log(msg):
	f = open('install.log', 'a')
	f.write(msg)
	f.close()

# function for writing a message to both stdout and the log
#
def log_print(msg):
	msg += '\n'
	sys.stdout.write(msg)
	log('>>>>> ' + msg + '\n')

# function for running a command via the shell and logging its results
#
def log_system(cmd):
	log('>>>>> Running command:\n')
	log('>>>>>   ' +  cmd + '\n')
	status = os.system('{ ' + cmd + ' ; } >> install.log 2>&1')
	log('\n')
	return status == 0

# function for running a command via the shell and logging its results
# that also returns a file object with access to the commands stdout
#
def log_popen(cmd):
	log('>>>>> Running command:\n')
	log('>>>>>   ' +  cmd + '\n')
	return os.popen('{ ' + cmd + ' ; echo $? > log_popen_exit_status; } 2>> install.log | tee -a install.log', 'r')

# function to clean up after log_popen()
#
def log_pclose(p):
	p.close()
	log('\n')
	f = open('log_popen_exit_status', 'r')
	status = int(f.read())
	f.close()
	os.unlink('log_popen_exit_status')
	return status == 0

# function to exit upon an error
#
def die():
	sys.stdout.write('See install.log for detailed information.\n')
	sys.exit(1)

# function to cleanup partial install then exit upon an error
#
def rollback_and_die():
	if 'TERAGRID_CLIENT_DISABLE_ROLLBACK' not in os.environ:
		log_print('Undoing previous install actions.')
		if not log_system('./uninstall-teragrid-client'):
			log_print('ERROR: failed to roll back partial installation.')
	die()

# make sure the working dir is inside the untarred package
#
if not os.path.isfile('install-teragrid-client'):
	sys.stdout.write('ERROR: Please run this installer from inside the untarred package.\n')
	sys.exit(1)

# make sure its cool with the user for us to install CA certs
#
ca_warning = """
As part of the TeraGrid Client Toolkit installation, a set of
certificate autorities (CAs) must be installed. Each CA represents
an organization (for example, the National Center for Supercomputing
Applciations NCSA) at the University of Illinois). Installing a CA
means that you trust the corresponding organization to verify the
indentities of grid services that you access from this machine.

This version of the toolkit will only install the NCSA certificate.
"""
sys.stdout.write(ca_warning)
if 'TERAGRID_CLIENT_NO_PROMPT' in os.environ:
	ca_answer = 'y'
else:
	ca_answer = raw_input('\nIs it OK to continue? (y/N):')
sys.stdout.write('\n')
if (len(ca_answer) == 0) or (ca_answer.lower()[0] != 'y'):
	sys.stdout.write('Installation aborted; exiting.\n')
	sys.exit(1)

# blow away any existing install log so we can start fresh
#
if os.path.exists('install.log'):
	os.unlink('install.log')

# say who we are and what we're doing
#
log_print('Installing the TeraGrid Client Toolkit ' + version + '.')

# check if everything's already installed
#
if os.path.isfile('install-marker'):
	log_print('Installation already present; exiting.')
	sys.exit(0)

# check for a previous unfinished install and remove it if present
#
if os.path.isfile('tarball-file-list'):
	log_print('Partial install already present; removing.')
	if not log_system('./uninstall-teragrid-client'):
		log_print('ERROR: Unable to remove previously unfinished install')
		die()

# dump out a list of what's in our working dir; this will be used
# by the unintaller as a list of what to keep around
#
lsfile = open('tarball-file-list', 'w')
for filename in os.listdir('.'):
	lsfile.write(filename + '\n')
lsfile.close()

# untar Pacman
#
if not log_system('tar xzf pacman-3.26.tar.gz'):
	log_print('ERROR: Unable to untar Pacman.')
	rollback_and_die()

# setup environment to pre-answer the VDT installer's questions
#
os.environ['VDTSETUP_AGREE_TO_LICENSES'] = 'y'
os.environ['VDTSETUP_INSTALL_CERTS'] = 'l'
os.environ['VDTSETUP_EDG_CRL_UPDATE']= 'n'

# initialize the contents of the Pacman trusted.caches file
#
if not log_system('cp pacman-caches trusted.caches'):
	log_print('ERROR: Error initializing trusted.caches.')
	rollback_and_die()

# see if we should be using an HTTP proxy
#
if 'TERAGRID_CLIENT_HTTP_PROXY' in os.environ:
	os.environ['http_proxy'] = os.environ['TERAGRID_CLIENT_HTTP_PROXY']

# set up command line for call to pacman
#
pacman_cmd = 'cd pacman-3.26 && . ./setup.sh && cd .. && /usr/bin/env python -u pacman-3.26/bin/pacman -v cache -v download -v tar -get '

# default Pacman cache can be overridden via the environment
#
if 'TERAGRID_CLIENT_PACKAGE_LOCATION' in os.environ:
	pacman_cmd += os.environ['TERAGRID_CLIENT_PACKAGE_LOCATION']
else:
	pacman_cmd += 'http://www.cs.wisc.edu/~gquinn/teragrid/pacman:TeraGrid-Client-' + version

# Pacman can also be told to use a specific platform ID rather than autodetecting
#
if 'TERAGRID_CLIENT_PLATFORM' in os.environ:
	pacman_cmd += ' -pretend-platform ' + os.environ['TERAGRID_CLIENT_PLATFORM']
	
# initialize Pacman to use a web proxy if one is given in the environment
#
if 'http_proxy' in os.environ:
	pacman_cmd += ' -http-proxy ' + os.environ['http_proxy']

# start pacman via popen, and process its stdout in order to display a progess meter
#
p = log_popen(pacman_cmd)
sys.stdout.write('[')
progress_re = re.compile(r'(^Package \[.*\] found)|(^Downloading \[.*\] from)')
progress_count = 0
while True:
	line = p.readline()
	if not line:
		break
	if progress_re.search(line):
		progress_count += 1
		if progress_count % 3 == 0:
			sys.stdout.write('*')
			sys.stdout.flush()
if not log_pclose(p):
	sys.stdout.write('\n')
	log_print('ERROR: Problem installing packages via Pacman.')
	rollback_and_die()
sys.stdout.write(']\n')

# install the TeraGrid-specific post-setup scripts
#
if not log_system('mkdir post-setup && cp setup-teragrid-client.*sh post-setup'):
	log_print('ERROR: Problem installing setup scripts.')
	rollback_and_die()

# install the CA certificates used by TeraGrid
#
f = open('vdt/etc/vdt-update-certs.conf', 'a')
f.write('\ncacerts_url = http://www.cs.wisc.edu/~gquinn/teragrid/certificates/vdt-igtf-ca-certs-version\n')
f.close()
if not log_system('source setup.sh && vdt-setup-ca-certificates'):
	log_print('ERROR: Problem installing CA certificates')
	rollback_and_die()

# touch a marker file to indicate the install succeeded
#
if not log_system('touch install-marker'):
	log_print('ERROR: Could not create install marker.')

# output an enouraging success message
#
log_print('TeraGrid Client Toolkit successfully installed.')
