#!/usr/bin/env python
# written by: Kuba Moscicki, 2003 CERN
# $Revision: 1.40 $
# last modified by: $Author: pfeiffer $ $Date: 2006/01/18 10:57:04 $
#
# please note: this script is a quick and dirty hack and should not be further developed
# in the current shape but it should be properly refactored instead. In particular in
# the area of recursive call to the same script which should be replaced by a recursive
# funtion call to properly inherit the original command line options.
#
import re
def usage():
msg = """
LCG Software Distribution and Installation Management Utility
usage:
lcg-installation-manager.py arguments [options] commands
arguments:
--project=NAME : name and version of LCG Project (example: POOL_1_0_0, SEAL_0_3_2)
commands:
list : list all dependant packages of the project
tar : archive (tar) all dependant packages into distribution area
html : create html page for the distribution area
download: download and install a project with dependant packages from central LCG repository
diff : list projects which need download (diff between local and main LCG repository)
this commands does NOT require a project name
rpm : do the rpms for EDG/LCG1 deployment
help : instructions how to use this script, RPM building etc...
options:
--prefix=DIR : LCG installation prefix (default: /afs/cern.ch/sw/lcg)
--keep-going,-k : continue execution even if some errors occur
--repository=URL: specify the repository (default: http://spi.cern.ch/extsoft)
--arch=ARCH : override the SCRAM_ARCH variable
--clean-tar=no|lcg|all
: remove tarballs after downloading, affects only download command
no is default, lcg=only lcg projects,all=lcg+external packages
--dereference : dereference symbolic links when tarring (used to be a default)
--distribution=DIR : change the location of tarball cache
ie.e use $PREFIX/external/DIR rather then $PREFIX/external/distribution
--always-fetch : download files even if local copies exist and have the same size as originals
environment variables:
SCRAM_ARCH - specifies platform.
required software:
SCRAM installation is required for html, tar and list commands.
SCRAM is NOT required for download command.
"""
# --commit : unless you specify commit NO changes are done to the installation area!
print msg
CONFIG = {}
CONFIG['lcg_prefix'] = '/afs/cern.ch/sw/lcg'
CONFIG['platf'] = 'rh73_gcc323' # default platform
# update with new projects when they arrive
CONFIG['lcg_project_list'] = ['PI','POOL', 'SEAL','GENSER','CORAL']
# update every time new platform is introduced
CONFIG['lcg_known_platforms'] = ['rh73_gcc32','rh73_ecc71','rh73_icc71','rh73_ecc80','rh73_icc80','win32_vc7','win32_vc71','sunos58','rh73_gcc323','cel3-i386_gcc323','slc3_ia32_gcc323','slc3_gcc323','slc3_ia64_gcc323','slc3_amd64_gcc323','slc3_amd64_gcc344','osx103_gcc33']
CONFIG['lcg_website_url'] = 'http://spi.cern.ch/lcgsoft'
CONFIG['website_dir'] = '/afs/cern.ch/project/lcg/app/www/spi/lcgsoft/'
CONFIG['rpm_prefix'] = '/usr/src/redhat/' #'/scratch/usr/src/redhat/'
CONFIG['distribution_location'] = 'distribution' # relative location of distribution directory in external...
# configure according to prefix
def configure():
global CONFIG
CONFIG['external_dir'] = CONFIG['lcg_prefix']+'/external'
CONFIG['distribution_dir'] = CONFIG['lcg_prefix']+'/external/'+CONFIG['distribution_location']
CONFIG['release_dir'] = CONFIG['lcg_prefix']+'/app/releases'
CONFIG['scram_dir'] = CONFIG['lcg_prefix']+'/app/spi/scram'
CONFIG['lcg_repository_url'] = 'http://service-spi.web.cern.ch/service-spi/external/'+CONFIG['distribution_location']+'/'
CONFIG['package_map_file_name'] = 'PACKAGE_MAP'
CONFIG['package_map_file_dir'] = '/external/distribution'#'/external/scripts'
CONFIG['html_template_file'] = CONFIG['distribution_dir']+'/lcgsoft_package_template.html'
CONFIG['package_map_file'] = CONFIG['lcg_prefix']+CONFIG['package_map_file_dir']+'/'+CONFIG['package_map_file_name']
CONFIG['rpm_template_file'] = CONFIG['lcg_prefix']+'/external/distribution/package.spec.template'
# this function is just internal, please refer to get_package_list()
def _get_package_list_from_scram_output(tool_list_file, package_map_file):
"""
parse scram output file and return a list of packages required by a project as
[scram_name, extsoft_name_string, extsoft_version_string].
Name and version string translations are defined by the python dictionary in package_map_file
Example of a translation dictionary:
dict = { 'python' : ['Python', {'2.2.2': '2-2-2'} ],
'gcc3' : None
}
"""
# skip first 4 lines of output
lines = file(tool_list_file).readlines()[4:]
# remove blank lines and whitespaces
splines = filter(lambda x: len(x)>0, map(lambda x: x.strip().split(), lines))
dict = eval( reduce( lambda x,y: x+y, file(package_map_file).readlines(), "") )
package_list = []
for l in splines:
name = l[0]
ver = l[1]
extsoft_name = name
extsoft_ver = ver
if name in dict:
meta = dict[name]
if meta:
extsoft_name = meta[0]
if meta[1] and ver in meta[1]:
extsoft_ver = meta[1][ver]
else:
extsoft_name = None
if extsoft_name == None:
print "### ignoring package: ", name
else:
if extsoft_name == 'coral' : extsoft_name = "CORAL" # bad hack for now, needs fix in config
package_list.append([name, extsoft_name, extsoft_ver])
return package_list
def get_scram_version_for_project(project_name, version_name):
return file(CONFIG['release_dir']+'/'+mk_prjpath(project_name, version_name)+'/config/scram_version').readline().strip()
def scram_tar_file_name(project_name, version_name):
return 'SCRAM_'+get_scram_version_for_project(project_name, version_name)+'.tar.gz'
def mk_prjname(project_name, version_name):
if version_name:
return project_name+'_'+version_name
else:
return version_name
def mk_prjpath(project_name, version_name):
return project_name+'/'+ mk_prjname(project_name,version_name)
def mk_tarball_name(project_name, version_name,platf=None):
return mk_release_name(project_name, version_name,platf)+".tar.gz"
def mk_release_name(project_name, version_name,platf=None):
if platf==None:
platf = CONFIG['platf']
return mk_prjname(project_name, version_name) + "__"+"LCG_"+platf
# relative path of the package in the external directory
def mk_package_path(package_name, version_name,platf):
return package_name+"/"+version_name+"/"+platf
def mk_scram_output_name(project_name, version_name):
return mk_prjname(project_name,version_name)+'.scram_output'
def mk_package_info_name(project_name, version_name):
return mk_release_name(project_name, version_name)+'.info'
def mk_specfile_name(pname,vname):
return mk_release_name(pname,vname)+'-1.spec'
# generate a spec file into SPECS subdirectory
# pinstall_dir and make_ppath allow to reuse this function for both LCG projects
# and external packages
def make_rpm_spec_file(pname,vname, pinstall_dir, make_ppath):
prjname = mk_release_name(pname,vname)
ppath = make_ppath(pname,vname)
print "generating specfile for "+prjname
template_file = file(CONFIG['rpm_template_file'])
template = template_file.read()
template = template.replace('@FULL_PACKAGE_NAME@',prjname)
template = template.replace('@INSTALLATION_PREFIX@',pinstall_dir)
l = list_files(pinstall_dir+'/'+ppath)
l = l.replace('./','"%{prefix}/'+ppath+'/')
l = l.replace('\n','"\n')
spec_filename = CONFIG['rpm_prefix']+'/SPECS/'+mk_specfile_name(pname,vname)
sf = file(spec_filename,'w')
sf.write(template+l)
return spec_filename
# assume gzipped tarball is in distribution dir...
def make_rpm_build(pname,vname, pinstall_dir, make_ppath, keep_going):
prjname = mk_release_name(pname,vname)
ppath = make_ppath(pname,vname)
# copy tarball and add -1 suffix
tbn = mk_release_name(pname,vname)+'-1.tar'
rpm_tarball = CONFIG['rpm_prefix']+'/SOURCES/'+tbn
import shutil
shutil.copyfile(CONFIG['distribution_dir']+'/'+mk_tarball_name(pname,vname),rpm_tarball+'.gz')
if not exists(rpm_tarball):
if os.system('gunzip -f '+rpm_tarball+'.gz'):
if not keep_going:
sys.exit(2)
print "building RPM for ",mk_specfile_name(pname,vname)
cmd = 'cd '+CONFIG['rpm_prefix']+'/SPECS ; rpm -bb '+ mk_specfile_name(pname,vname)
print cmd
if 0: #os.system(cmd):
if not keep_going:
sys.exit(2)
return 1
# get file list recursively...
def list_files(dir):
cmd = "(cd "+dir+"; rm -f /tmp/ll; find . > /tmp/ll)"
#print cmd
if os.system(cmd):
return None
flist = file('/tmp/ll').read()
return flist[flist.find('\n')+1:] # remove the first line
def create_scram_output_file(project_name, version_name, dest_dir):
tmp_file = dest_dir+'/'+ mk_scram_output_name(project_name, version_name)
cmd = 'cd '+CONFIG['release_dir']+'/'+mk_prjpath(project_name, version_name)+ ';'
cmd += 'rm -f '+tmp_file+';'
cmd += CONFIG['scram_dir']+'/scram tool list > '+tmp_file+';'
if os.system('('+cmd+')'):
print "error executing commands: "+cmd
return None
return tmp_file
# get all files to be tarred for the project in the release area
# filtering out tmp and other release directories
def get_project_tar_input_files(project_name, version_name):
prj_dir = CONFIG['release_dir']+"/"+mk_prjpath(project_name,version_name)
flist, dlist = get_dir_list(prj_dir)
# some projects have a lot of temporary files and directories
if "tmp" in dlist:
dlist.remove("tmp")
# remove tar directories if existing
if "tar" in dlist:
dlist.remove("tar")
# remove all platform directories other than current one (CONFIG['platf'])
for p in CONFIG['lcg_known_platforms']:
if p != CONFIG['platf']:
for rp in get_related_platforms_list(project_name, version_name, p):
if rp in dlist:
dlist.remove(rp)
src_list = reduce(lambda x,y: x+y , map( lambda x: mk_prjpath(project_name,version_name)+"/"+x+" ", flist+dlist))
return src_list
# return a list of directories which correspond to given platform (and all its related platforms)
# which exist in the CONFIG['release_dir']
def get_related_platforms_list(project_name, version_name, platf):
prj_dir = CONFIG['release_dir']+"/"+mk_prjpath(project_name,version_name)
flist, dlist = get_dir_list(prj_dir)
rlist = []
for d in dlist:
if re.match('^'+platf+'(_.*$|$)',d): # directory name match with my platform name or plus _*
rlist.append(d)
return rlist
# scram tool info PACKAGE | grep _BASE will give the platform
def get_platform_for_package(package_name, project_name, version_name):
if package_name.upper() in CONFIG['lcg_project_list']:
return CONFIG['platf']
cmd = "cd "+CONFIG['release_dir']+'/'+mk_prjpath(project_name, version_name)+';'
cmd += "unset noclobber;"
cmd += CONFIG['scram_dir']+"/scram tool info "+package_name+' | grep _BASE > /tmp/lcgtmp2;'
if os.system('('+cmd+')') != 0:
print "WARNING: unable to read platform using 'scram tool info "+package_name+"'"
print "assuming default platform:"+CONFIG['platf']
return CONFIG['platf']
ll = file("/tmp/lcgtmp2",'r').readlines()
if len(ll)!=1:
print "ERROR: missing or multiple string _BASE found in the output of scram tool info"
print ll
sys.exit(2)
return ll[0].split('/')[-1].strip() # the last part of the path
#
# Get package dependency list
# by default run scram to obtain the list and save it in the file
# set from_file to true to read it from a file (for downloader)
def get_package_list(project_name, version_name, from_file=None):
"""
Get package list by running scram. NEW: we may mix platforms so platform is
specified for each package separately.
[scram_name, extsoft_name_string, extsoft_version_string, platform]
"""
#CONFIG['distribution_dir']+'/'+mk_scram_output_name(project_name,version_name)
if from_file:
# check if we use new scheme with .info files
info_fn = CONFIG['distribution_dir']+'/'+mk_package_info_name(project_name, version_name)
if exists(info_fn):
#parse .info file and return the list with platform information
return load_info_file(info_fn)
# check if we deal with old scheme (.scram_output files)
info_fn = CONFIG['distribution_dir']+'/'+mk_scram_output_name(project_name, version_name)
if exists(info_fn):
ll =_get_package_list_from_scram_output(info_fn,CONFIG['package_map_file'])
# add platform information
for l in ll:
l.append(CONFIG['platf'])
return ll
print "ERROR: unable to find the info file for this project"
return []
# get scram package list into a temp file
tmp_file = create_scram_output_file(project_name, version_name,"/tmp/")
if not tmp_file: sys.exit(2)
package_list = _get_package_list_from_scram_output(tmp_file,CONFIG['package_map_file'])
# read platform information for every package separately and append to package_list
for l in package_list:
l.append(get_platform_for_package(l[0],project_name, version_name))
return package_list
# load and return the package dependency list from .info file (see get_package_list)
def load_info_file(info_fn):
import xml.parsers.expat
dep_list = []
def start_element(name, attrs):
if name == 'package':
l = [attrs['scram_name'],attrs['spi_name'],attrs['spi_version'],attrs['arch']]
dep_list.append(l)
p = xml.parsers.expat.ParserCreate()
p.StartElementHandler = start_element
p.Parse(file(info_fn,'r').read())
return dep_list
# save package dependency list to .info file (see get_package_list)
def save_info_file(dep_list, info_fn, project_name, version_name):
f = file(info_fn,'w')
print >>f, ''
for l in dep_list:
print >>f, ' '
print >>f, ''
# equivalence relation
def equiv(p,q):
return (p and q) or (not p and not q)
import stat
# check if file exists
# optional arguments add more constraints on a type of the file
# directory=true|false
def exists(file,**kwds):
try:
mode = os.stat(file)[stat.ST_MODE]
if "directory" in kwds:
return equiv(stat.S_ISDIR(mode), kwds["directory"])
return 1
except OSError:
return None
# return a (file_list, directory_list)
def get_dir_list(dir):
flist, dlist = [],[]
entry_list = None
try:
entry_list = os.listdir(dir)
except Exception, x:
return (flist,dlist)
for f in entry_list:
pathname = '%s/%s' % (dir, f)
try:
mode = os.stat(pathname)[stat.ST_MODE]
except Exception,x:
print str(x)
continue
if stat.S_ISDIR(mode):
if f != "CVS":
dlist.append(f)
elif stat.S_ISREG(mode):
flist.append(f)
else:
# Unknown file type, print a message
print "Skipping irregular file "+pathname
return (flist,dlist)
import urllib, string, stat
# download files over http
# override == 0 : never override any files
# override == 1 : override if files differ in length
# override > 1 : always override
# download files over http
def fetch(tarFileName, targetDir=None, downloadURL = "", override=0, silent=0):
if not targetDir:
targetDir = CONFIG['prefix']
if downloadURL == "":
downloadURL = CONFIG['lcg_repository_url']
tarFileURL = downloadURL + '/' + tarFileName
tarFiles = []
fileName = targetDir + '/'+tarFileName
if not silent:
print "fetching file: " + fileName,
if ( os.path.exists(fileName) ) :
# compare size here
inf = urllib.urlopen(tarFileURL).info()
label = 'Content-Length:'
filesize = -1
for h in inf.headers:
if h.find(label) != -1:
filesize = int(h[len(label):].strip())
break
if not silent:
print 'Size:',filesize,
if override > 1:
if not silent:
print "overriding...",
os.unlink(fileName)
else:
if override:
if filesize != os.stat(fileName)[stat.ST_SIZE]:
if not silent:
print "file has different size, overriding...",
os.unlink(fileName)
else:
if not silent:
print "Local file of the same size already exists"
else:
if not silent:
print "file already fetched "
tarFiles.append(tarFileName)
return 1
if not os.path.exists(fileName):
(fileNameRet, info) = urllib.urlretrieve (tarFileURL, fileName)
if (info.gettype() == "text/html") :
tmpFile = open(fileNameRet)
tmpTxt = tmpFile.readlines()
tmpFile.close()
if ( string.find( str(tmpTxt), "404 Not Found" ) != -1 ) :
if silent < 2:
print "\nERROR: could not download the file :", tarFileName
os.remove(fileName)
return 0
if not silent:
print "ok"
return 1
def HTMLMarkup(text,link=None,bold=None,tt=None,italic=None):
buf = text
# generate prefix
if link:
buf = ''+buf
if bold:
buf = ''+buf
if tt:
buf = ''+buf
if italic:
buf = ''+buf
# generate suffix
if italic:
buf = buf+''
if tt:
buf = buf+''
if bold:
buf = buf + ''
if link:
buf = buf+''
return buf
class HTMLWriter:
def __init__(self):
self.ostr = ""
def beginDocument(self,title):
self.ostr = '''
''' + title + '''
'''
def endDocument(self):
self.ostr += '''
'''
def beginTable(self,cols):
self.ostr += '\n'
self.addRow(cols);
def endTable(self):
self.ostr += "\n
"
def addRow(self, cols):
self.ostr += "\n"
for c in cols:
self.ostr += "\n "+str(c)+" | "
self.ostr += "\n
"
def addParagraph(self,text):
self.ostr += "\n "+str(text)+ "
"
def addH1(self,text):
self.ostr += "\n "+str(text)+ "
"
def addH3(self,text):
self.ostr += "\n "+str(text)+ "
"
def addRawText(self,text):
self.ostr += text
def buffer(self):
return self.ostr
def createHTMLDocumentFromTemplateFile(body_text, template_file_name):
tf = file(template_file_name)
txt_out = reduce(lambda x,y: x+y, tf.readlines())
return txt_out.replace("", body_text)
prj_printed = None
def check_project_name(project_name, version_name):
global prj_printed
if not project_name:
usage()
print "ERROR: missing project name"
sys.exit(2)
else:
if not prj_printed:
print "Project name: ", project_name
print "Project version: ", version_name
prj_printed = 1
arch_printed = None
def check_arch():
global arch_printed
try:
CONFIG['platf'] = os.environ['SCRAM_ARCH']
except:
print "ERROR: undefined platform"
print "ERROR: please use --arch option or set SCRAM_ARCH environment variable"
print "hint: you do not need full SCRAM environment if you are doing download"
sys.exit(-2)
if not arch_printed:
print "Architecture/platform:", CONFIG['platf']
arch_printed = 1
## # replace all occurences of 'text' by 'replacement' in 'file_in' and write to 'file_out'
## def replace_strings(file_in, file_out, text, replacement):
## fout = file(file_out,'w')
## lines = file(file_in,'r').readlines()
## for l in lines:
## fout.write(l.replace(text,replacement))
## def mk_scram_runtime_file_name(project_name, version_name, shell):
## return project_name+"_"+version_name+'_'+CONFIG['platf']+'.scram.runtime.'+shell
import sys, getopt, os
if __name__ == '__main__':
os.environ['PATH'] += ":." # for sh -- recursive call to the same script
try:
opts, args = getopt.getopt(sys.argv[1:], ":vk", ["prefix=","project=", "verbose=","keep-going","arch=","clean-tar=","dereference","distribution=","always-fetch"])
except getopt.GetoptError, x:
print "command line syntax error"
usage()
sys.exit(2)
project_name = ""
version_name = ""
keep_going = None
clean_tar = "no"
deref_tar = None
inherit_options = ""
# by default override if different length...
override = 1
for o,a in opts:
if o in ("--project",):
idx = a.find("_")
if idx == -1:
project_name = a
else:
project_name = a[:idx]
version_name = a[idx+1:]
if o in ("--prefix",):
CONFIG['lcg_prefix'] = a
inherit_options += ' --prefix='+a
if o in ("-k","--keep-going"):
keep_going = 1
inherit_options += ' --keep-going'
if o in ("--arch",):
os.environ['SCRAM_ARCH'] = a
inherit_options += ' --arch='+a
if o in ("--clean-tar",):
clean_tar = a
inherit_options += ' --clean-tar='+a
if o in ("--dereference",):
deref_tar = 1
inherit_options += ' --dereference'
if o in ("--distribution",):
CONFIG['distribution_location'] = a
inherit_options += ' --distribution='+a
if o == "--always-fetch":
override = 2
inherit_options += ' --always-fetch'
if len(args) == 0:
usage()
print "ERROR: specify one or more commands"
sys.exit(2)
# not every command requires a project name
#check_project_name(project_name, version_name)
configure()
print "LCG installation prefix: ", CONFIG['lcg_prefix']
print "LCG distribution directory (target): ", CONFIG['distribution_dir']
for a in args:
if a == "test":
dep_list = get_package_list(project_name, version_name)
save_info_file(dep_list,'/tmp/lcg-deplist.info', project_name, version_name)
dl2 = load_info_file('/tmp/lcg-deplist.info')
print "written /tmp/lcg-deplist.info"
if dep_list == dl2:
print "OK"
else:
print "ERROR: load/save loose data"
continue
if a == "list":
check_project_name(project_name, version_name)
check_arch()
print 'SCRAM VERSION REQUIRED: ', get_scram_version_for_project(project_name, version_name)
dep_list = get_package_list(project_name, version_name)
for l in dep_list:
print l
print "related platforms:", get_related_platforms_list(project_name, version_name,CONFIG['platf'])
continue
if a == "tar":
check_project_name(project_name, version_name)
check_arch()
display_once = 1
print "getting the dependency list...",
dep_list = get_package_list(project_name, version_name)
info_fn = CONFIG['distribution_dir']+'/'+mk_package_info_name(project_name, version_name)
print "saving the .info file: ",info_fn
save_info_file(dep_list,info_fn, project_name, version_name)
#if not ok:
# print "FATAL: unable to get the package list"
# sys.exit(2)
# verify the required version of scram is tarred in the scram directory
scram_tar_file = CONFIG['scram_dir']+'/tarfiles/'+scram_tar_file_name(project_name, version_name)
if not exists(scram_tar_file):
print "ERROR: cannot find ",scram_tar_file
if not keep_going:
sys.exit(2)
# make a symlink for the scram tar file in the distribution area
# remove the old one
scram_tar_link = CONFIG['distribution_dir']+'/'+scram_tar_file_name(project_name, version_name)
try:
os.remove(scram_tar_link)
except:
pass
try:
os.symlink(scram_tar_file,scram_tar_link)
except:
pass
# loop over dependant packages
for l in dep_list:
# if package is lcg-project then solve dependencies recursevly
if l[1] in CONFIG['lcg_project_list']:
cmd = 'lcg-installation-manager.py '+inherit_options+" --project="+l[2]
if keep_going:
cmd += ' --keep-going '
cmd += " tar"
print '--> recursive action for: ', l[2]
print cmd
if os.system(cmd) != 0:
print "error during system call"
if not keep_going:
sys.exit(2)
continue
tarname = mk_tarball_name(l[1],l[2],l[3]) #l[1]+"_"+l[2]+"__"+"LCG_"+CONFIG['platf']+".tar.gz"
package_path = mk_package_path(l[1],l[2],l[3]) #l[1]+"/"+l[2]+"/"+CONFIG['platf']
dest_tar = CONFIG['distribution_dir']+'/'+tarname
if exists(dest_tar):
print "### skipping ", l[1],"... tarball already exists in external/distribution"
else:
cd_cmd = "cd "+CONFIG['external_dir']
if deref_tar:
tar_cmd = "tar hczf "
else:
tar_cmd = "tar czf "
tar_cmd = tar_cmd+dest_tar+" "+package_path+'/*'
if display_once:
print cd_cmd
display_once = None
print tar_cmd
if os.system("("+cd_cmd+";"+tar_cmd+")") == 0:
print "OK"
else:
print "FAILED: removing tarball "+dest_tar
os.system("("+cd_cmd+"; rm -f "+dest_tar+")")
if not keep_going:
sys.exit(3)
tarname = mk_tarball_name(project_name, version_name)
dest_tar = CONFIG['distribution_dir']+'/'+tarname
if exists(dest_tar):
print "### skipping ",tarname,": tarball already exists in external/distribution"
else:
src_list = get_project_tar_input_files(project_name,version_name)
cd_cmd = 'cd '+CONFIG['release_dir']
if deref_tar:
tar_cmd = "tar hczf "
else:
tar_cmd = "tar czf "
tar_cmd = tar_cmd+dest_tar+' '+src_list
print cd_cmd
print tar_cmd
if os.system("("+cd_cmd+";"+tar_cmd+")") == 0:
print "OK"
else:
print "FAILED to create tarball "+tarname
if not keep_going:
sys.exit(3)
continue
if a == "rpm" :
check_project_name(project_name, version_name)
check_arch()
def success(x):
if not x and not keep_going:
sys.exit(2)
return x
success(make_rpm_spec_file(project_name, version_name, CONFIG['release_dir'], mk_prjpath))
success(make_rpm_build(project_name, version_name, CONFIG['release_dir'], mk_prjpath, keep_going))
for l in get_package_list(project_name, version_name):
# if package is lcg-project then solve dependencies recursevly
if l[1] in CONFIG['lcg_project_list']:
cmd = 'lcg-installation-manager.py '+inherit_options+" --project="+l[2]+' rpm'
print '--> recursive action for: ', l[2]
print cmd
if os.system(cmd) != 0:
print "error during system call"
if not keep_going:
sys.exit(2)
continue
success(make_rpm_spec_file(l[1],l[2],CONFIG['external_dir'],mk_package_path))
success(make_rpm_build(l[1],l[2],CONFIG['external_dir'],mk_package_path, keep_going))
continue
if a == "download":
check_project_name(project_name, version_name)
check_arch()
display_once = 1
if CONFIG['lcg_prefix']== '/afs/cern.ch/sw/lcg':
print "FATAL: cannot download into the main repository: ",CONFIG['lcg_prefix']
print "please change the prefix!"
sys.exit(-3)
print "LCG repository URL: ", CONFIG['lcg_repository_url']
if not exists(CONFIG['distribution_dir']):
os.makedirs(CONFIG['distribution_dir'])
if not exists(CONFIG['external_dir']):
os.makedirs(CONFIG['external_dir'])
if not exists(CONFIG['release_dir']):
os.makedirs(CONFIG['release_dir'])
if fetch('MAINTENANCE','/tmp/',override=2,silent=2): # be very silent
print file('/tmp/MAINTENANCE').read()
sys.exit(4)
if fetch('NEWS','/tmp/',override=2,silent=2): # be very silent
print file('/tmp/NEWS').read()
# support both old and new scheme...
if not fetch(mk_package_info_name(project_name, version_name), CONFIG['distribution_dir']+'/',override=1):
if not fetch(mk_scram_output_name(project_name,version_name), CONFIG['distribution_dir']+'/'):
print "Most probably", mk_prjname(project_name,version_name),
print ' is not available in the LCG software repository...'
print 'Please report this to LCG SPI'
sys.exit(3)
# always get the newest package map
if not fetch(CONFIG['package_map_file_name'],CONFIG['distribution_dir']+'/', override=2):
print "FATAL: exiting..."
sys.exit(3)
for l in get_package_list(project_name,version_name,from_file=1):
if l[1] in CONFIG['lcg_project_list']:
cmd = 'lcg-installation-manager.py '+inherit_options+" --project="+l[2]+" download"
print '--> recursive action for: ', l[2]
print cmd
if os.system(cmd) != 0:
print "error during system call"
if not keep_going:
sys.exit(2)
continue
print "downloading: ",l
tarname = mk_tarball_name(l[1],l[2],l[3]) #l[1]+"_"+l[2]+"__"+"LCG_"+CONFIG['platf']+".tar.gz"
package_path = mk_package_path(l[1],l[2],l[3]) #l[1]+"/"+l[2]+"/"+CONFIG['platf']
dest_tar = CONFIG['distribution_dir']+'/'+tarname
if 0 and exists(dest_tar): # DISABLED
print "### skipping ", l[1],"... tarball already exists in external/distribution"
else:
if not fetch(tarname,CONFIG['distribution_dir']+'/',override=override):
if not keep_going:
sys.exit(3)
cd_cmd = "cd "+CONFIG['external_dir']
tar_cmd = "tar xfz "+dest_tar
if display_once:
print cd_cmd
display_once = None
print tar_cmd
if os.system("("+cd_cmd+";"+tar_cmd+")") == 0:
print "OK"
if clean_tar == "all":
os.remove(CONFIG['distribution_dir']+'/'+tarname)
else:
print "FAILED"
sys.exit(3)
tarname = mk_tarball_name(project_name, version_name)
dest_tar = CONFIG['distribution_dir']+'/'+tarname
if 0 and exists(dest_tar): # DISABLED
print "### skipping ",tarname,": tarball already exists in external/distribution"
else:
if not fetch(tarname,CONFIG['distribution_dir']+'/',override=override):
sys.exit(3)
cd_cmd = 'cd '+CONFIG['release_dir']
tar_cmd = 'tar xfz '+dest_tar
print cd_cmd
print tar_cmd
if os.system("("+cd_cmd+";"+tar_cmd+")") == 0:
print "OK"
else:
print "FAILED"
sys.exit(3)
if clean_tar == "lcg" or clean_tar=="all":
os.remove(CONFIG['distribution_dir']+'/'+tarname)
if exists( CONFIG['scram_dir']+'/'+get_scram_version_for_project(project_name, version_name) ):
print get_scram_version_for_project(project_name, version_name)," already installed..."
else:
if not fetch(scram_tar_file_name(project_name, version_name),'/tmp/',override=override):
if not keep_going:
sys.exit(3)
if not fetch("SCRAM-install.sh",CONFIG['distribution_dir']+'/',override=override):
if not keep_going:
sys.exit(3)
print "INSTALLING SCRAM..."
cmd = "cd "+CONFIG['distribution_dir']+" ; "
cmd += "chmod +x SCRAM-install.sh ;"
cmd += "LCG_PREFIX="+CONFIG['lcg_prefix'] + " ; export LCG_PREFIX; "
cmd += "./SCRAM-install.sh "+get_scram_version_for_project(project_name, version_name)
if os.system('('+cmd+')') != 0:
if not keep_going:
sys.exit(3)
if not fetch("ProcessTools.sh", CONFIG['distribution_dir']+'/',override=override):
if not keep_going:
sys.exit(3)
once = 1
# modify SCRAM tool files with the local prefix for all our platforms
# however need to do scram install once only!
for platf in get_related_platforms_list(project_name,version_name,CONFIG['platf']):
processToolsCmd = CONFIG['distribution_dir']+"/ProcessTools.sh"
cmd = "chmod +x "+processToolsCmd+" ;"
cmd += "cd "+CONFIG['release_dir']+"/"+mk_prjpath(project_name,version_name)+" ;"
cmd += "chmod -R u+w .SCRAM;"
cmd += "LCG_PREFIX="+CONFIG['lcg_prefix'] + " ; export LCG_PREFIX; "
cmd += processToolsCmd+" "+platf+'; export SCRAM_ARCH='+platf+'; '
if once:
cmd += CONFIG['scram_dir']+'/scram install'
once=None
print 'executing: ' + cmd
if os.system('('+cmd+')') != 0:
if not keep_going:
sys.exit(3)
continue
if a == "diff":
check_arch()
import glob
locs = []
for l in glob.glob(CONFIG['distribution_dir']+'/*.scram_output'):
l2 = os.path.basename(l)
idx = l2.find('.scram_output')
locs.append(l2[:idx])
ff = "/tmp/lcg-soft-dir-listing.html"
if not fetch('',ff,CONFIG['lcg_repository_url'], override=2,silent=1):
sys.exit(1)
f = open(ff)
print 'Local installation diff summary:'
empty = 1
for l in map(lambda x: x.split('"'),f.readlines()):
if len(l) > 5:
idx = l[5].find('.scram_output')
if idx > 0:
prj = l[5][:idx]
if not prj in locs:
empty = 0
print prj, "needs download"
if empty:
print '---'
continue
if a == "html":
check_project_name(project_name, version_name)
check_arch()
out_file_name = CONFIG['website_dir']+'/'+mk_prjname(project_name,version_name).strip()+'_'+CONFIG['platf']+'-download.html'
print "writing to file: "+out_file_name,
if exists(out_file_name):
print " already exists, overriding..."
else:
print
out_file = file(out_file_name,"w")
writer = HTMLWriter()
markup = HTMLMarkup
t = 'Download page for '+ mk_prjname(project_name,version_name) + " / " + CONFIG['platf']
# no header or footer -- the contents will be intersted into the template
#writer.beginDocument(t)
writer.addH1(t)
writer.addH3('Automatic download')
writer.addParagraph('On the machine where you want to install the software run the following command: ')
writer.addParagraph(markup('./lcg-installation-manager.py --project='+mk_prjname(project_name,version_name)+' --arch='+CONFIG['platf']+' --prefix=/opt/sw/lcg download',tt=1))
writer.addParagraph('Python 2.2 or greater is required. Download the script here: '+markup('lcg-installation-manager.py',link=CONFIG["lcg_repository_url"]+'/'+'lcg-installation-manager.py')+' '+ markup('Make sure you read Local Installation HOWTO',bold=1,link='http://spi.cern.ch/workbook/howto/HowTo-Install-locally-lcg-software.html'))
writer.addH3('Manual download')
#writer.addParagraph('Release platform '+markup(CONFIG['platf'],bold=1)+" : ")
writer.addParagraph(markup(mk_tarball_name(project_name,version_name),
link=CONFIG["lcg_repository_url"]+'/'+mk_tarball_name(project_name,version_name),
bold =1))
writer.addParagraph('Required packages:')
writer.beginTable(map(lambda x: markup(x,bold=1),["name","version","download"]))
writer.addRow([markup("SCRAM",italic=1),
markup(get_scram_version_for_project(project_name, version_name),italic=1),
markup(scram_tar_file_name(project_name, version_name),link=CONFIG["lcg_repository_url"]+'/'+scram_tar_file_name(project_name, version_name))])
for l in get_package_list(project_name, version_name):
if l[1] in CONFIG['lcg_project_list']:
cmd = 'lcg-installation-manager.py '+inherit_options+" --project="+l[2]+" html"
print '--> recursive action for: ', l[2]
print cmd
if os.system(cmd) != 0:
print "error during system call"
if not keep_going:
sys.exit(2)
writer.addRow([markup(l[1],bold=1),markup(l[2],bold=1),markup('download page',link=CONFIG["lcg_website_url"]+'/'+l[2]+'_'+CONFIG['platf']+'-download.html')])
continue
else:
tarname = mk_tarball_name(l[1],l[2],l[3])
if exists(CONFIG['distribution_dir']+'/'+tarname):
writer.addRow([l[1],l[2],markup(tarname,link=CONFIG["lcg_repository_url"]+'/'+tarname)])
else:
print "tarball "+tarname+" not found in the distribution area"
writer.addRow([l[1],l[2],markup("use original distribution kit",italic=1)])
writer.endTable()
#writeHTMLFile(out_file,writer.buffer(), CONFIG['html_template_file'])
#writer.endDocument()
out_file.write(createHTMLDocumentFromTemplateFile(writer.buffer(),CONFIG['html_template_file']))
continue
if a == "help":
help_str = """
RPM Building:
These instructions as well as spec file template are based on LCG1 depolyment team recommendations.
1. Dowload the project with lcg-installation-manager.py
% lcg-installation-manager.py --arch=rh73_gcc32 --project=POOL_1_3_2 --prefix=/opt/sw/lcg --clean-tar=lcg download
2. LCG sofwtare is now locally installed. Make tarball which will be RPM input:
% lcg-installation-manager.py --arch=rh73_gcc32 --project=POOL_1_3_2 --prefix=/opt/sw/lcg --keep-going tar
3. Make sure your ~/.rpmmacros contains:
%_fixperms true
%__os_install_post true
%__find_requires %{nil}
4. Download spec file template and copy it into:
% /opt/sw/lcg/external/distribution/package.spec.template
5. Generate RPM spec files and build RPMs Typically you need to be root to do that.
% lcg-installation-manager.py --arch=rh73_gcc32 --project=POOL_1_3_2 --prefix=/opt/sw/lcg rpm
"""
print help_str
continue
print "command ",a," ignored..."