Salome HOME
Implementation of hdf5-1.6.4 instead of hdf5-1.6.3
[tools/install.git] / runInstall
1 #!/usr/bin/env python
2
3 """
4 Installation Wizard launching script.
5
6 This script is the part of the SALOME installation procedure.
7 Author    : Vadim SANDLER, Open CASCADE SAS (vadim.sandler@opencascade.com)
8 Created   : Thu Dec 18 12:01:00 2002
9 Copyright : 2002-2006 CEA
10
11 """
12
13 __version__ = "1.0.1"
14
15 # --- avoid "deprecation" warnings --- #
16 import warnings
17 warnings.filterwarnings("ignore", "", DeprecationWarning)
18
19 # --- imports --- #
20 import xmllib
21 import sys, os, string, re
22 import types
23 import random
24
25 # --- global variables --- #
26 opt_parser = None
27 root_path  = None
28
29 # --- XML tags definition --- #
30 __TAG__SOURCES__    = "install sources"
31 __TAG__BINARIES__   = "install binaries"
32 __TAG__NATIVE__     = "use native"
33 __TAG__PREINSTALL__ = "not install"
34
35 #------------------------------------------------------------------#
36 #                                                                  #
37 #                 COMMAND LINE ARGUMENTS PARSER                    #
38 #                                                                  #
39 #------------------------------------------------------------------#
40
41 #===================================================================
42 # class OptBaseError : base parse error
43 #===================================================================
44 class OptBaseError(Exception):
45     """
46     Base option parsing exception class
47     """
48     def __init__(self, msg):
49         self.msg = msg
50     def __str__ (self):
51         return self.msg
52
53 #===================================================================
54 # class OptError : bad option error
55 #===================================================================
56 class OptError(OptBaseError):
57     """
58     Bad option exception class
59     """
60     def __init__ (self, msg, option):
61         self.msg = msg
62         self.option = option
63     def __str__ (self):
64         if self.option:
65             opt_prs = "<unknown>"
66             if self.option.short_opt and self.option.long_opt:
67                 opt_prs = "%s/%s"%(self.option.short_opt,self.option.long_opt)
68             elif self.option.short_opt:
69                 opt_prs = "%s"%(self.option.short_opt)
70             elif self.option.long_opt:
71                 opt_prs = "%s"%(self.option.long_opt)
72             return "option %s: %s"%(opt_prs, self.msg)
73         return self.msg
74
75 #===================================================================
76 # class ArgError : bad option argument error
77 #===================================================================
78 class ArgError(OptBaseError):
79     """
80     Bad argument exception class
81     """
82     pass
83
84 #===================================================================
85 # class ValError : bad command line parameter error
86 #===================================================================
87 class ValError(OptBaseError):
88     """
89     Bad parameter exception class
90     """
91     pass
92
93 #===================================================================
94 # class ArgOption : command line option
95 #===================================================================
96 class ArgOption:
97     """
98     Option class
99     """
100     attrs   = ["short_opt", "long_opt", "dest", "action", "type", "default", "metavar", "help"]
101     actions = ["store", "store_true", "store_false"]
102     types   = ["string", "int", "float", "bool"]
103     def __init__(self, *args, **kwargs):
104         # set defaults
105         for attr in self.attrs: setattr(self, attr, None)
106         # parse arguments
107         for i in range(len(args)):
108             if i > len(self.attrs)-1:
109                 msg = "Wrong number of parameters is given (maximum is %d)" % len(self.attrs)
110                 raise OptBaseError(msg)
111             setattr(self, self.attrs[i], args[i])
112         for arg in kwargs:
113             if arg not in self.attrs:
114                 msg = "Invalid argument: %s" % arg
115                 raise OptBaseError(msg)
116             setattr(self, arg, kwargs[arg])
117         # check short option key
118         if self.short_opt and \
119                not re.match("^-[a-zA-Z]$",self.short_opt):
120             msg  = "invalid short option key; "
121             msg += "should be of the form -x (x is letter)"
122             raise OptError(msg, self)
123         # check long option key
124         if self.long_opt and \
125                not re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$",self.long_opt):
126             msg  = "invalid long option key; "
127             msg += "should be of the form --word[[-word]...] "
128             msg += "(word is letters and digits sequence)"
129             raise OptError(msg, self)
130         # check that at least one option key is defined
131         if not self.short_opt and not self.long_opt:
132             msg  = "invalid option; neither short nor long option key is defined"
133             raise OptError(msg, self)
134         # destination
135         if not self.dest and self.long_opt:
136             self.dest = self.long_opt[2:].replace('-','_')
137         if not self.dest and self.short_opt:
138             self.dest = self.short_opt[1:]
139         # action
140         if not self.action:
141             self.action = "store"
142         if self.action not in self.actions:
143             msg  = "invalid action: %s" % self.action
144             raise OptError(msg, self)
145         # type
146         if not self.type:
147             if self.action in ["store_true","store_false"]: self.type = "bool"
148             else: self.type = "string"
149         if self.type not in self.types:
150             msg  = "invalid type: %s" % self.type
151             raise OptError(msg, self)
152         if self.action in ["store_true","store_false"] and self.type != "bool":
153             msg  = "invalid type: %s : should be 'bool' or None" % self.type
154             raise OptError(msg, self)
155         # default
156         if self.default:
157             try:
158                 if self.type == "string": self.default = str(self.default)
159                 if self.type == "int":    self.default = int(self.default)
160                 if self.type == "float":  self.default = float(self.default)
161                 if self.type == "bool":   self.default = boolean(self.default)
162             except :
163                 msg  = "invalid default value type: should be %s" % self.type
164                 raise OptError(msg, self)
165             pass
166         # metavar
167         if not self.metavar:
168             self.metavar = self.dest.upper()
169         # help
170         if not self.help:
171             self.help = ""
172         pass
173
174     def to_string(self):
175         """
176         Returns string representation of the option
177         """
178         opts = []
179         opt = self.short_opt
180         if opt and self.action == "store" and self.metavar: opt += " %s" % self.metavar
181         if opt: opts.append(opt)
182         opt = self.long_opt
183         if opt and self.action == "store" and self.metavar: opt += "=%s" % self.metavar
184         if opt: opts.append(opt)
185         return (", ").join(opts)
186     
187 #===================================================================
188 # class Values : resulting option values
189 #===================================================================
190 class Values:
191     """
192     Values class
193     """
194     def __init__(self):
195         pass
196         
197 #===================================================================
198 # class ArgParser : command line arguments parser
199 #===================================================================
200 class ArgParser:
201     """
202     Arguments parser class
203     """
204     def __init__(self):
205         self.options = []
206         pass
207
208     def add_option(self, *args, **kwargs):
209         """Register an option"""
210         o = ArgOption(*args, **kwargs)
211         self._check_option(o)
212         self.options.append(o)
213         pass
214
215     def parse_args(self, args = None):
216         """Parse an arguments"""
217         if not args: args = sys.argv[1:]
218         values = Values()
219         for o in self.options:
220             if o.default:
221                 setattr(values, o.dest, o.default)
222             elif not hasattr(values,o.dest):
223                 setattr(values, o.dest, None)
224         try:
225             (values, args) = self._process_args(values, args)
226         except (ArgError, ValError), e:
227             self._error(e.msg)
228
229         return (values, args)
230             
231     def print_usage(self):
232         """Print usage"""
233         print "usage: %s [options]" % os.path.basename(sys.argv[0])
234         pass
235
236     def print_help(self):
237         """Print help"""
238         self.print_usage()
239         print ""
240         olen = 0
241         _maxwidth, _indent = 79, 2
242         if len(self.options):
243             for option in self.options:
244                 if olen < len(option.to_string()): olen = len(option.to_string())
245             print "options:"
246             for option in self.options:
247                 strings = []
248                 for hs in option.help.split("\n"):
249                     s = ""
250                     for w in hs.split():
251                         if len("%s %s" % (s,w)) > _maxwidth:
252                             strings.append(s.strip()); s = ""
253                         s = "%s %s" % (s,w)
254                     if s.strip(): strings.append(s.strip())
255                 if not strings: strings[:0] = [""]
256                 print "%s%s%s" % (option.to_string(), " "*(_indent+olen-len(option.to_string())), strings[0])
257                 for i in range(1, len(strings)):
258                     print "%s%s" % (" "*(olen+_indent), strings[i])
259         pass
260     
261     def _check_option(self, option):
262         o = self._get_option(option.short_opt)
263         if not o: o = self._get_option(option.long_opt)
264         if o:
265             msg = "option conflicts with previously defined option(s)"
266             raise OptError(msg, option)
267         pass
268
269     def _get_option(self, opt_key):
270         if opt_key:
271             for o in self.options:
272                 if opt_key in [o.short_opt, o.long_opt]: return o
273         return None
274         
275     def _error(self, msg):
276         self.print_usage()
277         sys.exit("\n%s: error: %s\n" % (os.path.basename(sys.argv[0]), msg))
278         pass
279
280     def _check_value(self, option, value):
281         o = self._get_option(option)
282         try:
283             if o.type == "string": return str(value)
284             if o.type == "int":    return int(value)
285             if o.type == "float":  return float(value)
286             if o.type == "bool":   return boolean(value)
287         except:
288             msg  = "invalid value type for option %s: %s; " % (option, value)
289             msg += "should be %s" % o.type
290             raise ValError(msg)
291         raise OptBaseError("unknown error")
292
293     def _process_args(self, values, args):
294         res_args = []
295         cur_opt = None
296         rargs   = []
297         for index in range(len(args)):
298             a = args[index]
299             if cur_opt and cur_opt[1].action == "store":
300                 setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a))
301                 cur_opt = None
302                 continue
303             if a == "-":
304                 rargs = args[index+1:]
305                 break
306             elif re.match("^-[a-zA-Z].*", a):
307                 for i in range(1,len(a)):
308                     if cur_opt and cur_opt[1].action == "store":
309                         setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a[i:]))
310                         cur_opt = None
311                         break
312                     o = self._get_option("-%s"%a[i])
313                     if not o:
314                         raise ArgError("no such option: -%s"%a[i])
315                     if o.action == "store_true":
316                         setattr(values, o.dest, True)
317                     elif o.action == "store_false":
318                         setattr(values, o.dest, False)
319                     else:
320                         cur_opt = ("-%s"%a[i], o)
321                 pass
322             elif re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*", a):
323                 oname  = ("%s="%a).split("=")[0]
324                 ovalue = ("%s="%a).split("=")[1]
325                 o = self._get_option(oname)
326                 if not o:
327                     raise ArgError("no such option: %s" % oname)
328                 if o.action == "store_true":
329                     if ovalue:
330                         raise ValError("option %s does not take a value" % oname)
331                     setattr(values, o.dest, True)
332                 elif o.action == "store_false":
333                     if ovalue:
334                         raise ValError("option %s does not take a value" % oname)
335                     setattr(values, o.dest, False)
336                 else:
337                     if ovalue:
338                         setattr(values, o.dest, self._check_value(oname, ovalue))
339                     else:
340                         cur_opt = (oname, o)
341                 pass
342             elif a.startswith("-"):
343                 raise ArgError("bad formatted option: %s" % a)
344             else:
345                 rargs = args[index:]
346                 break
347         if cur_opt and cur_opt[1].action == "store":
348             raise ValError("option %s requires value" % cur_opt[0])
349         return (values, rargs)
350
351 #------------------------------------------------------------------#
352 #                                                                  #
353 #                 XML CONFIGURATION FILES PARSER                   #
354 #                                                                  #
355 #------------------------------------------------------------------#
356
357 #===================================================================
358 # class Config : general configuration options : version, OS, etc...
359 #===================================================================
360 class Config :
361     """
362     General configuration file options:
363     - Install Wizard window caption
364     - SALOME platform version
365     - Copyright and libcense info
366     - Target Linux OS version
367     """
368     def __init__(self,
369                  theVersion   = None,
370                  theCaption   = None,
371                  theCopyright = None,
372                  theLicense   = None,
373                  theOS        = None):
374         self.version   = strip(theVersion)
375         self.caption   = strip(theCaption)
376         self.copyright = strip(theCopyright)
377         self.license   = strip(theLicense)
378         self.os        = strip(theOS)
379
380 #===================================================================
381 # class Path : default target, temporary directories options
382 #===================================================================
383 class Path :
384     """
385     Path options:
386     - default target directory
387     - default temporary directory
388     """
389     def __init__(self,
390                  theTargetdir = None,
391                  theTmpdir    = None):
392         self.targetdir = strip(theTargetdir)
393         self.tmpdir    = strip(theTmpdir)
394         
395 #==============================================================
396 # class Product : pre-requisite product options
397 #==============================================================
398 class Product :
399     """
400     Product options:
401     - name, version
402     - supported installation modes and the default one
403     - dependencies
404     - required disk space
405     - installation script
406     - etc...
407     """
408     def __init__(self,
409                  theName,
410                  theVersion            = None,
411                  theInstall            = None,
412                  theSupportred         = None,
413                  theDependencies       = None,
414                  theInstalldiskspace   = None,
415                  theTemporarydiskspace = None,
416                  theScript             = None,
417                  thePickUpEnvironment  = None):
418         self.name               = strip(theName)
419         self.version            = strip(theVersion)
420         self.install            = strip(theInstall)
421         self.supported          = strip(theSupportred)
422         self.dependencies       = strip(theDependencies)
423         self.installdiskspace   = strip(theInstalldiskspace)
424         self.temporarydiskspace = strip(theTemporarydiskspace)
425         self.script             = strip(theScript)
426         self.pickupEnv          = strip(thePickUpEnvironment)
427
428 #===================================================================
429 # class ConfigParser : XML files parser implementation
430 #===================================================================
431 class ConfigParser(xmllib.XMLParser):
432     """
433     XML configuration files parser
434     """
435     def __init__(self):
436         xmllib.XMLParser.__init__(self)
437         self.products = []
438         self.currentdata = []
439         self.path = None
440         self.config = None
441         
442     def handle_data(self, data):
443         self.currentdata.append(data)
444         
445     def start_product(self, attrs):
446         if not attrs.get('name', '').strip():         return
447         if check_bool(attrs.get('disable', 'false')): return
448         aProduct = Product(attrs.get('name'),
449                            attrs.get('version',            None),
450                            attrs.get('install',            None),
451                            attrs.get('supported',          None),
452                            attrs.get('dependancies',       None),
453                            attrs.get('installdiskspace',   None),
454                            attrs.get('temporarydiskspace', None),
455                            attrs.get('script',             None),
456                            attrs.get('pickupenv',          None))
457         self.products.append(aProduct)
458         pass
459
460     def end_product(self):
461         pass
462
463     def start_config(self, attrs):
464         self.config = Config(attrs.get('version',   None),
465                              attrs.get('caption',   None),
466                              attrs.get('copyright', None),
467                              attrs.get('license',   None),
468                              attrs.get('os',        None))
469         pass
470     
471     def end_config(self):
472         pass
473
474     def start_path (self, attrs):
475         self.path = Path(attrs.get('targetdir', None),
476                          attrs.get('tempdir',   None))
477         pass
478         
479     def end_path(self):
480         pass
481
482     def getProduct(self, prod):
483         for product in self.products:
484             if product.name == prod:
485                 return product
486         return None
487
488 #------------------------------------------------------------------#
489 #                                                                  #
490 #                         SERVICE FUNCTIONS                        #
491 #                                                                  #
492 #------------------------------------------------------------------#
493
494 #==============================================================
495 # message: prints diagnostic information
496 #==============================================================
497 def message(msg):
498     """
499     Prints diagnostic information.
500     """
501     if msg.strip():
502         print ">>>", msg
503     pass
504
505 #==============================================================
506 # warning: prints warning
507 #==============================================================
508 def warning(msg):
509     """
510     Prints warning.
511     """
512     if msg.strip():
513         print ""
514         print msg
515         print ""
516     pass
517
518 #==============================================================
519 # error_exit : prints (optionally) error string, then prints
520 #              help information and quits
521 #==============================================================
522 def error_exit(msg = "", print_help = True):
523     """
524     Prints (optionally) error string,
525     then prints help information and quits.
526     """
527     # print error message
528     if len(msg.strip()):
529         print ""
530         print msg
531         print ""
532     # print help information
533     if print_help:
534         global opt_parser
535         if opt_parser:
536             opt_parser.print_help() 
537             print ""
538     # cleaning 
539     clean_all()
540     # quit
541     sys.exit(1);
542     pass
543
544 #==============================================================
545 # boolean : Converts string to boolean value.
546 #==============================================================
547 def boolean(val):
548     """
549     Converts string to boolean value if possible.
550     Raises exception if wrong string is used.
551     """
552     if isinstance(val, types.StringType):
553         if val.strip().lower()   in ["true",  "yes", "ok"]     : return True
554         elif val.strip().lower() in ["false", "no",  "cancel"] : return False
555         else: raise TypeError("invalid boolean value")
556     return bool(val)
557
558 #=================================================================
559 # check_bool : checks boolean value: yes/no, true/false, 1/0
560 #=================================================================
561 def check_bool(val):
562     """
563     Checks boolean value.
564     """
565     try:
566         return boolean(val)
567     except:
568         pass
569     return False
570
571 #==============================================================
572 # clean_all : performs system cleaning before exiting
573 #==============================================================
574 def clean_all():
575     """
576     Performs system cleaning before exiting.
577     """
578     global root_path
579     remove_dir(root_path)
580     pass
581
582 #==============================================================
583 # parse_parameters : parses command line arguments
584 #==============================================================
585 def parse_parameters():
586     """
587     Parses command line arguments.
588     """
589     global opt_parser
590     opt_parser = ArgParser()
591     
592     help_str  = "Runs the Installation Wizard in the GUI mode [default].\n"
593     opt_parser.add_option("-g",
594                           "--gui",
595                           action="store_true",
596                           dest="gui",
597                           default=True,
598                           help=help_str)
599     help_str  = "Runs the Installation Wizard in the TUI mode."
600     opt_parser.add_option("-b",
601                           "--batch",
602                           action="store_false",
603                           dest="gui",
604                           help=help_str)
605     help_str  = "The configuration xml file.\n"
606     help_str += "If this parameter is missing, then the program tries to define the "
607     help_str += "Linux platform and use the corresponding xml file. For example, "
608     help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case. "
609     help_str += "If program fails to define target Linux platform or the corresponding "
610     help_str += "xml file is not provided with the Installation Wizard, then default "
611     help_str += "config.xml file is used."
612     opt_parser.add_option("-f",
613                           "--file",
614                           action="store",
615                           dest="xmlfile",
616                           metavar="FILE",
617                           help=help_str)
618     help_str  = "The target directory the products to be installed to.\n"
619     help_str += "When used this parameter overrides the default target directory "
620     help_str += "defined in the configuration xml file."
621     opt_parser.add_option("-d",
622                           "--target",
623                           action="store",
624                           dest="target_dir",
625                           metavar="DIR",
626                           help=help_str)
627     help_str  = "The directory to be used for temporary files.\n"
628     help_str += "When used this parameter overrides the default temporary directory "
629     help_str += "defined in the configuration xml file."
630     opt_parser.add_option("-t",
631                           "--tmp",
632                           action="store",
633                           dest="tmp_dir",
634                           metavar="DIR",
635                           help=help_str)
636     help_str  = "Prints version information and quits."
637     opt_parser.add_option("-v",
638                           "--version",
639                           action="store_true",
640                           help=help_str)
641     help_str  = "Prints this help and quits."
642     opt_parser.add_option("-h",
643                           "--help",
644                           action="store_true",
645                           help=help_str)
646     (options, args) = opt_parser.parse_args()
647     if options.help:
648         # print help info and quit
649         print "\nSALOME Installation Wizard\n"
650         opt_parser.print_help()
651         print ""
652         sys.exit(0)
653     if options.version:
654         # print version info and quit
655         print ""
656         cmd = "./bin/SALOME_InstallWizard --version"
657         os.system(cmd)
658         print ""
659         sys.exit(0)
660     return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui]
661
662 #=================================================================
663 # strip : removes spaces at the beginning and at the end of the 
664 #         <param> if it is of string type
665 #=================================================================
666 def strip(param):
667     """
668     Removes spaces at the beginning and at the end
669     of the given parameter.
670     """
671     if type(param) == types.StringType:
672         return param.strip()
673     return param
674     
675 #=================================================================
676 # get_dependencies : extract products dependencies
677 #=================================================================
678 def get_dependencies(prods):
679     """
680     Gets full list of pre-requisite products.
681     """
682     list = []
683     for product in prods:
684         deps = product.dependencies.split(",")
685         for dep in deps:
686             if dep and not dep in list:
687                 list.append( dep )
688                 
689         if product and not product in list:
690             list.append( product.name )
691             
692     return " ".join( list )
693
694 #==============================================================
695 # create_dir : creates a directory with (optional) permissions,
696 #              returns the part of path that existed before
697 #              directory creation; exits with error if access
698 #              is denied
699 #==============================================================
700 def create_dir(directory, access = 0777):
701     """
702     Creates a directory with (optional) permissions,
703     returns the part of path that existed before
704     directory creation; exits with error if access
705     is denied.
706     """
707     dirs = string.split(directory, "/")
708     existing = "";
709     dir = ""
710     root = ""
711     for subdir in dirs:
712         if len(subdir) == 0:  continue
713         dir = "%s/%s"%(dir, subdir)
714         if os.path.exists(dir):
715             existing = dir
716         else:
717             try:
718                 os.mkdir(dir, access)
719             except:
720                 error_exit("Can't create directory: %s.\nAccess is denied."%directory)
721             if dir == "%s/%s"%(existing, subdir):
722                 root = dir
723     return root
724
725 #==============================================================
726 # substituteVars : performes environment variables substistution
727 #                  the given string; if varibale is not defined
728 #                  it is substituted by the empty string
729 #==============================================================
730 def substituteVars(str):
731     """
732     Performes environment variables substistution.
733     """
734     str = os.path.expanduser(str)
735     str = os.path.expandvars(str)
736     return str
737
738 #================================================================
739 # get_program_path : gets program's directory path
740 #                    (and performs 'cd' command there) 
741 #================================================================
742 def get_program_path():
743     """
744     Returns the program directory path
745     (and make this directory current).
746     """
747     path = os.path.dirname(sys.argv[0])
748     if path:
749         os.chdir(path)
750     return os.getcwd()
751
752 #================================================================
753 # check_dir : checks directory existence
754 #================================================================
755 def check_dir(dir):
756     """
757     Checks directory existence.
758     """
759     if (os.path.islink(dir)):
760         realpath = os.path.realpath(dir)
761         if not os.path.exists(realpath):
762             msg = "Invalid link %s.\nThe directory %s a link points to does not exist. Stopped..."%(dir,realpath)
763             error_exit(msg, False)
764     else:
765         if not os.path.exists(dir):
766             msg = "Directory %s does not exist. Stopped..."%dir
767             error_exit(msg, False)
768     pass
769
770 #===============================================================
771 # check_disk_space : checks the disk space;
772 #                    quits if there is no enough disk space
773 #===============================================================
774 def check_disk_space(products, scripts_dir, target_dir, tmp_dir):
775     """
776     Checks if there is enough disk space to install products.
777     Quits with error if there is no enough disk space.
778     """
779     install_space = 0
780     temporary_space = 0
781     for product in products:
782         if product.install in [__TAG__NATIVE__, __TAG__PREINSTALL__]:
783             continue
784         spaces = string.split(product.installdiskspace, ',')
785         prod_space = spaces[0]
786         if (len(spaces) > 1 ) and (product.install == __TAG__SOURCES__):
787             prod_space = spaces[1]
788         install_space = install_space + string.atoi(prod_space)
789         if product.install == __TAG__SOURCES__:
790             temporary_space = max(temporary_space, string.atoi(product.temporarydiskspace))
791
792     res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", target_dir, install_space))
793     if res:
794         msg = "There is no enough space to install the products. Stopped..."
795         error_exit(msg, False)
796     
797     res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", tmp_dir, temporary_space))
798     if res:
799         msg = "There is no enough space for temporary directory. Stopped..."
800         error_exit(msg, False)
801     pass
802  
803 #===============================================================
804 # remove_dir : removes temporary directory
805 #===============================================================
806 def remove_dir(path):
807     """
808     Removes temporary directory.
809     """
810     if path and os.path.exists(path):
811         os.system("rm -rf " + path)
812     pass
813
814 #==============================================================
815 # has_binaries : returns True if some product is installed from
816 #                binaries
817 #===============================================================
818 def has_binaries(products):
819     """
820     Returns True if some product is installed in 'binaries' mode.
821     """
822     for product in products:
823         if product.install == __TAG__BINARIES__:
824             return True
825     return False
826
827 #==============================================================
828 # has_sources : returns True if some product is installed from
829 #               sources
830 #===============================================================
831 def has_sources(products):
832     """
833     Returns True if some product is installed in 'sources' mode.
834     """
835     for product in products:
836         if product.install == __TAG__SOURCES__:
837             return True
838     return False
839
840 #==============================================================
841 # get_tmp_dir : gets temporary directory name
842 #===============================================================
843 def get_tmp_dir(dir):
844     """
845     Gets temporary directory path.
846     """
847     max_attempts = 100
848     dir_prefix="INSTALLWORK"
849     range_bottom = 0; range_top = 999999
850     for i in xrange(max_attempts):
851         tmp_dir = "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
852         if not os.path.exists( tmp_dir ):
853             return tmp_dir
854     return "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
855     
856 #------------------------------------------------------------------#
857 #                                                                  #
858 #                    EXECUTION STARTS HERE                         #
859 #                                                                  #
860 #------------------------------------------------------------------#
861     
862 if __name__ == "__main__":
863     # parse command line
864     [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters()
865     if xml_file:   xml_file   = os.path.abspath(xml_file)
866     if target_dir: target_dir = os.path.abspath(target_dir)
867     if tmp_dir:    tmp_dir    = os.path.abspath(tmp_dir)
868     # get program dir
869     cur_dir = get_program_path()
870
871     # define xml file to be used
872     if (xml_file is None):
873         plt_name = ""
874         plt_ver  = ""
875         plt_bit  = ""
876         xml_file_name = "config.xml"
877         if os.path.exists("/etc/redhat-release"):
878             # - Red Hat Linux 8.0
879             # - Red Hat Linux 9
880             # - Mandrake Linux 10.1
881             # - Scientific Linux 3.0.5
882             # - Mandriva 2006.0 32bit/64bit
883             data = open("/etc/redhat-release").readline()
884             res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
885             if res:
886                 plt_name = "".join(res.group(1).split())
887                 plt_ver  = res.group(2)
888                 if re.search(r'x86_64', data):
889                     plt_bit  = "_64"
890         elif os.path.exists("/etc/debian_version"):
891             # - Debian 3.1
892             plt_name = "Debian"
893             plt_ver = open("/etc/debian_version").readline().strip()
894         elif os.path.exists("/etc/mandriva-release"):
895             # - Mandriva 2006 (an additional check if above check fails)
896             data = open("/etc/mandriva-release").readline()
897             res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
898             if res:
899                 plt_name = "".join(res.group(1).split())
900                 plt_ver  = res.group(2)
901                 if re.search(r'x86_64', data):
902                     plt_bit  = "_64"
903                 pass
904         _xml_file_name = "config_%s_%s%s.xml"%(plt_name, plt_ver, plt_bit)
905         if plt_name and plt_ver and os.path.exists("%s/%s"%(cur_dir, _xml_file_name)):
906             xml_file_name = _xml_file_name
907         else:
908             msg  = "Not supported Linux platform!\n"
909             msg += "Trying to use default configuration file!"
910             warning(msg)
911
912         xml_file = "%s/%s"%(cur_dir, xml_file_name)
913
914     if not xml_file or not os.path.exists(xml_file):
915         msg = "Configuration file %s is not found!"%xml_file
916         error_exit(msg)
917
918     if not os.access(xml_file, os.R_OK):
919         msg = "There is no read access for %s file!"%xml_file
920         error_exit(msg)
921
922     #---- GUI ----------------
923
924     if is_gui : 
925         env = os.environ
926         if not env.has_key("PATH") :
927             env["PATH"] = ""
928         if not env.has_key("LD_LIBRARY_PATH") :
929             env["LD_LIBRARY_PATH"] = ""
930
931         env["LD_LIBRARY_PATH"] =  ".:" + env["LD_LIBRARY_PATH"]
932         env["PATH"] = ".:" + env["PATH"]
933
934         cmd = "./bin/SALOME_InstallWizard --file %s"%xml_file
935         if target_dir is not None:
936             cmd += " --target %s"%target_dir
937         if tmp_dir is not None:
938             cmd += " --tmp %s"%tmp_dir
939         cmd += "&"
940         sys.exit(os.system(cmd))
941
942     #-----  TUI ---------------------
943
944     # parse XML file -----------
945     message("Parsing XML configuration file: %s"%xml_file)
946     filehandle = open(xml_file)
947     data = filehandle.read()
948     filehandle.close()
949     parser = ConfigParser()
950     parser.feed(data)
951     parser.close()
952
953     # actions map
954     what_to_do = { __TAG__SOURCES__    : "install_source",
955                    __TAG__BINARIES__   : "install_binary",
956                    __TAG__NATIVE__     : "try_native",
957                    __TAG__PREINSTALL__ : "try_preinstalled"}
958     # source directory map
959     bin_dir = ""
960     if parser.config.os:
961         bin_dir += "/%s"%parser.config.os
962     subdir = { __TAG__SOURCES__    : "SOURCES",
963                __TAG__BINARIES__   : "BINARIES" + bin_dir,
964                __TAG__NATIVE__     : "",
965                __TAG__PREINSTALL__ : ""}
966
967     # check scripts directory -----------
968     scripts_dir = "%s/%s"%(cur_dir, "config_files")
969     check_dir(scripts_dir)
970
971     # check products archives directories -----------
972     has_bin = has_binaries(parser.products)
973     has_src = has_sources(parser.products)
974     source_dir = "%s/%s"%(cur_dir, "Products")
975
976     if has_src or has_bin:
977         check_dir(source_dir)
978
979     if has_src:
980         check_dir("%s/%s"%(source_dir,subdir[__TAG__SOURCES__]))
981
982     if has_bin:
983         check_dir("%s/%s"%(source_dir,subdir[__TAG__BINARIES__]))
984
985     # check/create target dir -----------
986     if target_dir is None:
987         target_dir = parser.path.targetdir
988     target_dir = substituteVars(target_dir)
989
990     message("Creating target directory: " + target_dir)
991     create_dir(target_dir, 0755)
992
993     if not os.path.exists(target_dir):
994         error_exit("Invalid target directory: " + target_dir)
995
996     if not os.access(target_dir, os.W_OK) :
997         error_exit("There is no write permissions for the directory: " + target_dir)
998
999     # check/create temporary dir -----------
1000     if tmp_dir is None:
1001         tmp_dir = parser.path.tmpdir
1002     if not tmp_dir:
1003         tmp_dir = "/tmp"
1004     tmp_dir = substituteVars(tmp_dir)
1005     tmp_dir = get_tmp_dir(tmp_dir)
1006
1007     message("Creating temporary directory: " + tmp_dir)
1008     root_path = create_dir(tmp_dir, 0755)
1009    
1010     if not os.path.exists(tmp_dir):
1011         error_exit("Invalid temporary directory: " + tmp_dir)
1012
1013     if not os.access(tmp_dir, os.W_OK) :
1014         error_exit("There is no write permissions for the directory: " + tmp_dir)
1015         
1016     # check available disk space -----------
1017     message("Checking available disk space")
1018     check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir)
1019
1020     # change current directory -----------
1021     os.chdir(scripts_dir)
1022
1023     # get dependencies list -----------
1024     list_of_dep = get_dependencies(parser.products)
1025
1026     # starting -----------
1027     message("Starting ...")
1028     
1029     # install products -----------
1030     for product in parser.products:
1031         message("... processing %s ..."%product.name)
1032         cmd = '%s/%s %s %s %s/%s %s "%s" %s'%(scripts_dir,
1033                                               product.script,
1034                                               what_to_do[product.install],
1035                                               tmp_dir,
1036                                               source_dir,
1037                                               subdir[product.install],
1038                                               target_dir,
1039                                               list_of_dep,
1040                                               product.name)
1041         res = os.system(cmd)
1042
1043     # pickup environment -----------
1044     message("Creating environment files")
1045     for product in parser.products :
1046         if check_bool(product.pickupEnv):
1047             cmd = '%s/%s pickup_env %s %s/%s %s "%s" %s'%(scripts_dir,
1048                                                           product.script,
1049                                                           tmp_dir,
1050                                                           source_dir,
1051                                                           subdir[product.install],
1052                                                           target_dir,
1053                                                           list_of_dep,
1054                                                           product.name)
1055             res = os.system(cmd)
1056
1057     # clean temporary directory -----------
1058     message("Cleaning temporary directory")
1059     clean_all()
1060     
1061     # finishing -----------
1062     message("Finished!")
1063     pass