4 import sys, os, string, re
6 #==============================================================
8 #==============================================================
10 str = "\nSALOME2 Installation Wizard\n\n"
11 str = str + "\tUsage : \n\tInstall [-g|b] [-f <xml-file>] [-t <target-dir>] [-tmp <tmp-dir>]\n"
13 str = str + " -g Runs the Installation Wizard in the GUI mode.\n"
14 str = str + " In this case only <xmlfile> is taken into account \n"
15 str = str + " from the parameters list. This key is used by default.\n"
17 str = str + " -b Runs the Installation Wizard in the batch mode.\n"
18 str = str + " All the found parameters are taken in to account.\n"
20 str = str + " -f <xml-file> The configuration file to be parsed by the Installation Wizard.\n"
21 str = str + " If this parameter is missed then the script tries to define\n"
22 str = str + " the Red Hat version and use the corresponding xml. For example,\n"
23 str = str + " for Red Hat 8.0 config_RedHat8_0.xml file is supposed to be used\n"
24 str = str + " by default. If the appropriate xml file is not found, the config.xml\n"
25 str = str + " is used by default.\n"
27 str = str + " -t <target-dir> The target directory the products to be installed to.\n"
28 str = str + " This parameter overloads the target directory described in the\n"
29 str = str + " configuration file.\n"
31 str = str + " -tmp <tmp-dir> The directory which should be used for the temporary files.\n"
32 str = str + " This parameter overloads the temporary directory described in the\n"
33 str = str + " configuration file.\n"
35 str = str + " -h Prints this help information.\n"
38 #==============================================================
40 #==============================================================
44 #==============================================================
46 #==============================================================
47 def error_exit (str = ""):
49 if len(str): res = "\n" + str + "\n"
56 #==============================================================
57 # Cheks whether the passed parameter is a key.
58 #==============================================================
62 return re.match(r'^-[a-zA-Z]', val)
65 #==============================================================
66 # From the list of parameters extracts value following 'key'
67 #==============================================================
68 def extract_parameter ( key, args ) :
71 if ( length == 0 ) : return None
75 for i in range(0, length-1):
77 if ( is_key ( args[i+1]) ) :
78 print " No value after key ", key
82 if ( i < length - 2 and is_key ( args[i+2] ) == 0 ) : #control that only one value follows key
83 #(not a list). In this case params are correct.
84 print "Too much values after key ", key
95 #===============================================================
96 # Extracts list of values following specified 'key' from 'args[]'
97 #===============================================================
98 def extract_list (key, args) :
101 if ( args is None or lenght == 0 ):
107 for i in range(0, length) :
109 if (is_key ( args[i+1])) :
112 for i in range (i+1, lenght):
113 if is_key(args[i]) : break
117 return list; #empty list is returned if no values after key
120 #==============================================================
121 # Method find the $key in the list and return 1 if success
123 #==============================================================
124 def find_key (key, argv) :
126 if (not is_key(key)) : return 0
133 #==============================================================
134 # Parse the list of parameters
135 #==============================================================
136 def parse_parameters (args) :
138 if find_key('-h', args) :
139 print get_help_info();
143 xmlfile = extract_parameter("-f", args)
144 target_dir = extract_parameter("-t", args)
145 tmp_dir = extract_parameter("-tmp", args)
146 if find_key('-b', args):
149 return [xmlfile, target_dir, tmp_dir, is_gui]
152 #=================================================================
153 # Checks boolean value: yes/no, true/false, 1/0
154 #=================================================================
156 return str(val).strip() in ["yes","true", "1"]
158 #=================================================================
159 # The first algorithm to create the dependencies list by their level
160 #=================================================================
161 def get_next_level(list, products):
165 expr = "(" + list[0].name
166 for i in range(1, len(list)):
167 expr = expr + "|"+ list[i].name
170 #expr=re.compile(expr)
172 for product in products:
173 deps = re.sub(r'\s+', "", product.dependencies)
174 if re.search(expr, deps):
175 result.append(product)
180 def create_levels(prods):
183 products = copy.deepcopy(prods)
187 #1. find the products with empty lists of dependencies
189 for product in products:
190 if len(re.sub(r'\s', "", product.dependencies)) == 0 :
194 raise RuntimeError, "Products that depend on nothing are not found"
196 # remove the first level products from the common list of products
197 for product in list :
198 products.remove(product)
203 while (len(products)) :
204 res = get_next_level(list, products)
206 raise RuntimeError, "Empty list of products is found"
209 products.remove(product)
216 for i in result.keys():
217 for product in result[i]:
218 str = str + product.name + " "
222 #=================================================================
223 # The second algorithm
224 #=================================================================
225 def get_dependencies_set(prods) :
229 products = copy.deepcopy(prods)
233 while (len(products)) :
236 #find the products with empty list of dependencies
237 for product in products:
238 product.dependencies = re.sub(r'\s+$', "", product.dependencies)
239 product.dependencies = re.sub(r'^\s+', "", product.dependencies)
241 if len(product.dependencies) == 0 :
242 tmplist.append(product);
243 deps = deps + " " + product.name
247 #remove the products names from other products dependencies
249 products.remove(item)
251 regexpr1 = "((^|,(\s+)?)"+item.name+"$|^"+item.name+"(\s+)?,(\s+)?)"
252 regexpr2 = ",(\s+)?"+item.name+"(\s+)?,(\s+)?"
254 for product in products:
255 product.dependencies = re.sub(r'\s+$', "", product.dependencies)
256 product.dependencies = re.sub(r'^\s+', "", product.dependencies)
258 product.dependencies = re.sub(regexpr1, "", product.dependencies)
259 product.dependencies = re.sub(regexpr2, ",", product.dependencies)
263 #=================================================================
264 # The third algorithm (same as SALOME_InstallWizard.cxx uses)
265 #=================================================================
266 def get_dependencies(prods) :
268 for product in prods:
269 if check_bool(product.disable): continue
271 deps = product.dependencies.split(",")
273 if dep and not dep in list:
276 if product and not product in list:
277 list.append( product.name )
279 return " ".join( list )
281 #==============================================================
282 # Creates dir, returns the part of path that existed early.
283 # Access may be defined.
284 #==============================================================
285 def create_dir (directory, access = 0777):
287 dirs = string.split(directory, "/")
288 existing = ""; dir = ""
291 if len(item) == 0: continue
293 if os.path.exists(dir):
296 os.mkdir(dir, access )
297 #root= existing + "/"+item
298 if dir == existing + "/"+item :
300 #else : root = existing
304 #==============================================================
306 #==============================================================
309 def __init__(self, theName,
312 theSupportred = None,
314 theDependencies = None,
315 theInstalldiskspace = None,
316 theTemporarydiskspace = None,
318 thePickUpEnvironment = None):
322 self.version = theVersion
323 self.install = theInstall
324 self.supported = theSupportred
325 self.disable = theDisable
326 self.dependencies = theDependencies
327 self.installdiskspace = theInstalldiskspace
328 self.temporarydiskspace = theTemporarydiskspace
329 self.script = theScript
330 self.pickupEnv = thePickUpEnvironment
332 #===================================================================
334 #===================================================================
336 def __init__(self, theVersion='', theCaption='', theCopyright='', theLicense='', theOS=''):
337 self.version = theVersion
338 self.caption = theCaption
339 self.copyright = theCopyright
340 self.license = theLicense
344 #===================================================================
346 #===================================================================
348 def __init__(self, theTargetdir=".", theTmpdir="."):
349 self.targetdir = theTargetdir
350 self.tmpdir = theTmpdir
353 #===================================================================
355 #===================================================================
356 class ConfigParser(xmllib.XMLParser):
358 xmllib.XMLParser.__init__(self)
360 self.currentdata = []
364 def handle_data(self, data):
365 self.currentdata.append(data)
367 def start_product(self, attrs):
368 aProduct = Product(attrs['name'],
373 attrs['dependancies'],
374 attrs['installdiskspace'],
375 attrs['temporarydiskspace'],
378 if attrs.has_key( 'pickupenv' ):
379 aProduct.pickupEnv = attrs['pickupenv']
381 self.products.append(aProduct)
383 def end_product(self):
386 def start_config(self, attrs):
387 self.config = Config(attrs['version'],
392 def end_config(self):
395 def start_path (self, attrs):
396 self.path = Path(attrs['targetdir'],
402 def getProduct(self, prod):
403 for product in self.products:
404 if product.name == prod:
408 #================================================================
409 # get the path using file name
410 #================================================================
411 def get_current_path(file_name):
412 path = "."; where = string.rfind(file_name,'/');
414 path = (file_name)[: where]
416 path = os.getcwd() + "/"
419 #================================================================
420 # checks dir existing
421 #================================================================
423 if (os.path.islink(dir)) :
424 native_dir = os.readlink(dir)
425 if not os.path.exists(native_dir) :
426 print "Invalid link " + dir + ". The directory " + native_dir + " a link points to does not exist."
429 if not os.path.exists(dir):
430 print "Directory " + dir + " does not exist"
434 #===============================================================
435 # Checks the disk space. Exit from interpreter if there is no
437 #===============================================================
438 def check_disk_space(products, script_dir, target_dir, tmp_dir):
439 import re, string, os
442 for product in products :
443 product.install = re.sub(r'^\s+', "", product.install)
444 product.install = re.sub(r'\s+$', "", product.install)
446 if check_bool(product.disable) or product.install == "use native" or product.install == "not install":
448 spaces = string.split( product.installdiskspace,',')
449 prod_space = spaces[0]
450 if (len(spaces) == 2 ) and (product.install == "install binaries") :
451 prod_space = spaces[1]
452 install_space = install_space + string.atoi(prod_space)
453 temporary_space = temporary_space + string.atoi(product.temporarydiskspace)
454 res = os.system(scripts_dir + "checkSize.sh" + " " + target_dir + " " + str(install_space))
456 print "There is no enough space to install the products."
459 res = os.system(scripts_dir + "checkSize.sh" + " " + tmp_dir + " " + str(temporary_space))
461 print "There is no enough space for tmp directory."
466 #===============================================================
467 # Removes temporary directory
468 #===============================================================
469 def remove_dir( rem_path = "" ):
470 if len( rem_path ) and os.path.exists( rem_path ):
471 os.system( "rm -rf " + rem_path )
474 #================================================================
476 #================================================================
478 if __name__ == "__main__":
480 cur_dir = get_current_path(sys.argv[0])
482 [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters(sys.argv)
484 # define xml file -----------------
485 if (xml_file is None) :
486 xml_file_name = "config.xml"
487 if os.path.exists("/proc/version"):
488 data = open("/etc/redhat-release").readline()
489 res = re.search(r'Red\s+Hat\s+Linux\s+release\s+([\d.]*)', data)
491 num = re.sub("[.]", "_", (res.groups())[0])
492 filename = "config_RedHat" + num+ ".xml"
493 if (os.path.exists(cur_dir + filename)):
494 xml_file_name = filename
496 xml_file = cur_dir + xml_file_name
497 if xml_file is None or not os.path.exists(xml_file):
498 error_exit("No xml file is found, try to run with options -f <xmlfile>")
500 if not os.access(xml_file, os.R_OK):
501 print "There is no read access for "+ xml_file
504 #---- GUI ----------------
507 if not env.has_key("PATH") :
509 if not env.has_key("LD_LIBRARY_PATH") :
510 env["LD_LIBRARY_PATH"]= ""
512 env["LD_LIBRARY_PATH"] = ".:" + env["LD_LIBRARY_PATH"]
513 env["PATH"] = ".:"+ env["PATH"]
515 sys.exit(os.system("cd " + cur_dir + "; ./bin/SALOME_InstallWizard " + xml_file +"&"))
519 #----- TUI ---------------------
521 #print xml_file, target_dir, tmp_dir, is_gui
523 message("Parsing xml config file: " + xml_file)
524 filehandle = open(xml_file)
525 data = filehandle.read()
527 parser = ConfigParser()
533 what_to_do = { "install sources" : "install_source",
534 "install binaries" : "install_binary",
535 "use native" : "try_native",
536 "not install" : "try_preinstalled"}
537 # define tmp dir -----------
539 tmp_dir = parser.path.tmpdir
540 if tmp_dir is None or tmp_dir == "":
543 tmp_dir = tmp_dir + "/INSTALLWORK" + str(random.randint(10000,100000))
545 if not os.path.exists(tmp_dir):
546 message("Creating temporary directory: " + tmp_dir); root_path = create_dir(tmp_dir, 0755) ;
547 if not os.path.exists(tmp_dir):
548 error_exit("Invalid temporary directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file\n\n")
550 if not os.access(tmp_dir, os.W_OK) :
551 str = "There is no write permissions for directory " + tmp_dir + ". Use -tmp key to set temporary directory or correct xml file"
554 # define target dir --------
555 if target_dir is None:
556 target_dir = parser.path.targetdir
558 if not os.path.exists(target_dir):
559 message("Creating target directory: " + target_dir); create_dir(target_dir, 0755)
560 if not os.path.exists(target_dir):
561 error_exit("Invalid target directory " + target_dir + ". Use -t key to set directory or correct xml file\n\n")
563 if not os.access(target_dir, os.W_OK) :
564 str = "There is no write permissions for directory " + target_dir + ". Use -t key to set target directory or correct xml file."
567 # define products dir ------------
568 source_dir = cur_dir + "Products" ;
569 if not check_dir(source_dir):
570 remove_dir(root_path)
573 subdir = {"install sources" : "SOURCES",
574 "install binaries" : "BINARIES/"+parser.config.os,
579 # define scripts dir ------------
580 scripts_dir = cur_dir + "config_files/"
581 if not check_dir(scripts_dir):
582 remove_dir(root_path)
584 os.chdir(scripts_dir)
586 #list_of_dep = create_levels(parser.products)
587 #list_of_dep = get_dependencies_set(parser.products)
588 list_of_dep = get_dependencies(parser.products)
590 message("Checking available disk space")
591 if check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir) :
593 message("Starting...")
595 for product in parser.products :
597 if check_bool(product.disable): continue
599 message("Processing " + product.name + "...")
600 cmd = scripts_dir + product.script + " " + \
601 what_to_do[product.install]+ " " + \
603 source_dir + "/" + subdir[product.install] + " " + \
605 '"' + list_of_dep + '"' + " " + \
609 #if res : break; # try_preinstalled can return 1
612 message("Creating environment files")
613 for product in parser.products :
615 if check_bool(product.disable): continue
617 if check_bool(product.pickupEnv):
618 cmd = scripts_dir + product.script + " " + \
621 source_dir + "/" + subdir[product.install] + " " + \
623 '"' + list_of_dep + '"' + " " + \
628 message("Cleaning temporary directory")
629 remove_dir(root_path)