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,
291 self.version = theVersion
292 self.install = theInstall
293 self.supported = theSupportred
294 self.disable = theDisable
295 self.dependencies = theDependencies
296 self.installdiskspace = theInstalldiskspace
297 self.temporarydiskspace = theTemporarydiskspace
298 self.script = theScript
300 #===================================================================
302 #===================================================================
304 def __init__(self, theVersion='', theCaption='', theCopyright='', theLicense='', theOS=''):
305 self.version = theVersion
306 self.caption = theCaption
307 self.copyright = theCopyright
308 self.license = theLicense
312 #===================================================================
314 #===================================================================
316 def __init__(self, theTargetdir=".", theTmpdir="."):
317 self.targetdir = theTargetdir
318 self.tmpdir = theTmpdir
321 #===================================================================
323 #===================================================================
324 class ConfigParser(xmllib.XMLParser):
326 xmllib.XMLParser.__init__(self)
328 self.currentdata = []
332 def handle_data(self, data):
333 self.currentdata.append(data)
335 def start_product(self, attrs):
336 aProduct = Product(attrs['name'],
341 attrs['dependancies'],
342 attrs['installdiskspace'],
343 attrs['temporarydiskspace'],
346 self.products.append(aProduct)
348 def end_product(self):
351 def start_config(self, attrs):
352 self.config = Config(attrs['version'],
357 def end_config(self):
360 def start_path (self, attrs):
361 self.path = Path(attrs['targetdir'],
363 print self.path.tmpdir
368 #================================================================
369 # get the path using file name
370 #================================================================
371 def get_current_path(file_name):
372 path = "."; where = string.rfind(file_name,'/');
374 path = (file_name)[: where]
376 path = os.getcwd() + "/"
379 #================================================================
380 # checks dir existing
381 #================================================================
383 if (os.path.islink(dir)) :
384 native_dir = os.readlink(dir)
385 if not os.path.exists(native_dir) :
386 print "Bad link " + native_dir + " to directory " + native_dir + ". The last does not exist."
389 if not os.path.exists(dir):
390 print "Directory " + dir + " does not exist"
394 #===============================================================
395 # Checks the disk space. Exit from interpreter if there is no
397 #===============================================================
398 def check_disk_space(products, script_dir, target_dir, tmp_dir):
399 import re, string, os
402 for product in products :
403 product.install = re.sub(r'^\s+', "", product.install)
404 product.install = re.sub(r'\s+$', "", product.install)
406 if product.disable == "true" or product.install == "use native":
408 spaces = string.split( product.installdiskspace,',')
409 prod_space = spaces[0]
410 if (len(spaces) == 2 ) and (product.install == "install binaries") :
411 prod_space = spaces[1]
412 install_space = install_space + string.atoi(prod_space)
413 temporary_space = temporary_space + string.atoi(product.temporarydiskspace)
414 res = os.system(scripts_dir + "checkSize.sh" + " " + target_dir + " " + str(install_space))
416 print "There is no enough space to install the products."
419 res = os.system(scripts_dir + "checkSize.sh" + " " + tmp_dir + " " + str(temporary_space))
421 print "There is no enough space for tmp directory."
427 #================================================================
429 #================================================================
431 if __name__ == "__main__":
433 cur_dir = get_current_path(sys.argv[0])
435 [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters(sys.argv)
437 # define xml file -----------------
438 if (xml_file is None) :
439 xml_file_name = "config.xml"
440 if os.path.exists("/proc/version"):
441 data = open("/proc/version").readline()
442 res = re.search(r'Red\s+Hat\s+\w+(\s+)?(\d[.]\d)', data)
444 num = re.sub("[.]", "_", (res.groups())[1])
445 filename = "config_RedHat" + num+ ".xml"
446 if (os.path.exists(cur_dir + filename)):
447 xml_file_name = filename
449 xml_file = cur_dir + xml_file_name
450 if xml_file is None or not os.path.exists(xml_file):
451 error_exit("No xml file is found try to run with options -f <xmlfile>")
453 if not os.access(xml_file, os.R_OK):
454 print "There is no acceess to read "+ xml_file
457 #---- GUI ----------------
460 if not env.has_key("PATH") :
462 if not env.has_key("LD_LIBRARY_PATH") :
463 env["LD_LIBRARY_PATH"]= ""
465 env["LD_LIBRARY_PATH"] = ".:" + env["LD_LIBRARY_PATH"]
466 env["PATH"] = ".:"+ env["PATH"]
468 sys.exit(os.system("cd " + cur_dir + "; ./bin/SALOME_InstallWizard " + xml_file +"&"))
472 #----- TUI ---------------------
474 #print xml_file, target_dir, tmp_dir, is_gui
476 filehandle = open(xml_file)
477 data = filehandle.read()
479 parser = ConfigParser()
485 what_to_do = { "install sources":"install_source",
486 "install binaries":"install_binary",
487 "use native":"try_native"}
488 # define tmp dir -----------
490 tmp_dir = parser.path.tmpdir
492 if not os.path.exists(tmp_dir):
493 print "Creating " + tmp_dir; root_path = create_dir(tmp_dir) ;
495 tmp_dir = tmp_dir + "/INSTALLWORK" + str(random.randint(10000,100000))
496 create_dir(tmp_dir,0755)
497 if not os.path.exists(tmp_dir):
498 error_exit("There is no tmp directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file\n\n")
500 if not os.access(tmp_dir, os.W_OK) :
501 str = "We have no write permissions for directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file"
504 # define target dir --------
505 if target_dir is None:
506 target_dir = parser.path.targetdir
508 if not os.path.exists(target_dir):
509 print "Creating " + target_dir; create_dir(target_dir, 0755)
510 if not os.path.exists(target_dir):
511 error_exit("There is no target directory " + target_dir + ". Use -t key to set directory or correct xml file\n\n")
513 if not os.access(target_dir, os.W_OK) :
514 str = "We have no write permissions for directory " + target_dir + ". Use -t key to set directory or correct xml file"
518 # define products dir ------------
519 source_dir = cur_dir + "Products" ;
520 if not check_dir(source_dir):
521 if len(root_path) and os.path.exists(root_path):
522 os.system("rm -r -f "+ root_path)
525 subdir = {"install sources" : "SOURCES",
526 "install binaries" : "BINARIES/"+parser.config.os,
530 # define scripts dir ------------
531 scripts_dir = cur_dir + "config_files/"
532 if not check_dir(scripts_dir):
533 if len(root_path) and os.path.exists(root_path):
534 os.system("rm -r -f "+ root_path)
536 os.chdir(scripts_dir)
538 list_of_dep = create_levels(parser.products)
539 #list_of_dep = get_dependencies_set(parser.products)
541 if check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir) :
543 for product in parser.products :
545 if product.disable == "true": continue
547 cmd = scripts_dir + product.script + " " + \
548 what_to_do[product.install]+ " " + \
550 source_dir + "/" + subdir[product.install] + " " + \
552 '"' + list_of_dep + '"' + " " + \
558 if len(root_path) and os.path.exists(root_path):
559 os.system("rm -r -f "+ root_path)