From a13a4b1a040e45dae0eec813f20ec6a4ee43e78a Mon Sep 17 00:00:00 2001 From: Serge Rehbinder Date: Thu, 9 Jun 2016 10:25:28 +0200 Subject: [PATCH] Add the job command --- commands/compile.py | 6 +- commands/job.py | 155 ++++++++++++++++++++++++++++++++++++++++++++ commands/log.py | 3 +- commands/prepare.py | 6 +- salomeTools.py | 45 +++++++++---- src/compilation.py | 13 ---- src/environment.py | 2 +- src/logger.py | 16 ++++- src/xsl/command.xsl | 45 ++++++++++--- 9 files changed, 245 insertions(+), 46 deletions(-) create mode 100644 commands/job.py diff --git a/commands/compile.py b/commands/compile.py index 532c880..5ab1c50 100644 --- a/commands/compile.py +++ b/commands/compile.py @@ -399,7 +399,7 @@ def compile_product(sat, p_name_info, config, options, logger, header, len_end): # Logging and sat command call for configure step len_end_line = len_end log_step(logger, header, "CONFIGURE") - res_c, __ = sat.configure(config.VARS.application + " --products " + p_name, + res_c = sat.configure(config.VARS.application + " --products " + p_name, verbose = 0, logger_add_link = logger) log_res_step(logger, res_c) @@ -424,7 +424,7 @@ def compile_product(sat, p_name_info, config, options, logger, header, len_end): # Get the make_flags option if there is any if options.makeflags: make_arguments += " --option -j" + options.makeflags - res_m, __ = sat.make(make_arguments, + res_m = sat.make(make_arguments, verbose = 0, logger_add_link = logger) log_res_step(logger, res_m) @@ -435,7 +435,7 @@ def compile_product(sat, p_name_info, config, options, logger, header, len_end): else: # Logging and sat command call for make install step log_step(logger, header, "MAKE INSTALL") - res_mi, __ = sat.makeinstall(config.VARS.application + + res_mi = sat.makeinstall(config.VARS.application + " --products " + p_name, verbose = 0, diff --git a/commands/job.py b/commands/job.py new file mode 100644 index 0000000..cbaf3ea --- /dev/null +++ b/commands/job.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- +# Copyright (C) 2010-2012 CEA/DEN +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os + +import src +import jobs + +# Define all possible option for the make command : sat make +parser = src.options.Options() +parser.add_option('j', 'jobs_config', 'string', 'jobs_cfg', + _('The name of the config file that contains' + ' the jobs configuration')) +parser.add_option('', 'job', 'string', 'job', + _('The job name from which to execute commands.'), "") + +def description(): + '''method that is called when salomeTools is called with --help option. + + :return: The text to display for the job command description. + :rtype: str + ''' + return _("Executes the commands of the job defined" + " in the jobs configuration file") + +def run(args, runner, logger): + '''method that is called when salomeTools is called with job parameter. + ''' + + # Parse the options + (options, args) = parser.parse_args(args) + + jobs_cfg_files_dir = runner.cfg.SITE.jobs.config_path + + # Make sure the path to the jobs config files directory exists + if not os.path.exists(jobs_cfg_files_dir): + logger.write(_("Creating directory %s\n") % + src.printcolors.printcLabel(jobs_cfg_files_dir), 1) + os.mkdir(jobs_cfg_files_dir) + + # Make sure the jobs_config option has been called + if not options.jobs_cfg: + message = _("The option --jobs_config is required\n") + raise src.SatException( message ) + + # Make sure the job option has been called + if not options.job: + message = _("The option --job is required\n") + raise src.SatException( message ) + + # Make sure the invoked file exists + file_jobs_cfg = os.path.join(jobs_cfg_files_dir, options.jobs_cfg) + if not file_jobs_cfg.endswith('.pyconf'): + file_jobs_cfg += '.pyconf' + + if not os.path.exists(file_jobs_cfg): + message = _("The file %s does not exist.\n") % file_jobs_cfg + logger.write(src.printcolors.printcError(message), 1) + message = _("The possible files are :\n") + logger.write( src.printcolors.printcInfo(message), 1) + for f in sorted(os.listdir(jobs_cfg_files_dir)): + if not f.endswith('.pyconf'): + continue + jobscfgname = f[:-7] + logger.write("%s\n" % jobscfgname) + raise src.SatException( _("No corresponding file") ) + + jobs.print_info(logger, runner.cfg.VARS.dist, file_jobs_cfg) + + # Read the config that is in the file + config_jobs = src.read_config_from_a_file(file_jobs_cfg) + + # Find the job and its commands + found = False + for job in config_jobs.jobs: + if job.name == options.job: + commands = job.commands + found = True + break + if not found: + msg = _("Impossible to find the job \"%(job_name)s\" in " + "%(jobs_config_file)s" % {"job_name" : options.job, + "jobs_config_file" : file_jobs_cfg}) + logger.write(src.printcolors.printcError(msg) + "\n") + return 1 + + # Find the maximum length of the commands in order to format the display + len_max_command = max([len(cmd) for cmd in commands]) + + # Loop over the commands and execute it + res = 0 + nb_pass = 0 + for command in commands: + # Determine if it is a sat command or a shell command + cmd_exe = command.split(" ")[0] # first part + if cmd_exe == "sat": + sat_command_name = command.split(" ")[1] + end_cmd = command.replace(cmd_exe + " " + sat_command_name, "") + else: + sat_command_name = "shell" + end_cmd = "--command " + command + + # Get dynamically the command function to call + sat_command = runner.__getattr__(sat_command_name) + logger.write("Executing " + + src.printcolors.printcLabel(command) + " ", 3) + logger.write("." * (len_max_command - len(command)) + " ", 3) + logger.flush() + # Execute the command + code = sat_command(end_cmd, + batch = True, + verbose = 0, + logger_add_link = logger) + # Print the status of the command + if code == 0: + nb_pass += 1 + logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 3) + else: + res = 1 + logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 3) + + # Print the final state + if res == 0: + final_status = "OK" + else: + final_status = "KO" + + logger.write(_("\nCommands: %(status)s (%(valid_result)d/%(nb_products)d)\n\n") % \ + { 'status': src.printcolors.printc(final_status), + 'valid_result': nb_pass, + 'nb_products': len(commands) }, 3) + + # Print the status and the list of log files + logger.write(_("The status and the list of log files " + "used in the command is the following :\n")) + logger.write("%i\n" % res, 1) + for file_path in logger.l_logFiles: + logger.write("%s\n" % file_path, 1) + + return res \ No newline at end of file diff --git a/commands/log.py b/commands/log.py index c7e4602..ff93fad 100644 --- a/commands/log.py +++ b/commands/log.py @@ -161,7 +161,8 @@ def run(args, runner, logger): 'OUT', os.path.basename(filePath)[:-len('.xml')] + '.txt') remove_log_file(txtFilePath, logger) - # remove also the corresponding pyconf file in OUT directory + # remove also the corresponding pyconf (do not exist 2016-06) + # file in OUT directory pyconfFilePath = os.path.join(os.path.dirname(filePath), 'OUT', os.path.basename(filePath)[:-len('.xml')] + '.pyconf') diff --git a/commands/prepare.py b/commands/prepare.py index 3dedf61..a09f4a4 100644 --- a/commands/prepare.py +++ b/commands/prepare.py @@ -158,7 +158,7 @@ def run(args, runner, logger): msg = _("Clean the source directories ...") logger.write(msg, 3) logger.flush() - res_clean, __ = runner.clean(args_clean, batch=True, verbose = 0, + res_clean = runner.clean(args_clean, batch=True, verbose = 0, logger_add_link = logger) if res_clean == 0: logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 3) @@ -167,7 +167,7 @@ def run(args, runner, logger): if do_source: msg = _("Get the sources of the products ...") logger.write(msg, 5) - res_source, __ = runner.source(args_source, + res_source = runner.source(args_source, logger_add_link = logger) if res_source == 0: logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 5) @@ -176,7 +176,7 @@ def run(args, runner, logger): if do_patch: msg = _("Patch the product sources (if any) ...") logger.write(msg, 5) - res_patch, __ = runner.patch(args_patch, + res_patch = runner.patch(args_patch, logger_add_link = logger) if res_patch == 0: logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 5) diff --git a/salomeTools.py b/salomeTools.py index 4049ed2..e384fc4 100755 --- a/salomeTools.py +++ b/salomeTools.py @@ -171,7 +171,7 @@ class Sat(object): if argv != [''] and argv[0][0] != "-": appliToLoad = argv[0].rstrip('*') argv = argv[1:] - + # read the configuration from all the pyconf files cfgManager = config.ConfigManager() self.cfg = cfgManager.get_config(datadir=self.datadir, @@ -196,15 +196,11 @@ class Sat(object): self.cfg.USER.output_verbose_level = 0 silent = (self.cfg.USER.output_verbose_level == 0) - # create log file, unless the command is called - # with a logger as parameter + # create log file logger_command = src.logger.Logger(self.cfg, silent_sysstd=silent, all_in_terminal=self.options.all_in_terminal) - - if logger_add_link is not None: - logger_add_link.xmlFile.append_node_attrib("Links", attrib={__nameCmd__ : logger_command.logFilePath}) - + try: # Execute the hooks (if there is any) # and run method of the command @@ -226,8 +222,6 @@ class Sat(object): if verbose > -1: self.options.__setattr__("output_verbose_level", verbose_save) - - finally: # put final attributes in xml log file # (end time, total time, ...) and write it launchedCommand = ' '.join([self.cfg.VARS.salometoolsway + @@ -235,9 +229,34 @@ class Sat(object): 'sat', __nameCmd__, args]) - logger_command.end_write({"launchedCommand" : launchedCommand}) + launchedCommand = launchedCommand.replace('"', "'") + + # Add a link to the parent command + if logger_add_link is not None: + xmlLinks = logger_add_link.xmlFile.xmlroot.find( + "Links") + src.xmlManager.add_simple_node(xmlLinks, + "link", + text = logger_command.logFileName, + attrib = {"command" : __nameCmd__, + "passed" : res, + "launchedCommand" : launchedCommand}) + logger_add_link.l_logFiles += logger_command.l_logFiles + + finally: + launchedCommand = ' '.join([self.cfg.VARS.salometoolsway + + os.path.sep + + 'sat', + __nameCmd__, + args]) + launchedCommand = launchedCommand.replace('"', "'") + + # Put the final attributes corresponding to end time and + # Write the file to the hard drive + logger_command.end_write( + {"launchedCommand" : launchedCommand}) - return res, logger_command.logFilePath + return res # Make sure that run_command will be redefined # at each iteration of the loop @@ -414,11 +433,11 @@ if __name__ == "__main__": if options.debug_mode: # call classically the command and if it fails, # show exception and stack (usual python mode) - code, __ = fun_command(' '.join(args[1:])) + code = fun_command(' '.join(args[1:])) else: # catch exception in order to show less verbose but elegant message try: - code, __ = fun_command(' '.join(args[1:])) + code = fun_command(' '.join(args[1:])) except Exception as exc: code = 1 write_exception(exc) diff --git a/src/compilation.py b/src/compilation.py index 153d748..9368db9 100644 --- a/src/compilation.py +++ b/src/compilation.py @@ -44,19 +44,6 @@ class Builder: self.header = "" self.debug_mode = debug_mode - if not self.source_dir.exists() and check_src: - raise src.SatException(_("No sources found for product %(product)s in %(source_dir)s" % \ - { "product": self.product_info.name, "source_dir": self.source_dir } )) - - """ - # check that required modules exist - for dep in self.product_info.depend: - assert dep in self.config.TOOLS.src.product_info, "UNDEFINED product: %s" % dep - dep_info = self.config.TOOLS.src.product_info[dep] - if 'install_dir' in dep_info and not os.path.exists(dep_info.install_dir): - raise src.SatException(_("Module %s is required") % dep) - """ - ## # Shortcut method to log in log file. def log(self, text, level, showInfo=True): diff --git a/src/environment.py b/src/environment.py index 7868ed4..6e2888b 100644 --- a/src/environment.py +++ b/src/environment.py @@ -129,7 +129,7 @@ class Environ: :param key str: the environment variable to check ''' - return self.environ.has_key(key) + return key in self.environ.keys() def set(self, key, value): '''Set the environment variable "key" to value "value" diff --git a/src/logger.py b/src/logger.py index 0e66203..40c0136 100644 --- a/src/logger.py +++ b/src/logger.py @@ -54,10 +54,17 @@ class Logger(object): src.ensure_path_exists(os.path.dirname(logFilePath)) src.ensure_path_exists(os.path.dirname(txtFilePath)) + # The path of the log files (one for sat traces, and the other for + # the system commands traces) self.logFileName = logFileName self.logFilePath = logFilePath self.txtFileName = txtFileName self.txtFilePath = txtFilePath + + # The list of all log files corresponding to the current command and + # the commands called by the current command + self.l_logFiles = [logFilePath, txtFilePath] + # Initialize xml instance and put first fields # like beginTime, user, command, etc... self.xmlFile = xmlManager.XmlLogFile(logFilePath, "SATcommand", @@ -65,6 +72,8 @@ class Logger(object): self.put_initial_xml_fields() # Initialize the txt file for reading self.logTxtFile = open(str(self.txtFilePath), 'w') + # If the option all_in_terminal was called, all the system commands + # are redirected to the terminal if all_in_terminal: self.logTxtFile = sys.__stdout__ @@ -249,6 +258,7 @@ def show_command_log(logFilePath, cmd, application, notShownCommands): # Get the application of the log file logFileXml = src.xmlManager.ReadXmlFile(logFilePath) + if 'application' in logFileXml.xmlroot.keys(): appliLog = logFileXml.xmlroot.get('application') # if it corresponds, then the log has to be shown @@ -282,10 +292,12 @@ def list_log_file(dirPath, expression): date_hour_cmd = fileName.split('_') date_not_formated = date_hour_cmd[0] date = "%s/%s/%s" % (date_not_formated[6:8], - date_not_formated[4:6], date_not_formated[0:4] ) + date_not_formated[4:6], + date_not_formated[0:4]) hour_not_formated = date_hour_cmd[1] hour = "%s:%s:%s" % (hour_not_formated[0:2], - hour_not_formated[2:4], hour_not_formated[4:6]) + hour_not_formated[2:4], + hour_not_formated[4:6]) cmd = date_hour_cmd[2][:-len('.xml')] lRes.append((os.path.join(dirPath, fileName), date_not_formated, date, hour_not_formated, hour, cmd)) diff --git a/src/xsl/command.xsl b/src/xsl/command.xsl index 97c3dd6..6ab0300 100644 --- a/src/xsl/command.xsl +++ b/src/xsl/command.xsl @@ -24,6 +24,8 @@ overflow: auto; max-height: 250px; } + .OK2 { color:#00AA00; } + .KO2 { color:#FF0000; } @@ -49,24 +51,47 @@

Links

- - + + - - + + + +
- - - - +
+ + + Click for more information + OK2 + + + + + + + Click for more information + KO2 + + + + +
-

output

- PENSER A METTRE UN LIEN POUR OUVRIR LE FICHIER AVEC UN EDITEUR DE TEXTE +

output + + Click to open in an editor + + + log + +

+ \ No newline at end of file -- 2.39.2