4 warnings.filterwarnings("ignore", "", DeprecationWarning)
7 import sys, os, string, re
9 #==============================================================
11 #==============================================================
13 str = "\nSALOME Installation Wizard\n\n"
14 str = str + "\tUsage : \n\tInstall [-g|b] [-f <xml-file>] [-t <target-dir>] [-tmp <tmp-dir>]\n"
16 str = str + " -g Runs the Installation Wizard in the GUI mode.\n"
17 str = str + " In this case only <xmlfile> is taken into account \n"
18 str = str + " from the parameters list. This key is used by default.\n"
20 str = str + " -b Runs the Installation Wizard in the batch mode.\n"
21 str = str + " All the found parameters are taken in to account.\n"
23 str = str + " -f <xml-file> The configuration file to be parsed by the Installation Wizard.\n"
24 str = str + " If this parameter is missed then the script tries to define\n"
25 str = str + " the Red Hat version and use the corresponding xml. For example,\n"
26 str = str + " for Red Hat 8.0 config_RedHat_8.0.xml file is supposed to be used\n"
27 str = str + " by default. If the appropriate xml file is not found, the config.xml\n"
28 str = str + " is used by default.\n"
30 str = str + " -t <target-dir> The target directory the products to be installed to.\n"
31 str = str + " This parameter overloads the target directory described in the\n"
32 str = str + " configuration file.\n"
34 str = str + " -tmp <tmp-dir> The directory which should be used for the temporary files.\n"
35 str = str + " This parameter overloads the temporary directory described in the\n"
36 str = str + " configuration file.\n"
38 str = str + " -h Prints this help information.\n"
41 #==============================================================
43 #==============================================================
47 #==============================================================
49 #==============================================================
50 def error_exit (str = ""):
52 if len(str): res = "\n" + str + "\n"
59 #==============================================================
60 # Cheks whether the passed parameter is a key.
61 #==============================================================
65 return re.match(r'^-[a-zA-Z]', val)
68 #==============================================================
69 # From the list of parameters extracts value following 'key'
70 #==============================================================
71 def extract_parameter ( key, args ) :
74 if ( length == 0 ) : return None
78 for i in range(0, length-1):
80 if ( is_key ( args[i+1]) ) :
81 print " No value after key ", key
85 if ( i < length - 2 and is_key ( args[i+2] ) == 0 ) : #control that only one value follows key
86 #(not a list). In this case params are correct.
87 print "Too much values after key ", key
98 #===============================================================
99 # Extracts list of values following specified 'key' from 'args[]'
100 #===============================================================
101 def extract_list (key, args) :
104 if ( args is None or lenght == 0 ):
110 for i in range(0, length) :
112 if (is_key ( args[i+1])) :
115 for i in range (i+1, lenght):
116 if is_key(args[i]) : break
120 return list; #empty list is returned if no values after key
123 #==============================================================
124 # Method find the $key in the list and return 1 if success
126 #==============================================================
127 def find_key (key, argv) :
129 if (not is_key(key)) : return 0
136 #==============================================================
137 # Parse the list of parameters
138 #==============================================================
139 def parse_parameters (args) :
141 if find_key('-h', args) :
142 print get_help_info();
146 xmlfile = extract_parameter("-f", args)
147 target_dir = extract_parameter("-t", args)
148 tmp_dir = extract_parameter("-tmp", args)
149 if find_key('-b', args):
152 return [xmlfile, target_dir, tmp_dir, is_gui]
155 #=================================================================
156 # Checks boolean value: yes/no, true/false, 1/0
157 #=================================================================
159 return str(val).strip() in ["yes","true", "1"]
161 #=================================================================
162 # The first algorithm to create the dependencies list by their level
163 #=================================================================
164 def get_next_level(list, products):
168 expr = "(" + list[0].name
169 for i in range(1, len(list)):
170 expr = expr + "|"+ list[i].name
173 #expr=re.compile(expr)
175 for product in products:
176 deps = re.sub(r'\s+', "", product.dependencies)
177 if re.search(expr, deps):
178 result.append(product)
183 def create_levels(prods):
186 products = copy.deepcopy(prods)
190 #1. find the products with empty lists of dependencies
192 for product in products:
193 if len(re.sub(r'\s', "", product.dependencies)) == 0 :
197 raise RuntimeError, "Products that depend on nothing are not found"
199 # remove the first level products from the common list of products
200 for product in list :
201 products.remove(product)
206 while (len(products)) :
207 res = get_next_level(list, products)
209 raise RuntimeError, "Empty list of products is found"
212 products.remove(product)
219 for i in result.keys():
220 for product in result[i]:
221 str = str + product.name + " "
225 #=================================================================
226 # The second algorithm
227 #=================================================================
228 def get_dependencies_set(prods) :
232 products = copy.deepcopy(prods)
236 while (len(products)) :
239 #find the products with empty list of dependencies
240 for product in products:
241 product.dependencies = re.sub(r'\s+$', "", product.dependencies)
242 product.dependencies = re.sub(r'^\s+', "", product.dependencies)
244 if len(product.dependencies) == 0 :
245 tmplist.append(product);
246 deps = deps + " " + product.name
250 #remove the products names from other products dependencies
252 products.remove(item)
254 regexpr1 = "((^|,(\s+)?)"+item.name+"$|^"+item.name+"(\s+)?,(\s+)?)"
255 regexpr2 = ",(\s+)?"+item.name+"(\s+)?,(\s+)?"
257 for product in products:
258 product.dependencies = re.sub(r'\s+$', "", product.dependencies)
259 product.dependencies = re.sub(r'^\s+', "", product.dependencies)
261 product.dependencies = re.sub(regexpr1, "", product.dependencies)
262 product.dependencies = re.sub(regexpr2, ",", product.dependencies)
266 #=================================================================
267 # The third algorithm (same as SALOME_InstallWizard.cxx uses)
268 #=================================================================
269 def get_dependencies(prods) :
271 for product in prods:
272 if check_bool(product.disable): continue
274 deps = product.dependencies.split(",")
276 if dep and not dep in list:
279 if product and not product in list:
280 list.append( product.name )
282 return " ".join( list )
284 #==============================================================
285 # Creates dir, returns the part of path that existed early.
286 # Access may be defined.
287 #==============================================================
288 def create_dir (directory, access = 0777):
290 dirs = string.split(directory, "/")
291 existing = ""; dir = ""
294 if len(item) == 0: continue
296 if os.path.exists(dir):
299 os.mkdir(dir, access )
300 #root= existing + "/"+item
301 if dir == existing + "/"+item :
303 #else : root = existing
307 #==============================================================
309 #==============================================================
312 def __init__(self, theName,
315 theSupportred = None,
317 theDependencies = None,
318 theInstalldiskspace = None,
319 theTemporarydiskspace = None,
321 thePickUpEnvironment = None):
325 self.version = theVersion
326 self.install = theInstall
327 self.supported = theSupportred
328 self.disable = theDisable
329 self.dependencies = theDependencies
330 self.installdiskspace = theInstalldiskspace
331 self.temporarydiskspace = theTemporarydiskspace
332 self.script = theScript
333 self.pickupEnv = thePickUpEnvironment
335 #===================================================================
337 #===================================================================
339 def __init__(self, theVersion='', theCaption='', theCopyright='', theLicense='', theOS=''):
340 self.version = theVersion
341 self.caption = theCaption
342 self.copyright = theCopyright
343 self.license = theLicense
347 #===================================================================
349 #===================================================================
351 def __init__(self, theTargetdir=".", theTmpdir="."):
352 self.targetdir = theTargetdir
353 self.tmpdir = theTmpdir
356 #===================================================================
358 #===================================================================
359 class ConfigParser(xmllib.XMLParser):
361 xmllib.XMLParser.__init__(self)
363 self.currentdata = []
367 def handle_data(self, data):
368 self.currentdata.append(data)
370 def start_product(self, attrs):
371 aProduct = Product(attrs['name'],
376 attrs['dependancies'],
377 attrs['installdiskspace'],
378 attrs['temporarydiskspace'],
381 if attrs.has_key( 'pickupenv' ):
382 aProduct.pickupEnv = attrs['pickupenv']
384 self.products.append(aProduct)
386 def end_product(self):
389 def start_config(self, attrs):
390 self.config = Config(attrs['version'],
395 def end_config(self):
398 def start_path (self, attrs):
399 self.path = Path(attrs['targetdir'],
405 def getProduct(self, prod):
406 for product in self.products:
407 if product.name == prod:
411 #================================================================
412 # get the path using file name
413 #================================================================
414 def get_current_path(file_name):
415 path = "."; where = string.rfind(file_name,'/');
417 path = (file_name)[: where]
419 path = os.getcwd() + "/"
422 #================================================================
423 # checks dir existing
424 #================================================================
426 if (os.path.islink(dir)) :
427 native_dir = os.readlink(dir)
428 if not os.path.exists(native_dir) :
429 print "Invalid link " + dir + ". The directory " + native_dir + " a link points to does not exist."
432 if not os.path.exists(dir):
433 print "Directory " + dir + " does not exist"
437 #===============================================================
438 # Checks the disk space. Exit from interpreter if there is no
440 #===============================================================
441 def check_disk_space(products, script_dir, target_dir, tmp_dir):
442 import re, string, os
445 for product in products :
446 product.install = re.sub(r'^\s+', "", product.install)
447 product.install = re.sub(r'\s+$', "", product.install)
449 if check_bool(product.disable) or product.install == "use native" or product.install == "not install":
451 spaces = string.split( product.installdiskspace,',')
452 prod_space = spaces[0]
453 if (len(spaces) == 2 ) and (product.install == "install binaries") :
454 prod_space = spaces[1]
455 install_space = install_space + string.atoi(prod_space)
456 temporary_space = temporary_space + string.atoi(product.temporarydiskspace)
457 res = os.system(scripts_dir + "checkSize.sh" + " " + target_dir + " " + str(install_space))
459 print "There is no enough space to install the products."
462 res = os.system(scripts_dir + "checkSize.sh" + " " + tmp_dir + " " + str(temporary_space))
464 print "There is no enough space for tmp directory."
469 #===============================================================
470 # Removes temporary directory
471 #===============================================================
472 def remove_dir( rem_path = "" ):
473 if len( rem_path ) and os.path.exists( rem_path ):
474 os.system( "rm -rf " + rem_path )
477 #================================================================
479 #================================================================
481 if __name__ == "__main__":
483 cur_dir = get_current_path(sys.argv[0])
485 [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters(sys.argv)
487 # define xml file -----------------
488 if (xml_file is None) :
491 xml_file_name = "config.xml"
492 if os.path.exists("/etc/redhat-release"):
493 # - Red Hat Linux 8.0
495 # - Mandrake Linux 10.1
496 # - Scientific Linux 3.0.5
497 data = open("/etc/redhat-release").readline()
498 res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
500 plt_name = "".join(res.group(1).split())
501 plt_ver = res.group(2)
502 elif os.path.exists("/etc/debian_version"):
505 plt_ver = open("/etc/debian_version").readline().strip()
506 _xml_file_name = "config_%s_%s.xml"%(plt_name, plt_ver)
507 if plt_name and plt_ver and os.path.exists(cur_dir + _xml_file_name):
508 xml_file_name = _xml_file_name
511 print "Not supported Linux platform!"
512 print "Trying to use default configuration!"
515 xml_file = cur_dir + xml_file_name
517 if not xml_file or not os.path.exists(xml_file):
518 msg = "Configuration file %s is not found!"%xml_file
519 msg += "\nTry to run with -f <xmlfile> option."
522 if not os.access(xml_file, os.R_OK):
523 print "There is no read access for %s file!"%xml_file
526 #---- GUI ----------------
529 if not env.has_key("PATH") :
531 if not env.has_key("LD_LIBRARY_PATH") :
532 env["LD_LIBRARY_PATH"]= ""
534 env["LD_LIBRARY_PATH"] = ".:" + env["LD_LIBRARY_PATH"]
535 env["PATH"] = ".:"+ env["PATH"]
537 sys.exit(os.system("cd " + cur_dir + "; ./bin/SALOME_InstallWizard " + xml_file +"&"))
541 #----- TUI ---------------------
543 #print xml_file, target_dir, tmp_dir, is_gui
545 message("Parsing xml config file: " + xml_file)
546 filehandle = open(xml_file)
547 data = filehandle.read()
549 parser = ConfigParser()
555 what_to_do = { "install sources" : "install_source",
556 "install binaries" : "install_binary",
557 "use native" : "try_native",
558 "not install" : "try_preinstalled"}
559 # define tmp dir -----------
561 tmp_dir = parser.path.tmpdir
562 if tmp_dir is None or tmp_dir == "":
565 tmp_dir = tmp_dir + "/INSTALLWORK" + str(random.randint(10000,100000))
567 if not os.path.exists(tmp_dir):
568 message("Creating temporary directory: " + tmp_dir); root_path = create_dir(tmp_dir, 0755) ;
569 if not os.path.exists(tmp_dir):
570 error_exit("Invalid temporary directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file\n\n")
572 if not os.access(tmp_dir, os.W_OK) :
573 str = "There is no write permissions for directory " + tmp_dir + ". Use -tmp key to set temporary directory or correct xml file"
576 # define target dir --------
577 if target_dir is None:
578 target_dir = parser.path.targetdir
580 if not os.path.exists(target_dir):
581 message("Creating target directory: " + target_dir); create_dir(target_dir, 0755)
582 if not os.path.exists(target_dir):
583 error_exit("Invalid target directory " + target_dir + ". Use -t key to set directory or correct xml file\n\n")
585 if not os.access(target_dir, os.W_OK) :
586 str = "There is no write permissions for directory " + target_dir + ". Use -t key to set target directory or correct xml file."
589 # define products dir ------------
590 source_dir = cur_dir + "Products" ;
591 if not check_dir(source_dir):
592 remove_dir(root_path)
595 subdir = {"install sources" : "SOURCES",
596 "install binaries" : "BINARIES/"+parser.config.os,
601 # define scripts dir ------------
602 scripts_dir = cur_dir + "config_files/"
603 if not check_dir(scripts_dir):
604 remove_dir(root_path)
606 os.chdir(scripts_dir)
608 #list_of_dep = create_levels(parser.products)
609 #list_of_dep = get_dependencies_set(parser.products)
610 list_of_dep = get_dependencies(parser.products)
612 message("Checking available disk space")
613 if check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir) :
615 message("Starting...")
617 for product in parser.products :
619 if check_bool(product.disable): continue
621 message("Processing " + product.name + "...")
622 cmd = scripts_dir + product.script + " " + \
623 what_to_do[product.install]+ " " + \
625 source_dir + "/" + subdir[product.install] + " " + \
627 '"' + list_of_dep + '"' + " " + \
631 #if res : break; # try_preinstalled can return 1
634 message("Creating environment files")
635 for product in parser.products :
637 if check_bool(product.disable): continue
639 if check_bool(product.pickupEnv):
640 cmd = scripts_dir + product.script + " " + \
643 source_dir + "/" + subdir[product.install] + " " + \
645 '"' + list_of_dep + '"' + " " + \
650 message("Cleaning temporary directory")
651 remove_dir(root_path)