4 import sys, os, string, re
6 #==============================================================
8 #==============================================================
10 str = "\nPAL/SALOME 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 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 help information.\n"
38 #==============================================================
40 #==============================================================
41 def error_exit (str = ""):
43 if len(str): res = "\n" + str + "\n"
50 #==============================================================
51 # Cheks whether the passed parameter is a key.
52 #==============================================================
56 return re.match(r'^-[a-zA-Z]', val)
59 #==============================================================
60 # From the list of parameters extracts value following 'key'
61 #==============================================================
62 def extract_parameter ( key, args ) :
65 if ( length == 0 ) : return None
69 for i in range(0, length-1):
71 if ( is_key ( args[i+1]) ) :
72 print " No value after key ", key
76 if ( i < length - 2 and is_key ( args[i+2] ) == 0 ) : #control that only one value follows key
77 #(not a list). In this case params are correct.
78 print "Too much values after key ", key
89 #===============================================================
90 # Extracts list of values following specified 'key' from 'args[]'
91 #===============================================================
92 def extract_list (key, args) :
95 if ( args is None or lenght == 0 ):
101 for i in range(0, length) :
103 if (is_key ( args[i+1])) :
106 for i in range (i+1, lenght):
107 if is_key(args[i]) : break
111 return list; #empty list is returned if no values after key
114 #==============================================================
115 # Method find the $key in the list and return 1 if success
117 #==============================================================
118 def find_key (key, argv) :
120 if (not is_key(key)) : return 0
127 #==============================================================
128 # Parse the list of parameters
129 #==============================================================
130 def parse_parameters (args) :
132 if find_key('-h', args) :
133 print get_help_info();
137 xmlfile = extract_parameter("-f", args)
138 target_dir = extract_parameter("-t", args)
139 tmp_dir = extract_parameter("-tmp", args)
140 if find_key('-b', args):
143 return [xmlfile, target_dir, tmp_dir, is_gui]
146 #=================================================================
147 # The first algorithm to create the dependencies list by their level
148 #=================================================================
149 def get_next_level(list, products):
153 expr = "(" + list[0].name
154 for i in range(1, len(list)):
155 expr = expr + "|"+ list[i].name
158 #expr=re.compile(expr)
160 for product in products:
161 deps = re.sub(r'\s+', "", product.dependencies)
162 if re.search(expr, deps):
163 result.append(product)
168 def create_levels(prods):
171 products = copy.deepcopy(prods)
175 #1. find the products with empty lists of dependencies
177 for product in products:
178 if len(re.sub(r'\s', "", product.dependencies)) == 0 :
182 raise RuntimeError, "Products that depend on nothing are not found"
184 # remove the first level products from the common list of products
185 for product in list :
186 products.remove(product)
191 while (len(products)) :
192 res = get_next_level(list, products)
194 raise RuntimeError, "Empty list of products is found"
197 products.remove(product)
204 for i in result.keys():
205 for product in result[i]:
206 str = str + product.name + " "
210 #=================================================================
211 # The second algorithm
212 #=================================================================
213 def get_dependencies_set(prods) :
217 products = copy.deepcopy(prods)
221 while (len(products)) :
224 #find the products with empty list of dependencies
225 for product in products:
226 product.dependencies = re.sub(r'\s+$', "", product.dependencies)
227 product.dependencies = re.sub(r'^\s+', "", product.dependencies)
229 if len(product.dependencies) == 0 :
230 tmplist.append(product);
231 deps = deps + " " + product.name
235 #remove the products names from other products dependencies
237 products.remove(item)
239 regexpr1 = "((^|,(\s+)?)"+item.name+"$|^"+item.name+"(\s+)?,(\s+)?)"
240 regexpr2 = ",(\s+)?"+item.name+"(\s+)?,(\s+)?"
242 for product in products:
243 product.dependencies = re.sub(r'\s+$', "", product.dependencies)
244 product.dependencies = re.sub(r'^\s+', "", product.dependencies)
246 product.dependencies = re.sub(regexpr1, "", product.dependencies)
247 product.dependencies = re.sub(regexpr2, ",", product.dependencies)
251 #==============================================================
252 # Creates dir, returns the part of path that existed early.
253 # Access may be defined.
254 #==============================================================
255 def create_dir (directory, access = 0777):
257 dirs = string.split(directory, "/")
258 existing = ""; dir = ""
261 if len(item) == 0: continue
263 if os.path.exists(dir):
266 os.mkdir(dir, access )
267 #root= existing + "/"+item
268 if dir == existing + "/"+item :
270 #else : root = existing
274 #==============================================================
276 #==============================================================
279 def __init__(self, theName,
282 theSupportred = None,
284 theDependencies = None,
285 theInstalldiskspace = None,
286 theTemporarydiskspace = None,
288 thePickUpEnvironment = None):
292 self.version = theVersion
293 self.install = theInstall
294 self.supported = theSupportred
295 self.disable = theDisable
296 self.dependencies = theDependencies
297 self.installdiskspace = theInstalldiskspace
298 self.temporarydiskspace = theTemporarydiskspace
299 self.script = theScript
300 self.pickupEnv = thePickUpEnvironment
302 #===================================================================
304 #===================================================================
306 def __init__(self, theVersion='', theCaption='', theCopyright='', theLicense='', theOS=''):
307 self.version = theVersion
308 self.caption = theCaption
309 self.copyright = theCopyright
310 self.license = theLicense
314 #===================================================================
316 #===================================================================
318 def __init__(self, theTargetdir=".", theTmpdir="."):
319 self.targetdir = theTargetdir
320 self.tmpdir = theTmpdir
323 #===================================================================
325 #===================================================================
326 class ConfigParser(xmllib.XMLParser):
328 xmllib.XMLParser.__init__(self)
330 self.currentdata = []
334 def handle_data(self, data):
335 self.currentdata.append(data)
337 def start_product(self, attrs):
338 aProduct = Product(attrs['name'],
343 attrs['dependancies'],
344 attrs['installdiskspace'],
345 attrs['temporarydiskspace'],
348 if attrs.has_key( 'pickupenv' ):
349 aProduct.pickupEnv = attrs['pickupenv']
351 self.products.append(aProduct)
353 def end_product(self):
356 def start_config(self, attrs):
357 self.config = Config(attrs['version'],
362 def end_config(self):
365 def start_path (self, attrs):
366 self.path = Path(attrs['targetdir'],
368 print self.path.tmpdir
373 def getProduct(self, prod):
374 for product in self.products:
375 if product.name == prod:
379 #================================================================
380 # get the path using file name
381 #================================================================
382 def get_current_path(file_name):
383 path = "."; where = string.rfind(file_name,'/');
385 path = (file_name)[: where]
387 path = os.getcwd() + "/"
390 #================================================================
391 # checks dir existing
392 #================================================================
394 if (os.path.islink(dir)) :
395 native_dir = os.readlink(dir)
396 if not os.path.exists(native_dir) :
397 print "Bad link " + native_dir + " to directory " + native_dir + ". The last does not exist."
400 if not os.path.exists(dir):
401 print "Directory " + dir + " does not exist"
405 #===============================================================
406 # Checks the disk space. Exit from interpreter if there is no
408 #===============================================================
409 def check_disk_space(products, script_dir, target_dir, tmp_dir):
410 import re, string, os
413 for product in products :
414 product.install = re.sub(r'^\s+', "", product.install)
415 product.install = re.sub(r'\s+$', "", product.install)
417 if product.disable == "true" or product.install == "use native":
419 spaces = string.split( product.installdiskspace,',')
420 prod_space = spaces[0]
421 if (len(spaces) == 2 ) and (product.install == "install binaries") :
422 prod_space = spaces[1]
423 install_space = install_space + string.atoi(prod_space)
424 temporary_space = temporary_space + string.atoi(product.temporarydiskspace)
425 res = os.system(scripts_dir + "checkSize.sh" + " " + target_dir + " " + str(install_space))
427 print "There is no enough space to install the products."
430 res = os.system(scripts_dir + "checkSize.sh" + " " + tmp_dir + " " + str(temporary_space))
432 print "There is no enough space for tmp directory."
438 #================================================================
440 #================================================================
442 if __name__ == "__main__":
444 cur_dir = get_current_path(sys.argv[0])
446 [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters(sys.argv)
448 # define xml file -----------------
449 if (xml_file is None) :
450 xml_file_name = "config.xml"
451 if os.path.exists("/proc/version"):
452 data = open("/proc/version").readline()
453 res = re.search(r'Red\s+Hat\s+\w+(\s+)?(\d[.]\d)', data)
455 num = re.sub("[.]", "_", (res.groups())[1])
456 filename = "config_RedHat" + num+ ".xml"
457 if (os.path.exists(cur_dir + filename)):
458 xml_file_name = filename
460 xml_file = cur_dir + xml_file_name
461 if xml_file is None or not os.path.exists(xml_file):
462 error_exit("No xml file is found try to run with options -f <xmlfile>")
464 if not os.access(xml_file, os.R_OK):
465 print "There is no acceess to read "+ xml_file
468 #---- GUI ----------------
471 if not env.has_key("PATH") :
473 if not env.has_key("LD_LIBRARY_PATH") :
474 env["LD_LIBRARY_PATH"]= ""
476 env["LD_LIBRARY_PATH"] = ".:" + env["LD_LIBRARY_PATH"]
477 env["PATH"] = ".:"+ env["PATH"]
479 sys.exit(os.system("cd " + cur_dir + "; ./bin/SALOME_InstallWizard " + xml_file +"&"))
483 #----- TUI ---------------------
485 #print xml_file, target_dir, tmp_dir, is_gui
487 filehandle = open(xml_file)
488 data = filehandle.read()
490 parser = ConfigParser()
496 what_to_do = { "install sources":"install_source",
497 "install binaries":"install_binary",
498 "use native":"try_native"}
499 # define tmp dir -----------
501 tmp_dir = parser.path.tmpdir
503 if not os.path.exists(tmp_dir):
504 print "Creating " + tmp_dir; root_path = create_dir(tmp_dir) ;
506 tmp_dir = tmp_dir + "/INSTALLWORK" + str(random.randint(10000,100000))
507 create_dir(tmp_dir,0755)
508 if not os.path.exists(tmp_dir):
509 error_exit("There is no tmp directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file\n\n")
511 if not os.access(tmp_dir, os.W_OK) :
512 str = "We have no write permissions for directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file"
515 # define target dir --------
516 if target_dir is None:
517 target_dir = parser.path.targetdir
519 if not os.path.exists(target_dir):
520 print "Creating " + target_dir; create_dir(target_dir, 0755)
521 if not os.path.exists(target_dir):
522 error_exit("There is no target directory " + target_dir + ". Use -t key to set directory or correct xml file\n\n")
524 if not os.access(target_dir, os.W_OK) :
525 str = "We have no write permissions for directory " + target_dir + ". Use -t key to set directory or correct xml file"
529 # define products dir ------------
530 source_dir = cur_dir + "Products" ;
531 if not check_dir(source_dir):
532 if len(root_path) and os.path.exists(root_path):
533 os.system("rm -r -f "+ root_path)
536 subdir = {"install sources" : "SOURCES",
537 "install binaries" : "BINARIES/"+parser.config.os,
541 # define scripts dir ------------
542 scripts_dir = cur_dir + "config_files/"
543 if not check_dir(scripts_dir):
544 if len(root_path) and os.path.exists(root_path):
545 os.system("rm -r -f "+ root_path)
547 os.chdir(scripts_dir)
549 list_of_dep = create_levels(parser.products)
550 #list_of_dep = get_dependencies_set(parser.products)
552 if check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir) :
555 for product in parser.products :
557 if product.disable == "true": continue
559 cmd = scripts_dir + product.script + " " + \
560 what_to_do[product.install]+ " " + \
562 source_dir + "/" + subdir[product.install] + " " + \
564 '"' + list_of_dep + '"' + " " + \
571 for product in parser.products :
573 if product.disable == "true": continue
575 if product.pickupEnv == "true":
576 cmd = scripts_dir + product.script + " " + \
579 source_dir + "/" + subdir[product.install] + " " + \
581 '"' + list_of_dep + '"' + " " + \
586 if len(root_path) and os.path.exists(root_path):
587 os.system("rm -r -f "+ root_path)