#!/usr/bin/env python """ Installation Wizard launching script. This script is the part of the SALOME installation procedure. Author : Vadim SANDLER, Open CASCADE SAS (vadim.sandler@opencascade.com) Created : Thu Dec 18 12:01:00 2002 Copyright : 2002-2014 CEA """ __version__ = "1.1.5" # --- imports --- # import sys try: import xml.sax, xml.dom.minidom import os, re import types import random import warnings except Exception, an_exc: sys.exit("Error: %s! Please check the installed Python package." % str(an_exc)) pass # --- avoid "deprecation" warnings --- # warnings.filterwarnings("ignore", "", DeprecationWarning) # --- global variables --- # opt_parser = None root_path = None # --- actions definition --- # __BINARIES__ = "install_binary" __BUILDSRC__ = "install_source_and_build" __PREINSTALL__ = "try_preinstalled" # --- product type definition --- # __CTX__COMPONENT__ = "component" __CTX__PREREQUISITE__ = "prerequisite" #------------------------------------------------------------------# # # # COMMAND LINE ARGUMENTS PARSER # # # #------------------------------------------------------------------# #=================================================================== # class OptBaseError : base parse error #=================================================================== class OptBaseError(Exception): """ Base option parsing exception class """ def __init__(self, msg): self.msg = msg def __str__ (self): return self.msg #=================================================================== # class OptError : bad option error #=================================================================== class OptError(OptBaseError): """ Bad option exception class """ def __init__ (self, msg, option): self.msg = msg self.option = option def __str__ (self): if self.option: opt_prs = "" if self.option.short_opt and self.option.long_opt: opt_prs = "%s/%s"%(self.option.short_opt,self.option.long_opt) elif self.option.short_opt: opt_prs = "%s"%(self.option.short_opt) elif self.option.long_opt: opt_prs = "%s"%(self.option.long_opt) return "option %s: %s"%(opt_prs, self.msg) return self.msg #=================================================================== # class ArgError : bad option argument error #=================================================================== class ArgError(OptBaseError): """ Bad argument exception class """ pass #=================================================================== # class ValError : bad command line parameter error #=================================================================== class ValError(OptBaseError): """ Bad parameter exception class """ pass #=================================================================== # class ArgOption : command line option #=================================================================== class ArgOption: """ Option class """ attrs = ["short_opt", "long_opt", "dest", "action", "type", "default", "metavar", "help"] actions = ["store", "store_true", "store_false"] types = ["string", "int", "float", "bool"] def __init__(self, *args, **kwargs): # set defaults for attr in self.attrs: setattr(self, attr, None) # parse arguments for i in range(len(args)): if i > len(self.attrs)-1: msg = "Wrong number of parameters is given (maximum is %d)" % len(self.attrs) raise OptBaseError(msg) setattr(self, self.attrs[i], args[i]) for arg in kwargs: if arg not in self.attrs: msg = "Invalid argument: %s" % arg raise OptBaseError(msg) setattr(self, arg, kwargs[arg]) # check short option key if self.short_opt and \ not re.match("^-[a-zA-Z]$",self.short_opt): msg = "invalid short option key; " msg += "should be of the form -x (x is letter)" raise OptError(msg, self) # check long option key if self.long_opt and \ not re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$",self.long_opt): msg = "invalid long option key; " msg += "should be of the form --word[[-word]...] " msg += "(word is letters and digits sequence)" raise OptError(msg, self) # check that at least one option key is defined if not self.short_opt and not self.long_opt: msg = "invalid option; neither short nor long option key is defined" raise OptError(msg, self) # destination if not self.dest and self.long_opt: self.dest = self.long_opt[2:].replace('-','_') if not self.dest and self.short_opt: self.dest = self.short_opt[1:] # action if not self.action: self.action = "store" if self.action not in self.actions: msg = "invalid action: %s" % self.action raise OptError(msg, self) # type if not self.type: if self.action in ["store_true","store_false"]: self.type = "bool" else: self.type = "string" if self.type not in self.types: msg = "invalid type: %s" % self.type raise OptError(msg, self) if self.action in ["store_true","store_false"] and self.type != "bool": msg = "invalid type: %s : should be 'bool' or None" % self.type raise OptError(msg, self) # default if self.default is not None: try: if self.type == "string": self.default = str(self.default) if self.type == "int": self.default = int(self.default) if self.type == "float": self.default = float(self.default) if self.type == "bool": self.default = boolean(self.default) except : msg = "invalid default value type: should be %s" % self.type raise OptError(msg, self) pass # metavar if not self.metavar: self.metavar = self.dest.upper() # help if not self.help: self.help = "" pass def to_string(self): """ Returns string representation of the option """ opts = [] opt = self.short_opt if opt and self.action == "store" and self.metavar: opt += " %s" % self.metavar if opt: opts.append(opt) opt = self.long_opt if opt and self.action == "store" and self.metavar: opt += "=%s" % self.metavar if opt: opts.append(opt) return (", ").join(opts) #=================================================================== # class Values : resulting option values #=================================================================== class Values: """ Values class """ def __init__(self): pass #=================================================================== # class ArgParser : command line arguments parser #=================================================================== class ArgParser: """ Arguments parser class """ def __init__(self): self.options = [] pass def add_option(self, *args, **kwargs): """Register an option""" o = ArgOption(*args, **kwargs) self._check_option(o) self.options.append(o) pass def parse_args(self, args = None): """Parse an arguments""" if not args: args = sys.argv[1:] values = Values() for o in self.options: if o.default is not None: setattr(values, o.dest, o.default) elif not hasattr(values,o.dest): setattr(values, o.dest, None) try: (values, args) = self._process_args(values, args) except (ArgError, ValError), e: self._error(e.msg) return (values, args) def print_usage(self): """Print usage""" print "usage: %s [options]" % os.path.basename(sys.argv[0]) pass def print_help(self): """Print help""" self.print_usage() print "" olen = 0 _maxwidth, _indent = 79, 2 if len(self.options): for option in self.options: if olen < len(option.to_string()): olen = len(option.to_string()) print "options:" for option in self.options: strings = [] for hs in option.help.split("\n"): s = "" for w in hs.split(): if len("%s %s" % (s,w)) > _maxwidth: strings.append(s.strip()); s = "" s = "%s %s" % (s,w) if s.strip(): strings.append(s.strip()) if not strings: strings[:0] = [""] print "%s%s%s" % (option.to_string(), " "*(_indent+olen-len(option.to_string())), strings[0]) for i in range(1, len(strings)): print "%s%s" % (" "*(olen+_indent), strings[i]) pass def _check_option(self, option): o = self._get_option(option.short_opt) if not o: o = self._get_option(option.long_opt) if o: msg = "option conflicts with previously defined option(s)" raise OptError(msg, option) pass def _get_option(self, opt_key): if opt_key: for o in self.options: if opt_key in [o.short_opt, o.long_opt]: return o return None def _error(self, msg): self.print_usage() sys.exit("\n%s: error: %s\n" % (os.path.basename(sys.argv[0]), msg)) pass def _check_value(self, option, value): o = self._get_option(option) try: if o.type == "string": return str(value) if o.type == "int": return int(value) if o.type == "float": return float(value) if o.type == "bool": return boolean(value) except: msg = "invalid value type for option %s: %s; " % (option, value) msg += "should be %s" % o.type raise ValError(msg) raise OptBaseError("unknown error") def _process_args(self, values, args): res_args = [] cur_opt = None rargs = [] for index in range(len(args)): a = args[index] if cur_opt and cur_opt[1].action == "store": setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a)) cur_opt = None continue if a == "-": rargs = args[index+1:] break elif re.match("^-[a-zA-Z].*", a): for i in range(1,len(a)): if cur_opt and cur_opt[1].action == "store": setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a[i:])) cur_opt = None break o = self._get_option("-%s"%a[i]) if not o: raise ArgError("no such option: -%s"%a[i]) if o.action == "store_true": setattr(values, o.dest, True) elif o.action == "store_false": setattr(values, o.dest, False) else: cur_opt = ("-%s"%a[i], o) pass elif re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*", a): oname = ("%s="%a).split("=")[0] ovalue = ("%s="%a).split("=")[1] o = self._get_option(oname) if not o: raise ArgError("no such option: %s" % oname) if o.action == "store_true": if ovalue: raise ValError("option %s does not take a value" % oname) setattr(values, o.dest, True) elif o.action == "store_false": if ovalue: raise ValError("option %s does not take a value" % oname) setattr(values, o.dest, False) else: if ovalue: setattr(values, o.dest, self._check_value(oname, ovalue)) else: cur_opt = (oname, o) pass elif a.startswith("-"): raise ArgError("bad formatted option: %s" % a) else: rargs = args[index:] break if cur_opt and cur_opt[1].action == "store": raise ValError("option %s requires value" % cur_opt[0]) return (values, rargs) #------------------------------------------------------------------# # # # XML CONFIGURATION FILES PARSER # # # #------------------------------------------------------------------# #=================================================================== # class Config : general configuration options : version, target and # temporary directories, etc... #=================================================================== class Config : """ General configuration file options: - Install Wizard window caption - SALOME platform version - Copyright and license info - Default target and temporary directories - List of optional libraries for Salome """ def __init__(self, theVersion = None, theCaption = None, theCopyright = None, theLicense = None, thePlatforms = None, theTargetdir = None, theTmpdir = None, theOptLibs = None): self.version = strip(theVersion) self.caption = strip(theCaption) self.copyright = strip(theCopyright) self.license = strip(theLicense) self.platforms = strip(thePlatforms) self.targetdir = strip(theTargetdir) self.tmpdir = strip(theTmpdir) self.optlibs = strip(theOptLibs) #============================================================== # class Product : pre-requisite product options #============================================================== class Product : """ Product options: - name, version - target Linux OS version - dependencies - required disk space - installation script - etc... """ def __init__(self, theName, theType = None, theOS = None, theVersion = None, theDependencies = None, theWoGuiInstallation = None, theInstalldiskspace = None, theScript = None, thePickUpEnvironment = None): self.name = strip(theName) self.type = strip(theType) self.os = strip(theOS) self.version = strip(theVersion) self.dependencies = strip(theDependencies) self.woguiinst = strip(theWoGuiInstallation) self.installdiskspace = strip(theInstalldiskspace) self.script = strip(theScript) self.pickupEnv = strip(thePickUpEnvironment) self.whattodo = __BINARIES__ def setMode(self, mode): if mode not in [__BINARIES__, __BUILDSRC__, __PREINSTALL__]: return self.whattodo = mode return #=================================================================== # class ConfigParser : XML files parser implementation #=================================================================== class ConfigParser: """ XML configuration files parser """ def __init__(self, is_force_src=False, pltname=None): self.docElem = None self.products = [] self.full_prods_list = [] self.config = None self.is_force_src = is_force_src self.pltname = pltname pass def parse_config(self): # Parse 'config' part of the XML file configElem = self.docElem.getElementsByTagName('config')[0] self.config = Config(configElem.getAttribute('version').strip(), configElem.getAttribute('caption').strip(), configElem.getAttribute('copyright').strip(), configElem.getAttribute('license').strip(), configElem.getAttribute('platforms').strip(), configElem.getAttribute('targetdir').strip(), configElem.getAttribute('tempdir').strip(), configElem.getAttribute('optionallibs').strip()) if not self.pltname and self.config.platforms: self.pltname = self.config.platforms.split(",")[0].strip() pass def parse_dependencies(self): # Parse 'dependencies' part of the XML file depsMap = {} depsElem = self.docElem.getElementsByTagName('dependencies')[0] for prodElem in depsElem.getElementsByTagName('product'): prodName = prodElem.getAttribute('name').strip() if not prodName: continue depsList = [] for depElem in prodElem.getElementsByTagName('dep'): depsList.append(depElem.firstChild.data) pass depsMap[prodName] = depsList pass return depsMap def parse_product(self): # Parse 'products' part of the XML file depsMap = self.parse_dependencies() prodsElem = self.docElem.getElementsByTagName('products')[0] sal_prods_list = []; req_prods_list = [] modules_list = []; prereqs_list = [] for prodElem in prodsElem.getElementsByTagName('product'): prodName = prodElem.getAttribute('name').strip() if not prodName: continue instElems = prodElem.getElementsByTagName('installation') instElem = None for node in instElems: if not self.pltname or self.pltname == node.getAttribute('os').strip(): instElem = node break pass if not instElem: continue if check_bool(str(instElem.getAttribute('disable').strip())): continue depsList = [] if prodName in depsMap: depsList = depsMap[prodName] aProduct = Product(prodName, prodElem.getAttribute('type').strip(), instElem.getAttribute('os').strip(), instElem.getAttribute('version').strip(), depsList, instElem.getAttribute('woguimode').strip(), instElem.getAttribute('installdiskspace').strip(), instElem.getAttribute('script').strip(), instElem.getAttribute('pickupenv').strip()) if self.is_force_src: aProduct.setMode(__BUILDSRC__) pass if prodElem.getAttribute('type').strip() == "component": sal_prods_list.append(aProduct) # fill an ordered modules list ----------- modules_list.append(prodName) modules_list.append(prodName + "_src") pass else: #prerequisite req_prods_list.append(aProduct) # fill an ordered prerequisites list ----------- prereqs_list.append(prodName) #AKL: prerequisite sources and temp files are removed, by default. # So, there is no need to make sources environment #if aProduct.whattodo == __BUILDSRC__: prereqs_list.append(prodName + "_src") pass pass self.products.extend( req_prods_list ) self.products.extend( sal_prods_list ) if len(self.products) != 0: gcc_product = Product("gcc", __CTX__PREREQUISITE__, self.products[0].os, "", [], None, "0,0,0", "gcc-common.sh", "") gcc_product.setMode(__PREINSTALL__) self.products.insert(0, gcc_product) prereqs_list.insert(0, gcc_product.name) pass self.full_prods_list.extend( prereqs_list ) self.full_prods_list.extend( modules_list ) pass def parse(self, xml_file): filehandle = open(xml_file) sax_parser = xml.sax.make_parser() doc = xml.dom.minidom.parse(filehandle, sax_parser) filehandle.close() self.docElem = doc.documentElement self.parse_config() self.parse_product() pass def getProduct(self, prod): for product in self.products: if product.name == prod: return product return None #------------------------------------------------------------------# # # # SERVICE FUNCTIONS # # # #------------------------------------------------------------------# #============================================================== # message: prints diagnostic information #============================================================== def message(msg): """ Prints diagnostic information. """ if msg.strip(): print ">>>", msg pass #============================================================== # warning: prints warning #============================================================== def warning(msg): """ Prints warning. """ if msg.strip(): print "" print msg print "" pass #============================================================== # error_exit : prints (optionally) error string, then prints # help information and quits #============================================================== def error_exit(msg = "", print_help = True): """ Prints (optionally) error string, then prints help information and quits. """ # print error message if len(msg.strip()): print "" print msg print "" # print help information if print_help: global opt_parser if opt_parser: opt_parser.print_help() print "" # cleaning clean_all() # quit sys.exit(1); pass #============================================================== # boolean : Converts string to boolean value. #============================================================== def boolean(val): """ Converts string to boolean value if possible. Raises exception if wrong string is used. """ if isinstance(val, types.StringType): if val.strip().lower() in ["true", "yes", "ok"] : return True elif val.strip().lower() in ["false", "no", "cancel"] : return False else: raise TypeError("invalid boolean value") return bool(val) #================================================================= # check_bool : checks boolean value: yes/no, true/false, 1/0 #================================================================= def check_bool(val): """ Checks boolean value. """ try: return boolean(val) except: pass return False #============================================================== # clean_all : performs system cleaning before exiting #============================================================== def clean_all(): """ Performs system cleaning before exiting. """ global root_path remove_dir(root_path) pass #============================================================== # parse_parameters : parses command line arguments #============================================================== def parse_parameters(): """ Parses command line arguments. """ global opt_parser opt_parser = ArgParser() help_str = "Runs the Installation Wizard in the GUI mode [default].\n" opt_parser.add_option("-g", "--gui", action="store_true", dest="gui", default=True, help=help_str) help_str = "Runs the Installation Wizard in the TUI mode." opt_parser.add_option("-b", "--batch", action="store_false", dest="gui", help=help_str) help_str = "The configuration xml file.\n" help_str += "If this parameter is missing, then the program tries to define the " help_str += "Linux platform and use the corresponding xml file. For example, " help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case. " opt_parser.add_option("-f", "--file", action="store", dest="xmlfile", metavar="FILE", help=help_str) help_str = "The platform specification.\n" help_str += "This option can be used in conjunction with --file option in order" help_str += "to specify Linux platform name when XML file contains installation" help_str += "options for several platforms." opt_parser.add_option("-p", "--platform", action="store", dest="platform", metavar="PLT", help=help_str) help_str = "The target directory the products to be installed to.\n" help_str += "When used this parameter overrides the default target directory " help_str += "defined in the configuration xml file." opt_parser.add_option("-d", "--target", action="store", dest="target_dir", metavar="DIR", help=help_str) help_str = "The directory to be used for temporary files.\n" help_str += "When used this parameter overrides the default temporary directory " help_str += "defined in the configuration xml file." opt_parser.add_option("-t", "--tmp", action="store", dest="tmp_dir", metavar="DIR", help=help_str) help_str = "Force all products to be installed from sources \n" help_str += "including SALOME modules.\n" help_str += "If this option is used all the default installation modes are ignored." opt_parser.add_option("-a", "--all-from-sources", action="store_true", dest="force_sources", default=False, help=help_str) help_str = "Install all SALOME binaries packages to one directory.\n" help_str += "This option is ignored when --all-from-sources (-a) option is used." opt_parser.add_option("-s", "--single-directory", action="store_true", dest="single_dir", default=False, help=help_str) help_str = "Prints version information and quits." opt_parser.add_option("-v", "--version", action="store_true", help=help_str) help_str = "Prints this help and quits." opt_parser.add_option("-h", "--help", action="store_true", help=help_str) (options, args) = opt_parser.parse_args() if options.help: # print help info and quit print "\nSALOME Installation Wizard (running on %s)\n" % get_os_name() opt_parser.print_help() print "" sys.exit(0) if options.version: # print version info and quit print "" cmd = "./bin/SALOME_InstallWizard --version" os.system(cmd) print "" sys.exit(0) return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui, options.force_sources, options.single_dir, options.platform] #================================================================= # strip : removes spaces at the beginning and at the end of the # if it is of string type #================================================================= def strip(param): """ Removes spaces at the beginning and at the end of the given parameter. """ if type(param) == types.StringType: return param.strip() return param #================================================================= # get_dependencies : extract products dependencies #================================================================= def get_dependencies(prods): """ Gets a list of installed and required products. """ prods_list = [] for product in prods: for dep in product.dependencies: if dep and dep not in prods_list: prods_list.append( dep ) dep_name = dep if product.whattodo == __BUILDSRC__: dep_name = dep + "_src" if dep_name not in parser.full_prods_list: msg = "Prerequisite '%s' is required for '%s' product,\n"%(dep, product.name) msg += "but the first one is absent in the list of products to be installed!\n" msg += "Please check your XML file." warning(msg) if product.name and product.name not in prods_list: prods_list.append( product.name ) return " ".join( prods_list ) #============================================================== # create_dir : creates a directory with (optional) permissions, # returns the part of path that existed before # directory creation; exits with error if access # is denied #============================================================== def create_dir(directory, access = 0777): """ Creates a directory with (optional) permissions, returns the part of path that existed before directory creation; exits with error if access is denied. """ dirs = directory.split("/") existing = ""; dir = "" root = "" for subdir in dirs: if len(subdir) == 0: continue dir = "%s/%s"%(dir, subdir) if os.path.exists(dir): existing = dir else: try: os.mkdir(dir, access) except: error_exit("Can't create directory: %s.\nAccess is denied."%directory) if dir == "%s/%s"%(existing, subdir): root = dir return root #============================================================== # substituteVars : performes environment variables substistution # the given string; if varibale is not defined # it is substituted by the empty string #============================================================== def substituteVars(str): """ Performes environment variables substistution. """ str = os.path.expanduser(str) str = os.path.expandvars(str) return str #================================================================ # get_program_path : gets program's directory path # (and performs 'cd' command there) #================================================================ def get_program_path(): """ Returns the program directory path (and make this directory current). """ path = os.path.dirname(sys.argv[0]) if path: os.chdir(path) return os.getcwd() #================================================================ # check_dir : checks directory existence #================================================================ def check_dir(dir): """ Checks directory existence. """ if (os.path.islink(dir)): realpath = os.path.realpath(dir) if not os.path.exists(realpath): msg = "Invalid link %s.\nThe directory %s a link points to does not exist. Stopped..."%(dir,realpath) error_exit(msg, False) else: if not os.path.exists(dir): msg = "Directory %s does not exist. Stopped..."%dir error_exit(msg, False) pass #=============================================================== # check_disk_space : checks the disk space; # quits if there is no enough disk space #=============================================================== def check_disk_space(products, scripts_dir, target_dir, tmp_dir, is_force_src=False): """ Checks if there is enough disk space to install products. Quits with error if there is no enough disk space. """ install_space = 0 temporary_space = 0 for product in products: prod_space = 0 try: spaces = product.installdiskspace.split(',') prod_space = int( spaces[0] ) if product.whattodo == __BINARIES__: prod_space = int( spaces[0] ) if product.type == __CTX__COMPONENT__: prod_space += int( spaces[1] ) else: if product.type == __CTX__PREREQUISITE__: prod_space = int( spaces[0] ) else: prod_space = int( spaces[2] ) except: pass install_space = install_space + prod_space pass res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", target_dir, install_space)) if res: msg = "There is no enough space to install the products. Stopped..." error_exit(msg, False) pass #=============================================================== # remove_dir : removes temporary directory #=============================================================== def remove_dir(path): """ Removes temporary directory. """ if path and os.path.exists(path): os.system("rm -rf " + path) pass #============================================================== # has_binaries : returns True if some product is installed from # binaries #=============================================================== def has_binaries(products): """ Returns True if some product is installed in 'binaries' mode. """ for product in products: if product.whattodo == __BINARIES__: return True return False #============================================================== # has_sources : returns True if some product is installed from # sources #=============================================================== def has_sources(products): """ Returns True if some product is installed in 'sources' mode. """ for product in products: if product.whattodo == __BUILDSRC__: return True return False #============================================================== # get_tmp_dir : gets temporary directory name #=============================================================== def get_tmp_dir(dir): """ Gets temporary directory path. """ max_attempts = 100 dir_prefix="INSTALLWORK" range_bottom = 0; range_top = 999999 for i in xrange(max_attempts): tmp_dir = "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top)) if not os.path.exists( tmp_dir ): return tmp_dir return "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top)) #============================================================== # get_os_release : gets OS release; the OS name, version and # architecture # For example: # RedHat, 8.0; Mandriva, 2006.0, 64 #=============================================================== def get_os_release(): filename = "/etc/issue" # --- plt_name = "unknown" plt_ver = "" plt_arch = "" if os.path.exists(filename): # --- f = open(filename) lines = f.readlines() f.close() # --- regvar = re.compile("(.*)\s+[^\s]*[R|r]elease[^\s]*\s+([\d.]*)") regvar1 = re.compile("(.*)\s+[^\s]*[L|l][I|i][N|n][U|u][X|x][^\s]*(.*)\s+([\d.]*)\s+") regvar2 = re.compile("([A-Za-z]+)\s+([0-9.]+)\s+.*") for l in lines: res = re.search(regvar, l) if not res: res = re.search(regvar1, l) if not res: res = re.search(regvar2, l) if res: plt_name = " ".join(" ".join(res.groups()[:len(res.groups())-1]).split()) # workaround for Mandrake and other platforms plt_name = plt_name.replace("Linux", "").replace("linux", "").replace("LINUX", "").strip() # workaround for SuSe plt_name = plt_name.replace("Welcome to", "").strip() # --- plt_name = " ".join(plt_name.split()) plt_ver = res.group(len(res.groups())) if re.search(r'x86_64', l): plt_arch = "64bit" pass # workaround for Red Hat Enterprise if not plt_arch: try: import platform if platform.machine() == "x86_64": plt_arch = "64bit" pass pass except: pass pass break pass pass return plt_name, plt_ver, plt_arch #============================================================== # get_os_name : gets qualified OS name # For example: # Mandriva 2010.0 64bit #=============================================================== def get_os_name(): plt_name, plt_ver, plt_arch = get_os_release() data = [] for i in plt_name, plt_ver, plt_arch: if i: data.append(i) return " ".join(data) #============================================================== # check_xml_file : checks XML file existence and readability #=============================================================== def check_xml_file(xml_file): """ Checks XML file existence and readability. """ if not os.path.isfile(xml_file): msg = "Configuration file %s is not found!"%xml_file error_exit(msg, False) if not os.access(xml_file, os.R_OK): msg = "There is no read access for %s file!"%xml_file error_exit(msg, False) pass #============================================================== # get_supported_plts : gets map of supported Linux platforms and # corresponding configuration files #=============================================================== def get_supported_platforms(xml_file=None): """ Gets map of supported Linux platforms and corresponding configuration files. """ platforms_map = {} if xml_file: xml_file_list = [xml_file] pass else: xml_file_list = filter(lambda i: i.endswith(".xml"), os.listdir(get_program_path())) while 'config.xml' in xml_file_list: xml_file_list.remove('config.xml') if os.path.exists(os.path.join(get_program_path(), 'config.xml')): xml_file_list.append('config.xml') xml_file_list = [os.path.abspath(i) for i in xml_file_list] pass for an_xml_file in xml_file_list: # XML files parsing check_xml_file(an_xml_file) parser = ConfigParser() parser.parse(an_xml_file) if parser.config.platforms is not None: for plt in parser.config.platforms.split(","): if not plt or plt in platforms_map.keys(): continue platforms_map[strip(plt)] = an_xml_file pass pass pass return platforms_map #============================================================== # Print menu with list of supported platform # and return user choice #=============================================================== def select_platform(all_platforms): platforms = all_platforms.keys() platforms.sort() pltname = None while not pltname: print "Please, select any platform from the list below." print "--------------------------" for idx in range(len(platforms)): print " %2d. %s" % (idx+1, " ".join(platforms[idx].split("_"))) print " 0. Exit" print "--------------------------" print "Type your choice (%d-%d) and press :" % (0, len(platforms)), try: idx = raw_input() except: sys.exit(1) try: idx = int(idx) except: warning("Invalid input!") pass if idx == 0: sys.exit(0) if idx > 0 and idx <= len(platforms): pltname = platforms[idx-1] else: warning("Invalid input!") pass return pltname, all_platforms[pltname] #============================================================== # Check existence of required libraries in system and # warn user if some ones are absent #=============================================================== def check_not_found_libs(filepath, optlibs): a_file = open(filepath, 'r') nf_mand_libs = list() nf_opt_libs = list() pref_opt_libs = optlibs.split(",") for line in a_file: line = line.strip() if not line: continue line = line.split(" ")[0] if line in nf_mand_libs or line in nf_opt_libs: continue is_optional = False; for opt_lib in pref_opt_libs: if line.lower().startswith(opt_lib.lower().strip()): is_optional = True break if is_optional: nf_opt_libs.append(line) else: nf_mand_libs.append(line) pass msg = "=== WARNING: Some libraries are absent! ===\n" if nf_mand_libs: msg += "One or several MANDATORY libraries listed below are not found. SALOME may not work properly.\n\t" msg += "\n\t".join(nf_mand_libs) msg += "\n" if nf_opt_libs: msg += "One or several OPTIONAL libraries listed below are not found. This does not affect on the correct work of SALOME platform.\n\t" msg += "\n\t".join(nf_opt_libs) if nf_mand_libs or nf_opt_libs: print msg a_file.close() pass #------------------------------------------------------------------# # # # EXECUTION STARTS HERE # # # #------------------------------------------------------------------# if __name__ == "__main__": # get program dir cur_dir = get_program_path() # parse command line [xml_file, target_dir, tmp_dir, is_gui, is_force_src, is_single_dir, pltname] = parse_parameters() if xml_file: xml_file = os.path.abspath(xml_file) if target_dir: target_dir = os.path.abspath(target_dir) if tmp_dir: tmp_dir = os.path.abspath(tmp_dir) #---- GUI ---------------- if is_gui : env = os.environ if not env.has_key("PATH") : env["PATH"] = "" if not env.has_key("LD_LIBRARY_PATH") : env["LD_LIBRARY_PATH"] = "" env["LD_LIBRARY_PATH"] = "./bin/lib:" + ".:" + env["LD_LIBRARY_PATH"] env["PATH"] = ".:" + env["PATH"] cmd = "./bin/SALOME_InstallWizard" if xml_file is not None: cmd += " --file %s"%xml_file if pltname is not None: cmd += " --platform %s"%pltname if target_dir is not None: cmd += " --target %s"%target_dir if tmp_dir is not None: cmd += " --tmp %s"%tmp_dir if is_force_src: cmd += " --all-from-sources" if is_single_dir: cmd += " --single-directory" cmd += "&" sys.exit(os.system(cmd)) #----- TUI --------------------- # # define xml file to be used # # get current Linux platform plt_name, plt_ver, plt_arch = get_os_release() data = [] for i in plt_name, plt_ver, plt_arch: if i: data.append(i) full_plt_name = " ".join(data) # get all supported platforms all_platforms = get_supported_platforms(xml_file) if all_platforms: if pltname: # platform name is specified in the command line if pltname in all_platforms: # if specified platform is supported, choose the corresponding XML file for use xml_file = all_platforms[pltname] else: # if specified platform is NOT supported, print warning message # and prompt user to choose another platform msg = "Specified platform is not supported: %s" % (pltname) warning(msg) pltname, xml_file = select_platform(all_platforms) pass pass elif full_plt_name in all_platforms: # if current platform is supported, choose the corresponding XML file for use pltname = full_plt_name xml_file = all_platforms[pltname] else: if xml_file and len(all_platforms) == 1: # XML file is specified and contains only one platform definition xml_file = all_platforms.values()[0] pltname = all_platforms.keys()[0] else: # current Linux platform is not supported, print warning message # and prompt user to choose platform from the list warning("Not supported Linux platform: %s."%" ".join(data)) pltname, xml_file = select_platform(all_platforms) pass pass else: # current Linux platform is not supported, exit if pltname: msg = "Not supported Linux platform: %s."%pltname else: msg = "Not supported Linux platform: %s."%" ".join(data) error_exit(msg, False) pass # parse XML file ----------- message("Parsing XML configuration file: %s"%xml_file) parser = ConfigParser(is_force_src, pltname) parser.parse(xml_file) # source directory map bin_dir = "" if parser.config.platforms: bin_dir += "/%s"%"_".join( parser.pltname.split() ) subdir = { __BINARIES__ : "BINARIES" + bin_dir, __BUILDSRC__ : "SOURCES", __PREINSTALL__ : ""} # check scripts directory ----------- scripts_dir = "%s/%s"%(cur_dir, "config_files") check_dir(scripts_dir) # check products archives directories ----------- has_bin = has_binaries(parser.products) has_src = has_sources(parser.products) source_dir = "%s/%s"%(cur_dir, "Products") if has_src or has_bin: check_dir(source_dir) if has_src: check_dir("%s/%s"%(source_dir,subdir[__BUILDSRC__])) if has_bin: check_dir("%s/%s"%(source_dir,subdir[__BINARIES__])) # check/create target dir ----------- if target_dir is None: target_dir = parser.config.targetdir target_dir = substituteVars(target_dir) message("Creating target directory: " + target_dir) create_dir(target_dir, 0755) if not os.path.exists(target_dir): error_exit("Invalid target directory: " + target_dir) if not os.access(target_dir, os.W_OK) : error_exit("There is no write permissions for the directory: " + target_dir) # check/create temporary dir ----------- if tmp_dir is None: tmp_dir = parser.config.tmpdir if not tmp_dir: tmp_dir = "/tmp" tmp_dir = substituteVars(tmp_dir) tmp_dir = get_tmp_dir(tmp_dir) message("Creating temporary directory: " + tmp_dir) root_path = create_dir(tmp_dir, 0755) if not os.path.exists(tmp_dir): error_exit("Invalid temporary directory: " + tmp_dir) if not os.access(tmp_dir, os.W_OK) : error_exit("There is no write permissions for the directory: " + tmp_dir) # check available disk space ----------- message("Checking available disk space") check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir, is_force_src) # change current directory ----------- os.chdir(scripts_dir) # get dependencies list ----------- list_of_dep = get_dependencies(parser.products) products_string = " ".join(parser.full_prods_list) # don't remove sources and tmp files, by default ----------- rm_src_tmp = "FALSE" # starting ----------- message("Starting ...") # install products ----------- for product in parser.products: # remove only prerequisites temporary files if product.type == __CTX__PREREQUISITE__ or \ (product.type == __CTX__COMPONENT__ and product.whattodo == __BUILDSRC__): rm_src_tmp = "TRUE" message("... processing %s ..."%product.name) cmd = '%s/%s %s %s %s/%s %s "%s" %s "%s" %s/%s %s %s/%s' % ( scripts_dir, product.script, product.whattodo, tmp_dir, source_dir, subdir[product.whattodo], target_dir, products_string, product.name, products_string, source_dir, subdir[__BUILDSRC__], rm_src_tmp, source_dir, subdir[__BINARIES__] ) # install all modules with GUI if product.woguiinst is not None and product.woguiinst != "": cmd += ' TRUE' # use single directory or not if product.whattodo == __BINARIES__ and product.type == __CTX__COMPONENT__ and is_single_dir: cmd += ' TRUE' res = os.system(cmd) rm_src_tmp = "FALSE" pass # pickup environment ----------- message("Creating environment files") for product in parser.products : if check_bool(product.pickupEnv): cmd = '%s/%s pickup_env %s %s/%s %s "%s" %s "%s" %s/%s %s %s/%s' % ( scripts_dir, product.script, tmp_dir, source_dir, subdir[product.whattodo], target_dir, products_string, product.name, products_string, source_dir, subdir[__BUILDSRC__], rm_src_tmp, source_dir, subdir[__BINARIES__] ) # install all modules with GUI if product.woguiinst is not None and product.woguiinst != "": cmd += ' TRUE' # use single directory or not if product.whattodo == __BINARIES__ and product.type == __CTX__COMPONENT__ and is_single_dir: cmd += ' TRUE' res = os.system(cmd) pass pass if not is_force_src: if is_single_dir: # modify *.la files, if --single-directory option was pointed ----------- message("Modifying of *.la files of SALOME modules...") cmd = '%s/modifyLaFiles.sh modify_la_files %s' % (scripts_dir, target_dir) res = os.system(cmd) else: # check that all required libraries are in system message("Check existence of Fortran and other required libraries...") cmd = '%s/checkFortran.sh find_libraries %s > %s/not_found_libs.txt' % (scripts_dir, target_dir, tmp_dir) if os.system(cmd): check_not_found_libs("%s/not_found_libs.txt" % (tmp_dir), parser.config.optlibs) # clean temporary directory ----------- message("Cleaning temporary directory") clean_all() # finishing ----------- message("Finished!") pass