From: barate Date: Mon, 14 Dec 2009 16:17:53 +0000 (+0000) Subject: Merged from BR_AR X-Git-Tag: V1_1_0_alpha1~2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=44bb5fd4c2d81932971a482ed576d39e33020dcc;p=tools%2Flibbatch.git Merged from BR_AR --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fe08a3c..3a5d9d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,7 @@ ENDIF (BUILD_LOCAL_SUBMISSION) add_subdirectory (LSF) add_subdirectory (PBS) add_subdirectory (SGE) +add_subdirectory (SSH) # Make a copy of the built value and clear the built value for the next run of cmake SET(SRC_FILES ${SRC_FILES_BUILD} CACHE INTERNAL "") @@ -65,6 +66,7 @@ SET(HDR_FILES_BUILD CACHE INTERNAL "") add_library (Batch SHARED ${SRC_FILES}) include_directories(${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Core) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Local) target_link_libraries(Batch ${PTHREAD_LIBRARY}) IF (WIN32) diff --git a/src/Core/Batch_BatchManager_eClient.cxx b/src/Core/Batch_BatchManager_eClient.cxx index c386f2a..81f03a3 100644 --- a/src/Core/Batch_BatchManager_eClient.cxx +++ b/src/Core/Batch_BatchManager_eClient.cxx @@ -37,6 +37,8 @@ #include #include +#include + #ifdef WIN32 #include #include @@ -69,7 +71,8 @@ namespace Batch { // Destructeur BatchManager_eClient::~BatchManager_eClient() { - delete _mpiImpl; + if (_mpiImpl) + delete _mpiImpl; } void BatchManager_eClient::exportInputFiles(const Job& job) @@ -80,7 +83,7 @@ namespace Batch { Versatile::iterator Vit; _username = string(params[USER]); - string subCommand = string("mkdir -p ") + string(params[TMPDIR]); + string subCommand = string("mkdir -p ") + string(params[TMPDIR]) + string("/logs"); string command = _protocol.getExecCommand(subCommand, _hostname, _username); cerr << command.c_str() << endl; status = system(command.c_str()); @@ -147,6 +150,7 @@ namespace Batch { Parametre params = job.getParametre(); Versatile V = params[OUTFILE]; Versatile::iterator Vit; + _username = string(params[USER]); for(Vit=V.begin(); Vit!=V.end(); Vit++) { CoupleType cpt = *static_cast< CoupleType * >(*Vit); @@ -164,6 +168,17 @@ namespace Batch { } } + // Copy logs + int status = _protocol.copyFile(string(params[TMPDIR]) + string("/logs"), _hostname, _username, + directory, "", ""); + if (status) { + std::string mess("Copy logs directory failed ! status is :"); + ostringstream status_str; + status_str << status; + mess += status_str.str(); + cerr << mess << endl; + } + } MpiImpl *BatchManager_eClient::FactoryMpiImpl(string mpiImpl) throw(EmulationException) @@ -181,7 +196,7 @@ namespace Batch { else if(mpiImpl == "prun") return new MpiImpl_PRUN(); else if(mpiImpl == "nompi") - throw EmulationException("you must specify an mpi implementation for batch manager"); + return NULL; else{ ostringstream oss; oss << mpiImpl << " : not yet implemented"; diff --git a/src/Core/Batch_BatchManager_eClient.hxx b/src/Core/Batch_BatchManager_eClient.hxx index 74e8cbc..9a043b9 100644 --- a/src/Core/Batch_BatchManager_eClient.hxx +++ b/src/Core/Batch_BatchManager_eClient.hxx @@ -44,7 +44,7 @@ namespace Batch { class Job; - class BATCH_EXPORT BatchManager_eClient : public BatchManager + class BATCH_EXPORT BatchManager_eClient : virtual public BatchManager { public: // Constructeur et destructeur diff --git a/src/Core/Batch_CommunicationProtocol.cxx b/src/Core/Batch_CommunicationProtocol.cxx index da4d49c..530a5f3 100644 --- a/src/Core/Batch_CommunicationProtocol.cxx +++ b/src/Core/Batch_CommunicationProtocol.cxx @@ -28,6 +28,7 @@ #include #include +#include #include @@ -126,9 +127,9 @@ namespace Batch { for (unsigned int i=0 ; i cmd; cmd.push_back(CP_COMMAND); +#ifndef WIN32 + cmd.push_back("-r"); +#endif cmd.push_back(fixPath(sourcePath)); cmd.push_back(fixPath(destinationPath)); return cmd; diff --git a/src/Core/Batch_CommunicationProtocolSSH.cxx b/src/Core/Batch_CommunicationProtocolSSH.cxx index a9c6590..e6b4198 100644 --- a/src/Core/Batch_CommunicationProtocolSSH.cxx +++ b/src/Core/Batch_CommunicationProtocolSSH.cxx @@ -67,23 +67,28 @@ namespace Batch { if (sourceUser.size() != 0) { fullSource += sourceUser + "@"; } - fullSource += sourceHost + ":"; + fullSource += sourceHost + ":'"; } fullSource += sourcePath; + if (sourceHost.size() != 0) + fullSource += "'"; string fullDestination; if (destinationHost.size() != 0) { if (destinationUser.size() != 0) { fullDestination += destinationUser + "@"; } - fullDestination += destinationHost + ":"; + fullDestination += destinationHost + ":'"; } fullDestination += destinationPath; + if (destinationHost.size() != 0) + fullDestination += "'"; // Option -p is used to keep the same permissions for the destination file // (particularly useful to keep scripts executable when copying them) cmd.push_back(SCP_COMMAND); cmd.push_back("-p"); + cmd.push_back("-r"); cmd.push_back(fullSource); cmd.push_back(fullDestination); diff --git a/src/Core/Batch_Defines.hxx b/src/Core/Batch_Defines.hxx index ab2a237..587e7d7 100644 --- a/src/Core/Batch_Defines.hxx +++ b/src/Core/Batch_Defines.hxx @@ -36,4 +36,10 @@ # define BATCH_EXPORT #endif +#ifdef WIN32 +#define BATCH_CHMOD(name, mode) _chmod(name, mode) +#else +#define BATCH_CHMOD(name, mode) chmod(name, mode) +#endif + #endif diff --git a/src/Core/Batch_FactBatchManager_eClient.hxx b/src/Core/Batch_FactBatchManager_eClient.hxx index d047f55..0e4274f 100644 --- a/src/Core/Batch_FactBatchManager_eClient.hxx +++ b/src/Core/Batch_FactBatchManager_eClient.hxx @@ -49,7 +49,8 @@ namespace Batch { virtual Batch::BatchManager_eClient * operator() (const char * hostname, CommunicationProtocolType protocolType, - const char * mpi) const = 0; + const char * mpi, + int nb_proc_per_node = 1) const = 0; protected: diff --git a/src/Core/Batch_Versatile.hxx b/src/Core/Batch_Versatile.hxx index 6a3a945..2f9f944 100644 --- a/src/Core/Batch_Versatile.hxx +++ b/src/Core/Batch_Versatile.hxx @@ -105,9 +105,9 @@ namespace Batch { std::string getName() const; void setName(const std::string & name); - protected: // Efface tous les elements internes de l'objet virtual void eraseAll(); + protected: DiscriminatorType _discriminator; // type de l'element interne size_type _maxsize; // nombre max d'elements internes diff --git a/src/Core/Test/SimpleParser.cxx b/src/Core/Test/SimpleParser.cxx index 83f6478..9942576 100644 --- a/src/Core/Test/SimpleParser.cxx +++ b/src/Core/Test/SimpleParser.cxx @@ -141,7 +141,6 @@ int SimpleParser::getValueAsInt(const string & key) const throw(ParserException) ostream & operator <<(ostream & os, const SimpleParser & parser) throw() { - os << "Configuration map:" << endl; if (parser._configmap.empty()) { os << "Empty map" << endl; } else { diff --git a/src/Core/Test/Test_SimpleParser.cxx b/src/Core/Test/Test_SimpleParser.cxx index bb446ef..6e60fbc 100644 --- a/src/Core/Test/Test_SimpleParser.cxx +++ b/src/Core/Test/Test_SimpleParser.cxx @@ -55,6 +55,7 @@ int main(int argc, char** argv) } // Print the configuration + cout << "Configuration map:" << endl; cout << parser << endl; return 0; diff --git a/src/LSF/Batch_BatchManager_eLSF.cxx b/src/LSF/Batch_BatchManager_eLSF.cxx index a74a4b2..2f34d04 100644 --- a/src/LSF/Batch_BatchManager_eLSF.cxx +++ b/src/LSF/Batch_BatchManager_eLSF.cxx @@ -38,6 +38,9 @@ #include #include +#include +#include + #ifdef WIN32 #include #else @@ -53,7 +56,8 @@ namespace Batch { BatchManager_eLSF::BatchManager_eLSF(const FactBatchManager * parent, const char * host, CommunicationProtocolType protocolType, const char * mpiImpl) - : BatchManager_eClient(parent, host, protocolType, mpiImpl) + : BatchManager_eClient(parent, host, protocolType, mpiImpl), + BatchManager(parent, host) { // Nothing to do } @@ -69,36 +73,42 @@ namespace Batch { { int status; Parametre params = job.getParametre(); - const std::string dirForTmpFiles = params[TMPDIR]; + const std::string workDir = params[WORKDIR]; const string fileToExecute = params[EXECUTABLE]; - std::string fileNameToExecute; - if( fileToExecute.size() > 0 ){ - string::size_type p1 = fileToExecute.find_last_of("/"); - string::size_type p2 = fileToExecute.find_last_of("."); - fileNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); - } - else - fileNameToExecute = "command"; + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + std::string fileNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); // export input files on cluster + cerr << "Export des fichiers en entree" << endl; exportInputFiles(job); // build batch script for job + cerr << "Construction du script de batch" << endl; buildBatchScript(job); + cerr << "Script envoye" << endl; // define name of log file (local) string logFile = generateTemporaryFileName("LSF-submitlog"); // define command to submit batch - string subCommand = string("cd ") + dirForTmpFiles + "; bsub < " + - fileNameToExecute + "_Batch.sh"; + string subCommand = string("cd ") + workDir + "; bsub < " + fileNameToExecute + "_Batch.sh"; string command = _protocol.getExecCommand(subCommand, _hostname, _username); command += " > "; command += logFile; + command += " 2>&1"; cerr << command.c_str() << endl; status = system(command.c_str()); if(status) - throw EmulationException("Error of connection on remote host"); + { + ifstream error_message(logFile.c_str()); + std::string mess; + std::string temp; + while(std::getline(error_message, temp)) + mess += temp; + error_message.close(); + throw EmulationException("Error of connection on remote host, error was: " + mess); + } // read id of submitted job in log file char line[128]; @@ -201,33 +211,41 @@ namespace Batch { { #ifndef WIN32 //TODO: need for porting on Windows Parametre params = job.getParametre(); - Environnement env = job.getEnvironnement(); - const int nbproc = params[NBPROC]; - const long edt = params[MAXWALLTIME]; - const long mem = params[MAXRAMSIZE]; - const string workDir = params[WORKDIR]; - const std::string dirForTmpFiles = params[TMPDIR]; - const string fileToExecute = params[EXECUTABLE]; - const string home = params[HOMEDIR]; - const std::string queue = params[QUEUE]; - std::string rootNameToExecute; - std::string fileNameToExecute; - std::string filelogtemp; - if( fileToExecute.size() > 0 ){ - string::size_type p1 = fileToExecute.find_last_of("/"); - string::size_type p2 = fileToExecute.find_last_of("."); - rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); - char* basec=strdup(fileToExecute.c_str()); - fileNameToExecute = "~/" + dirForTmpFiles + "/" + string(basename(basec)); - free(basec); - - int idx = dirForTmpFiles.find("Batch/"); - filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length()); - } - else{ - rootNameToExecute = "command"; - } + // Job Parameters + string workDir = ""; + string fileToExecute = ""; + int nbproc = 0; + int edt = 0; + int mem = 0; + string queue = ""; + + // Mandatory parameters + if (params.find(WORKDIR) != params.end()) + workDir = params[WORKDIR].str(); + else + throw EmulationException("params[WORKDIR] is not defined ! Please defined it, cannot submit this job"); + if (params.find(EXECUTABLE) != params.end()) + fileToExecute = params[EXECUTABLE].str(); + else + throw EmulationException("params[EXECUTABLE] is not defined ! Please defined it, cannot submit this job"); + + // Optional parameters + if (params.find(NBPROC) != params.end()) + nbproc = params[NBPROC]; + if (params.find(MAXWALLTIME) != params.end()) + edt = params[MAXWALLTIME]; + if (params.find(MAXRAMSIZE) != params.end()) + mem = params[MAXRAMSIZE]; + if (params.find(QUEUE) != params.end()) + queue = params[QUEUE].str(); + + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + string rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + string fileNameToExecute = fileToExecute.substr(p1+1); + + // Create batch submit file ofstream tempOutputFile; std::string TmpFileName = createAndOpenTemporaryFile("LSF-script", tempOutputFile); @@ -239,43 +257,53 @@ namespace Batch { if( mem > 0 ) tempOutputFile << "#BSUB -M " << mem*1024 << endl ; tempOutputFile << "#BSUB -n " << nbproc << endl ; - if( fileToExecute.size() > 0 ){ - tempOutputFile << "#BSUB -o " << home << "/" << dirForTmpFiles << "/output.log." << filelogtemp << endl ; - tempOutputFile << "#BSUB -e " << home << "/" << dirForTmpFiles << "/error.log." << filelogtemp << endl ; - } - else{ - tempOutputFile << "#BSUB -o " << dirForTmpFiles << "/" << env["LOGFILE"] << ".output.log" << endl ; - tempOutputFile << "#BSUB -e " << dirForTmpFiles << "/" << env["LOGFILE"] << ".error.log" << endl ; - } - if( workDir.size() > 0 ) - tempOutputFile << "cd " << workDir << endl ; - if( fileToExecute.size() > 0 ){ - tempOutputFile << _mpiImpl->boot("",nbproc); - tempOutputFile << _mpiImpl->run("",nbproc,fileNameToExecute); - tempOutputFile << _mpiImpl->halt(); - } + size_t pos = workDir.find("$HOME"); + string baseDir; + if( pos != string::npos ) + baseDir = getHomeDir(workDir) + workDir.substr(pos+5,workDir.length()-5); else{ - tempOutputFile << "source " << env["SOURCEFILE"] << endl ; - tempOutputFile << env["COMMAND"]; + pos = workDir.find("~"); + if( pos != string::npos ) + baseDir = getHomeDir(workDir) + workDir.substr(pos+1,workDir.length()-1); + else + baseDir = workDir; } - + tempOutputFile << "#BSUB -o " << baseDir << "/logs/output.log." << rootNameToExecute << endl ; + tempOutputFile << "#BSUB -e " << baseDir << "/logs/error.log." << rootNameToExecute << endl ; + + tempOutputFile << "cd " << workDir << endl ; + + // generate nodes file + tempOutputFile << "bool=0" << endl; + tempOutputFile << "for i in $LSB_MCPU_HOSTS; do" << endl; + tempOutputFile << " if test $bool = 0; then" << endl; + tempOutputFile << " n=$i" << endl; + tempOutputFile << " bool=1" << endl; + tempOutputFile << " else" << endl; + tempOutputFile << " for ((j=0;j<$i;j++)); do" << endl; + tempOutputFile << " echo $n >> nodesFile" << endl; + tempOutputFile << " done" << endl; + tempOutputFile << " bool=0" << endl; + tempOutputFile << " fi" << endl; + tempOutputFile << "done" << endl; + + // Abstraction of PBS_NODEFILE - TODO + tempOutputFile << "export LIBBATCH_NODEFILE=nodesFile" << endl; + + // Launch the executable + tempOutputFile << "./" + fileNameToExecute << endl; tempOutputFile.flush(); tempOutputFile.close(); -#ifdef WIN32 - _chmod( -#else - chmod( -#endif - TmpFileName.c_str(), 0x1ED); - cerr << TmpFileName.c_str() << endl; + + BATCH_CHMOD(TmpFileName.c_str(), 0x1ED); + cerr << "Batch script file generated is: " << TmpFileName.c_str() << endl; int status = _protocol.copyFile(TmpFileName, "", "", - dirForTmpFiles + "/" + rootNameToExecute + "_Batch.sh", + workDir + "/" + rootNameToExecute + "_Batch.sh", _hostname, _username); if (status) throw EmulationException("Error of connection on remote host"); - remove(TmpFileName.c_str()); #endif } @@ -293,4 +321,24 @@ namespace Batch { return oss.str(); } + std::string BatchManager_eLSF::getHomeDir(std::string tmpdir) + { + std::string home; + int idx = tmpdir.find("Batch/"); + std::string filelogtemp = tmpdir.substr(idx+6, tmpdir.length()); + filelogtemp = "/tmp/logs" + filelogtemp + "_home"; + + string subCommand = string("echo $HOME"); + string command = _protocol.getExecCommand(subCommand, _hostname, _username) + " > " + filelogtemp; + cerr << command.c_str() << endl; + int status = system(command.c_str()); + if (status) + throw EmulationException("Error of launching home command on remote host"); + + std::ifstream file_home(filelogtemp.c_str()); + std::getline(file_home, home); + file_home.close(); + return home; + } + } diff --git a/src/LSF/Batch_BatchManager_eLSF.hxx b/src/LSF/Batch_BatchManager_eLSF.hxx index 09a7f1c..6d48a0e 100644 --- a/src/LSF/Batch_BatchManager_eLSF.hxx +++ b/src/LSF/Batch_BatchManager_eLSF.hxx @@ -72,6 +72,8 @@ namespace Batch { private: + std::string getHomeDir(std::string tmpdir); + #ifdef SWIG public: // Recupere le l'identifiant d'un job deja soumis au BatchManager diff --git a/src/LSF/Batch_FactBatchManager_eLSF.cxx b/src/LSF/Batch_FactBatchManager_eLSF.cxx index f799922..afece45 100644 --- a/src/LSF/Batch_FactBatchManager_eLSF.cxx +++ b/src/LSF/Batch_FactBatchManager_eLSF.cxx @@ -54,7 +54,8 @@ namespace Batch { BatchManager_eClient * FactBatchManager_eLSF::operator() (const char * hostname, CommunicationProtocolType protocolType, - const char * mpiImpl) const + const char * mpiImpl, + int nb_proc_per_node) const { // MESSAGE("Building new BatchManager_LSF on host '" << hostname << "'"); return new BatchManager_eLSF(this, hostname, protocolType, mpiImpl); diff --git a/src/LSF/Batch_FactBatchManager_eLSF.hxx b/src/LSF/Batch_FactBatchManager_eLSF.hxx index 9144f64..3f3c604 100644 --- a/src/LSF/Batch_FactBatchManager_eLSF.hxx +++ b/src/LSF/Batch_FactBatchManager_eLSF.hxx @@ -47,7 +47,8 @@ namespace Batch { virtual BatchManager * operator() (const char * hostname) const; virtual BatchManager_eClient * operator() (const char * hostname, CommunicationProtocolType protocolType, - const char * mpiImpl) const; + const char * mpiImpl, + int nb_proc_per_node = 1) const; protected: diff --git a/src/Local/Batch_BatchManager_Local.cxx b/src/Local/Batch_BatchManager_Local.cxx index 4166e3f..aadbcdc 100644 --- a/src/Local/Batch_BatchManager_Local.cxx +++ b/src/Local/Batch_BatchManager_Local.cxx @@ -443,6 +443,9 @@ namespace Batch { string local = cp.getLocal(); string remote = cp.getRemote(); + std::cerr << workdir << std::endl; + std::cerr << remote << std::endl; + int status = p_ta->getBatchManager().getProtocol().copyFile(local, "", "", workdir + "/" + remote, executionhost, user); @@ -463,6 +466,8 @@ namespace Batch { // On forke/exec un nouveau process pour pouvoir controler le fils // (plus finement qu'avec un appel system) // int rc = system(commande.c_str()); + //char *const parmList[] = {"/usr/bin/ssh", "localhost", "-l", "aribes", "sleep 10 && echo end", NULL}; + //execv("/usr/bin/ssh", parmList); #ifdef WIN32 child = p_ta->launchWin32ChildProcess(); p_ta->pere(child); @@ -594,6 +599,14 @@ namespace Batch { int child_rc = 0; pid_t child_wait_rc = waitpid(child, &child_rc, WNOHANG /* | WUNTRACED */); if (child_wait_rc > 0) { + UNDER_LOCK( cout << "Status is: " << WIFEXITED( child_rc) << endl); + UNDER_LOCK( cout << "Status is: " << WEXITSTATUS( child_rc) << endl); + UNDER_LOCK( cout << "Status is: " << WIFSIGNALED( child_rc) << endl); + UNDER_LOCK( cout << "Status is: " << WTERMSIG( child_rc) << endl); + UNDER_LOCK( cout << "Status is: " << WCOREDUMP( child_rc) << endl); + UNDER_LOCK( cout << "Status is: " << WIFSTOPPED( child_rc) << endl); + UNDER_LOCK( cout << "Status is: " << WSTOPSIG( child_rc) << endl); + UNDER_LOCK( cout << "Status is: " << WIFCONTINUED( child_rc) << endl); if (WIFSTOPPED(child_rc)) { // NOTA : pour rentrer dans cette section, il faut que le flag WUNTRACED // soit positionne dans l'appel a waitpid ci-dessus. Ce flag est couramment @@ -740,6 +753,10 @@ namespace Batch { Parametre param = _job.getParametre(); Parametre::iterator it; + //char *const parmList[] = {"/usr/bin/ssh", "localhost", "-l", "aribes", "sleep 1 && echo end", NULL}; + //int result = execv("/usr/bin/ssh", parmList); + //UNDER_LOCK( cout << "*** debug_command = " << result << endl ); + //UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl ); try { // EXECUTABLE is MANDATORY, if missing, we exit with failure notification @@ -761,6 +778,7 @@ namespace Batch { argv[command.size()] = NULL; UNDER_LOCK( cout << "*** debug_command = " << comstr << endl ); + UNDER_LOCK( cout << "*** debug_command = " << argv[0] << endl ); // Create the environment for the new process. Note (RB): Here we change the environment for // the process launched in local. It would seem more logical to set the environment for the @@ -784,6 +802,10 @@ namespace Batch { envp[i] = NULL; } + //char *const parmList[] = {"/usr/bin/ssh", "localhost", "-l", "aribes", "sleep 1 && echo end", NULL}; + //int result = execv("/usr/bin/ssh", parmList); + //UNDER_LOCK( cout << "*** debug_command = " << result << endl ); + //UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl ); @@ -813,6 +835,10 @@ namespace Batch { } + //char *const parmList[] = {"/usr/bin/ssh", "localhost", "-l", "aribes", "sleep 1 && echo end", NULL}; + //int result = execv("/usr/bin/ssh", parmList); + //UNDER_LOCK( cout << "*** debug_command = " << result << endl ); + //UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl ); // On cree une session pour le fils de facon a ce qu'il ne soit pas // detruit lorsque le shell se termine (le shell ouvre une session et @@ -827,8 +853,8 @@ namespace Batch { // On execute la commande du fils - execve(argv[0], argv, envp); - + int result = execve(argv[0], argv, envp); + UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl ); // No need to deallocate since nothing happens after a successful exec // Normalement on ne devrait jamais arriver ici diff --git a/src/Local/Batch_BatchManager_Local.hxx b/src/Local/Batch_BatchManager_Local.hxx index d6fc0f7..bae6592 100644 --- a/src/Local/Batch_BatchManager_Local.hxx +++ b/src/Local/Batch_BatchManager_Local.hxx @@ -58,7 +58,7 @@ namespace Batch { class FactBatchManager; - class BATCH_EXPORT BatchManager_Local : public BatchManager + class BATCH_EXPORT BatchManager_Local : virtual public BatchManager { private: #ifdef WIN32 diff --git a/src/PBS/Batch_BatchManager_ePBS.cxx b/src/PBS/Batch_BatchManager_ePBS.cxx index 38593b3..fd01bc0 100644 --- a/src/PBS/Batch_BatchManager_ePBS.cxx +++ b/src/PBS/Batch_BatchManager_ePBS.cxx @@ -22,7 +22,7 @@ /* * BatchManager_ePBS.cxx : emulation of PBS client * - * Auteur : Bernard SECHER - CEA DEN + * Auteur : Bernard SECHER - CEA DEN, André RIBES - EDF R&D * Mail : mailto:bernard.secher@cea.fr * Date : Thu Apr 24 10:17:22 2008 * Projet : PAL Salome @@ -37,6 +37,8 @@ #include #include +#include +#include #include #ifdef MSVC @@ -53,10 +55,13 @@ using namespace std; namespace Batch { BatchManager_ePBS::BatchManager_ePBS(const FactBatchManager * parent, const char * host, - CommunicationProtocolType protocolType, const char * mpiImpl) - : BatchManager_eClient(parent, host, protocolType, mpiImpl) + CommunicationProtocolType protocolType, const char * mpiImpl, + int nb_proc_per_node) + : BatchManager_eClient(parent, host, protocolType, mpiImpl), + BatchManager(parent, host) { // Nothing to do + _nb_proc_per_node = nb_proc_per_node; } // Destructeur @@ -70,7 +75,7 @@ namespace Batch { { int status; Parametre params = job.getParametre(); - const std::string dirForTmpFiles = params[TMPDIR]; + const std::string workDir = params[WORKDIR]; const string fileToExecute = params[EXECUTABLE]; string::size_type p1 = fileToExecute.find_last_of("/"); string::size_type p2 = fileToExecute.find_last_of("."); @@ -86,15 +91,23 @@ namespace Batch { string logFile = generateTemporaryFileName("PBS-submitlog"); // define command to submit batch - string subCommand = string("cd ") + dirForTmpFiles + "; qsub " + - fileNameToExecute + "_Batch.sh"; + string subCommand = string("cd ") + workDir + "; qsub " + fileNameToExecute + "_Batch.sh"; string command = _protocol.getExecCommand(subCommand, _hostname, _username); command += " > "; command += logFile; + command += " 2>&1"; cerr << command.c_str() << endl; status = system(command.c_str()); if(status) - throw EmulationException("Error of connection on remote host"); + { + ifstream error_message(logFile.c_str()); + std::string mess; + std::string temp; + while(std::getline(error_message, temp)) + mess += temp; + error_message.close(); + throw EmulationException("Error of connection on remote host, error was: " + mess); + } // read id of submitted job in log file ifstream idfile(logFile.c_str()); @@ -197,91 +210,89 @@ namespace Batch { void BatchManager_ePBS::buildBatchScript(const Job & job) { + std::cerr << "BuildBatchScript" << std::endl; Parametre params = job.getParametre(); Environnement env = job.getEnvironnement(); - const long nbproc = params[NBPROC]; - const long edt = params[MAXWALLTIME]; - const long mem = params[MAXRAMSIZE]; - const string workDir = params[WORKDIR]; - const std::string dirForTmpFiles = params[TMPDIR]; - const string fileToExecute = params[EXECUTABLE]; - const string home = params[HOMEDIR]; - const std::string queue = params[QUEUE]; - std::string rootNameToExecute; - std::string fileNameToExecute; - std::string filelogtemp; - if( fileToExecute.size() > 0 ){ - string::size_type p1 = fileToExecute.find_last_of("/"); - string::size_type p2 = fileToExecute.find_last_of("."); - rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); - -#ifdef MSVC - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; - _splitpath_s(fileToExecute.c_str(), NULL, 0, NULL, 0, fname, _MAX_FNAME, ext, _MAX_EXT); - string execBaseName = string(fname) + ext; -#else - char* basec=strdup(fileToExecute.c_str()); - string execBaseName = string(basename(basec)); - free(basec); -#endif - fileNameToExecute = "~/" + dirForTmpFiles + "/" + execBaseName; + // Job Parameters + string workDir = ""; + string fileToExecute = ""; + int nbproc = 0; + int edt = 0; + int mem = 0; + string queue = ""; + + // Mandatory parameters + if (params.find(WORKDIR) != params.end()) + workDir = params[WORKDIR].str(); + else + throw EmulationException("params[WORKDIR] is not defined ! Please defined it, cannot submit this job"); + if (params.find(EXECUTABLE) != params.end()) + fileToExecute = params[EXECUTABLE].str(); + else + throw EmulationException("params[EXECUTABLE] is not defined ! Please defined it, cannot submit this job"); + + // Optional parameters + if (params.find(NBPROC) != params.end()) + nbproc = params[NBPROC]; + if (params.find(MAXWALLTIME) != params.end()) + edt = params[MAXWALLTIME]; + if (params.find(MAXRAMSIZE) != params.end()) + mem = params[MAXRAMSIZE]; + if (params.find(QUEUE) != params.end()) + queue = params[QUEUE].str(); - int idx = dirForTmpFiles.find("Batch/"); - filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length()); - } - else{ - rootNameToExecute = "command"; - } + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + string rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + string fileNameToExecute = fileToExecute.substr(p1+1); + // Create batch submit file ofstream tempOutputFile; std::string TmpFileName = createAndOpenTemporaryFile("PBS-script", tempOutputFile); tempOutputFile << "#! /bin/sh -f" << endl; + if (nbproc > 0) + { + // Division - arrondi supérieur + int nodes_requested = (nbproc + _nb_proc_per_node -1) / _nb_proc_per_node; + tempOutputFile << "#PBS -l nodes=" << nodes_requested << ":ppn=" << _nb_proc_per_node << endl; + } if (queue != "") - tempOutputFile << "#BSUB -q " << queue << endl; + tempOutputFile << "#PBS -q " << queue << endl; if( edt > 0 ) - tempOutputFile << "#PBS -l walltime=" << edt*60 << endl ; + tempOutputFile << "#PBS -l walltime=" << edt*60 << endl; if( mem > 0 ) - tempOutputFile << "#PBS -l mem=" << mem << "mb" << endl ; - if( fileToExecute.size() > 0 ){ - tempOutputFile << "#PBS -o " << home << "/" << dirForTmpFiles << "/output.log." << filelogtemp << endl ; - tempOutputFile << "#PBS -e " << home << "/" << dirForTmpFiles << "/error.log." << filelogtemp << endl ; - } - else{ - tempOutputFile << "#PBS -o " << dirForTmpFiles << "/" << env["LOGFILE"] << ".output.log" << endl ; - tempOutputFile << "#PBS -e " << dirForTmpFiles << "/" << env["LOGFILE"] << ".error.log" << endl ; - } - if( workDir.size() > 0 ) - tempOutputFile << "cd " << workDir << endl ; - if( fileToExecute.size() > 0 ){ - tempOutputFile << _mpiImpl->boot("${PBS_NODEFILE}",nbproc); - tempOutputFile << _mpiImpl->run("${PBS_NODEFILE}",nbproc,fileNameToExecute); - tempOutputFile << _mpiImpl->halt(); - } - else{ - tempOutputFile << "source " << env["SOURCEFILE"] << endl ; - tempOutputFile << env["COMMAND"]; + tempOutputFile << "#PBS -l mem=" << mem << "kb" << endl; + tempOutputFile << "#PBS -o " << workDir << "/logs/output.log." << rootNameToExecute << endl; + tempOutputFile << "#PBS -e " << workDir << "/logs/error.log." << rootNameToExecute << endl; + + // Define environment for the job + if (!env.empty()) { + tempOutputFile << "#PBS -v "; + Environnement::const_iterator iter; + for (iter = env.begin() ; iter != env.end() ; ++iter) { + tempOutputFile << iter->first << "=" << iter->second << ","; + } + tempOutputFile << endl; } + // Abstraction of PBS_NODEFILE - TODO + tempOutputFile << "export LIBBATCH_NODEFILE=$PBS_NODEFILE" << endl; + + // Launch the executable + tempOutputFile << "cd " << workDir << endl; + tempOutputFile << "./" + fileNameToExecute << endl; tempOutputFile.flush(); tempOutputFile.close(); -#ifdef WIN32 - _chmod( -#else - chmod( -#endif - TmpFileName.c_str(), 0x1ED); - cerr << TmpFileName.c_str() << endl; + + BATCH_CHMOD(TmpFileName.c_str(), 0x1ED); + cerr << "Batch script file generated is: " << TmpFileName.c_str() << endl; int status = _protocol.copyFile(TmpFileName, "", "", - dirForTmpFiles + "/" + rootNameToExecute + "_Batch.sh", + workDir + "/" + rootNameToExecute + "_Batch.sh", _hostname, _username); if (status) - throw EmulationException("Error of connection on remote host"); - - remove(TmpFileName.c_str()); + throw EmulationException("Error of connection on remote host, cannot copy batch submission file"); } - } diff --git a/src/PBS/Batch_BatchManager_ePBS.hxx b/src/PBS/Batch_BatchManager_ePBS.hxx index a2f9457..9d7e8ce 100644 --- a/src/PBS/Batch_BatchManager_ePBS.hxx +++ b/src/PBS/Batch_BatchManager_ePBS.hxx @@ -45,7 +45,8 @@ namespace Batch { public: // Constructeur et destructeur BatchManager_ePBS(const FactBatchManager * parent, const char * host="localhost", - CommunicationProtocolType protocolType = SSH, const char * mpiImpl="nompi"); // connexion a la machine host + CommunicationProtocolType protocolType = SSH, const char * mpiImpl="nompi", + int nb_proc_per_node=1); // connexion a la machine host virtual ~BatchManager_ePBS(); // Recupere le nom du serveur par defaut @@ -70,6 +71,7 @@ namespace Batch { void buildBatchScript(const Job & job); private: + int _nb_proc_per_node; #ifdef SWIG public: diff --git a/src/PBS/Batch_FactBatchManager_ePBS.cxx b/src/PBS/Batch_FactBatchManager_ePBS.cxx index 2984a3c..e017f2f 100644 --- a/src/PBS/Batch_FactBatchManager_ePBS.cxx +++ b/src/PBS/Batch_FactBatchManager_ePBS.cxx @@ -58,10 +58,11 @@ namespace Batch { BatchManager_eClient * FactBatchManager_ePBS::operator() (const char * hostname, CommunicationProtocolType protocolType, - const char * mpiImpl) const + const char * mpiImpl, + int nb_proc_per_node) const { // MESSAGE("Building new BatchManager_PBS on host '" << hostname << "'"); - return new BatchManager_ePBS(this, hostname, protocolType, mpiImpl); + return new BatchManager_ePBS(this, hostname, protocolType, mpiImpl, nb_proc_per_node); } diff --git a/src/PBS/Batch_FactBatchManager_ePBS.hxx b/src/PBS/Batch_FactBatchManager_ePBS.hxx index 930552d..3cf5d3a 100644 --- a/src/PBS/Batch_FactBatchManager_ePBS.hxx +++ b/src/PBS/Batch_FactBatchManager_ePBS.hxx @@ -52,7 +52,8 @@ namespace Batch { virtual BatchManager * operator() (const char * hostname) const; virtual BatchManager_eClient * operator() (const char * hostname, CommunicationProtocolType protocolType, - const char * mpiImpl) const; + const char * mpiImpl, + int nb_proc_per_node = 1) const; protected: diff --git a/src/PBS/Test/CMakeLists.txt b/src/PBS/Test/CMakeLists.txt index f584265..a96946a 100644 --- a/src/PBS/Test/CMakeLists.txt +++ b/src/PBS/Test/CMakeLists.txt @@ -32,16 +32,15 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) include_directories(${CMAKE_CURRENT_BINARY_DIR}) # Build the test programs and add the tests +add_executable(Test_ePBS Test_ePBS.cxx) +target_link_libraries(Test_ePBS Batch SimpleParser) + IF (HAS_SSH) - add_executable(Test_ePBS_SSH Test_ePBS_SSH.cxx) - target_link_libraries(Test_ePBS_SSH Batch SimpleParser) - ADD_TEST(ePBS_SSH Test_ePBS_SSH) + ADD_TEST(ePBS_SSH Test_ePBS SSH) ENDIF (HAS_SSH) IF (HAS_RSH) - add_executable(Test_ePBS_RSH Test_ePBS_RSH.cxx) - target_link_libraries(Test_ePBS_RSH Batch SimpleParser) - ADD_TEST(ePBS_RSH Test_ePBS_RSH) + ADD_TEST(ePBS_RSH Test_ePBS RSH) ENDIF (HAS_RSH) IF (BUILD_PBS_INTERFACE AND PBS_FOUND) diff --git a/src/PBS/Test/Test_PBS.cxx b/src/PBS/Test/Test_PBS.cxx index e58278d..5ceb09f 100644 --- a/src/PBS/Test/Test_PBS.cxx +++ b/src/PBS/Test/Test_PBS.cxx @@ -47,6 +47,8 @@ using namespace std; using namespace Batch; +const int MAX_SLEEP_TIME = 600; + int main(int argc, char** argv) { cout << "*******************************************************************************************" << endl; @@ -92,6 +94,7 @@ int main(int argc, char** argv) job.setParametre(p); // ... and its environment Environnement e; + e["MYENVVAR"] = "MYVALUE"; job.setEnvironnement(e); cout << job << endl; @@ -107,13 +110,28 @@ int main(int argc, char** argv) cout << jobid.__repr__() << endl; // Wait for the end of the job - string state = "Undefined"; - for (int i=0 ; i -1); + bool timeoutReached = (testTimeout && time >= timeout); + JobInfo jinfo = jobid.queryJob(); + string state = jinfo.getParametre()["STATE"].str(); + cout << "State is \"" << state << "\""; + while (!timeoutReached && state != "U" && state != "C") { + cout << ", sleeping " << sleeptime << "s..." << endl; + sleep(sleeptime); + time += sleeptime; + timeoutReached = (testTimeout && time >= timeout); + sleeptime *= 2; + if (testTimeout && sleeptime > timeout - time) + sleeptime = timeout - time; + if (sleeptime > MAX_SLEEP_TIME) + sleeptime = MAX_SLEEP_TIME; + jinfo = jobid.queryJob(); state = jinfo.getParametre()["STATE"].str(); - cout << "State is \"" << state << "\"" << endl; + cout << "State is \"" << state << "\""; } + cout << endl; if (state == "U" || state == "C") { cout << "Job " << jobid.__repr__() << " is done" << endl; @@ -131,16 +149,21 @@ int main(int argc, char** argv) } // test the result file - string exp = "c = 12"; - string res; - ifstream f("result.txt"); - getline(f, res); - f.close(); - - cout << "result found : " << res << ", expected : " << exp << endl; - - if (res == exp) - return 0; - else + try { + SimpleParser resultParser; + resultParser.parse("result.txt"); + cout << "Result:" << endl << resultParser; + const string & envvar = resultParser.getValue("MYENVVAR"); + int result = resultParser.getValueAsInt("c"); + if (envvar == "MYVALUE" && result == 12) { + cout << "OK, Expected result found." << endl; + return 0; + } else { + cerr << "Error, result is not the expected one (MYENVVAR = MYVALUE, c = 12)." << endl; + return 1; + } + } catch (ParserException e) { + cerr << "Parser error on result file: " << e.what() << endl; return 1; + } } diff --git a/src/PBS/Test/Test_ePBS.cxx b/src/PBS/Test/Test_ePBS.cxx new file mode 100644 index 0000000..b603d75 --- /dev/null +++ b/src/PBS/Test/Test_ePBS.cxx @@ -0,0 +1,188 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +/* + * Test_ePBS.cxx : + * + * Author : Renaud BARATE - EDF R&D + * Date : April 2009 + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef WIN32 +#include +#define sleep(seconds) Sleep((seconds)*1000) +#define usleep(useconds) Sleep((useconds)/1000) +#endif + +using namespace std; +using namespace Batch; + +const int MAX_SLEEP_TIME = 600; + +void print_usage() +{ + cout << "usage: Test_ePBS PROTOCOL" << endl; + cout << " PROTOCOL \"SSH\" or \"RSH\"" << endl; +} + +int main(int argc, char** argv) +{ + // Parse argument + if (argc != 2) { + print_usage(); + return 1; + } + CommunicationProtocolType protocol; + if (strcmp(argv[1], "SSH") == 0) + protocol = SSH; + else if (strcmp(argv[1], "RSH") == 0) + protocol = RSH; + else { + print_usage(); + return 1; + } + + cout << "*******************************************************************************************" << endl; + cout << "This program tests the batch submission based on PBS emulation. Passwordless authentication" << endl; + cout << "must be used for this test to pass. For SSH, this can be configured with ssh-agent for" << endl; + cout << "instance. For RSH, this can be configured with the .rhosts file." << endl; + cout << "*******************************************************************************************" << endl; + + // eventually remove any previous result + remove("result.txt"); + + try { + // Parse the test configuration file + SimpleParser parser; + parser.parseTestConfigFile(); + const string & homedir = parser.getValue("TEST_EPBS_HOMEDIR"); + const string & host = parser.getValue("TEST_EPBS_HOST"); + const string & user = parser.getValue("TEST_EPBS_USER"); + const string & queue = parser.getValue("TEST_EPBS_QUEUE"); + int timeout = parser.getValueAsInt("TEST_EPBS_TIMEOUT"); + + // Define the job... + Job job; + // ... and its parameters ... + Parametre p; + p["EXECUTABLE"] = "./test-script.sh"; + p["NAME"] = string("Test_ePBS_") + argv[1]; + p["WORKDIR"] = homedir + "/tmp/Batch"; + p["INFILE"] = Couple("seta.sh", "tmp/Batch/seta.sh"); + p["INFILE"] += Couple("setb.sh", "tmp/Batch/setb.sh"); + p["OUTFILE"] = Couple("result.txt", "tmp/Batch/result.txt"); + p["TMPDIR"] = "tmp/Batch/"; + p["USER"] = user; + p["NBPROC"] = 1; + p["MAXWALLTIME"] = 1; + p["MAXRAMSIZE"] = 1000; + p["HOMEDIR"] = homedir; + p["QUEUE"] = queue; + job.setParametre(p); + // ... and its environment + Environnement e; + e["MYENVVAR"] = "MYVALUE"; + job.setEnvironnement(e); + cout << job << endl; + + // Get the catalog + BatchManagerCatalog& c = BatchManagerCatalog::getInstance(); + + // Create a BatchManager of type ePBS on localhost + FactBatchManager_eClient * fbm = (FactBatchManager_eClient *)(c("ePBS")); + BatchManager_eClient * bm = (*fbm)(host.c_str(), protocol, "lam"); + + // Submit the job to the BatchManager + JobId jobid = bm->submitJob(job); + cout << jobid.__repr__() << endl; + + // Wait for the end of the job + int time = 0; + int sleeptime = 1; + bool testTimeout = (timeout > -1); + bool timeoutReached = (testTimeout && time >= timeout); + JobInfo jinfo = jobid.queryJob(); + string state = jinfo.getParametre()["STATE"].str(); + cout << "State is \"" << state << "\""; + while (!timeoutReached && state != "U" && state != "C") { + cout << ", sleeping " << sleeptime << "s..." << endl; + sleep(sleeptime); + time += sleeptime; + timeoutReached = (testTimeout && time >= timeout); + sleeptime *= 2; + if (testTimeout && sleeptime > timeout - time) + sleeptime = timeout - time; + if (sleeptime > MAX_SLEEP_TIME) + sleeptime = MAX_SLEEP_TIME; + jinfo = jobid.queryJob(); + state = jinfo.getParametre()["STATE"].str(); + cout << "State is \"" << state << "\""; + } + cout << endl; + + if (state == "U" || state == "C") { + cout << "Job " << jobid.__repr__() << " is done" << endl; + bm->importOutputFiles(job, "."); + } else { + cerr << "Timeout while executing job" << endl; + return 1; + } + + } catch (GenericException e) { + cerr << "Error: " << e << endl; + return 1; + } catch (ParserException e) { + cerr << "Parser error: " << e.what() << endl; + return 1; + } + + // test the result file + try { + SimpleParser resultParser; + resultParser.parse("result.txt"); + cout << "Result:" << endl << resultParser; + const string & envvar = resultParser.getValue("MYENVVAR"); + int result = resultParser.getValueAsInt("c"); + if (envvar == "MYVALUE" && result == 12) { + cout << "OK, Expected result found." << endl; + return 0; + } else { + cerr << "Error, result is not the expected one (MYENVVAR = MYVALUE, c = 12)." << endl; + return 1; + } + } catch (ParserException e) { + cerr << "Parser error on result file: " << e.what() << endl; + return 1; + } +} diff --git a/src/PBS/Test/test-script.sh b/src/PBS/Test/test-script.sh index 64eb2fa..ae952c8 100755 --- a/src/PBS/Test/test-script.sh +++ b/src/PBS/Test/test-script.sh @@ -5,4 +5,5 @@ source setb.sh c=`expr $a "*" $b` -echo "c = $c" > result.txt +echo "MYENVVAR = $MYENVVAR" > result.txt +echo "c = $c" >> result.txt diff --git a/src/SGE/Batch_BatchManager_eSGE.cxx b/src/SGE/Batch_BatchManager_eSGE.cxx index dc7845e..98d9085 100644 --- a/src/SGE/Batch_BatchManager_eSGE.cxx +++ b/src/SGE/Batch_BatchManager_eSGE.cxx @@ -36,6 +36,10 @@ #include #include #include + +#include +#include + #ifdef WIN32 #include #else @@ -51,7 +55,8 @@ namespace Batch { BatchManager_eSGE::BatchManager_eSGE(const FactBatchManager * parent, const char * host, CommunicationProtocolType protocolType, const char * mpiImpl) - : BatchManager_eClient(parent, host, protocolType, mpiImpl) + : BatchManager_eClient(parent, host, protocolType, mpiImpl), + BatchManager(parent, host) { // Nothing to do } @@ -67,7 +72,7 @@ namespace Batch { { int status; Parametre params = job.getParametre(); - const std::string dirForTmpFiles = params[TMPDIR]; + const std::string workDir = params[WORKDIR]; const string fileToExecute = params[EXECUTABLE]; string::size_type p1 = fileToExecute.find_last_of("/"); string::size_type p2 = fileToExecute.find_last_of("."); @@ -83,15 +88,23 @@ namespace Batch { string logFile = generateTemporaryFileName("SGE-submitlog"); // define command to submit batch - string subCommand = string("cd ") + dirForTmpFiles + "; qsub " + - fileNameToExecute + "_Batch.sh"; + string subCommand = string("cd ") + workDir + "; qsub " + fileNameToExecute + "_Batch.sh"; string command = _protocol.getExecCommand(subCommand, _hostname, _username); command += " > "; command += logFile; + command += " 2>&1"; cerr << command.c_str() << endl; status = system(command.c_str()); if(status) - throw EmulationException("Error of connection on remote host"); + { + ifstream error_message(logFile.c_str()); + std::string mess; + std::string temp; + while(std::getline(error_message, temp)) + mess += temp; + error_message.close(); + throw EmulationException("Error of connection on remote host, error was: " + mess); + } // read id of submitted job in log file char line[128]; @@ -191,32 +204,43 @@ namespace Batch { { #ifndef WIN32 //TODO porting on Win32 platform + std::cerr << "BuildBatchScript" << std::endl; Parametre params = job.getParametre(); - Environnement env = job.getEnvironnement(); - const long nbproc = params[NBPROC]; - const long edt = params[MAXWALLTIME]; - const long mem = params[MAXRAMSIZE]; - const string workDir = params[WORKDIR]; - const std::string dirForTmpFiles = params[TMPDIR]; - const string fileToExecute = params[EXECUTABLE]; - const string home = params[HOMEDIR]; - const std::string queue = params[QUEUE]; - std::string rootNameToExecute; - std::string fileNameToExecute; - std::string filelogtemp; - if( fileToExecute.size() > 0 ){ - string::size_type p1 = fileToExecute.find_last_of("/"); - string::size_type p2 = fileToExecute.find_last_of("."); - rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); - fileNameToExecute = "~/" + dirForTmpFiles + "/" + string(basename((char *) fileToExecute.c_str())); - - int idx = dirForTmpFiles.find("Batch/"); - filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length()); - } - else{ - rootNameToExecute = "command"; - } + // Job Parameters + string workDir = ""; + string fileToExecute = ""; + int nbproc = 0; + int edt = 0; + int mem = 0; + string queue = ""; + + // Mandatory parameters + if (params.find(WORKDIR) != params.end()) + workDir = params[WORKDIR].str(); + else + throw EmulationException("params[WORKDIR] is not defined ! Please defined it, cannot submit this job"); + if (params.find(EXECUTABLE) != params.end()) + fileToExecute = params[EXECUTABLE].str(); + else + throw EmulationException("params[EXECUTABLE] is not defined ! Please defined it, cannot submit this job"); + + // Optional parameters + if (params.find(NBPROC) != params.end()) + nbproc = params[NBPROC]; + if (params.find(MAXWALLTIME) != params.end()) + edt = params[MAXWALLTIME]; + if (params.find(MAXRAMSIZE) != params.end()) + mem = params[MAXRAMSIZE]; + if (params.find(QUEUE) != params.end()) + queue = params[QUEUE].str(); + + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + string rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + string fileNameToExecute = fileToExecute.substr(p1+1); + + // Create batch submit file ofstream tempOutputFile; std::string TmpFileName = createAndOpenTemporaryFile("SGE-script", tempOutputFile); @@ -228,38 +252,27 @@ namespace Batch { tempOutputFile << "#$ -l h_rt=" << getWallTime(edt) << endl ; if( mem > 0 ) tempOutputFile << "#$ -l h_vmem=" << mem << "M" << endl ; - if( fileToExecute.size() > 0 ){ - tempOutputFile << "#$ -o " << home << "/" << dirForTmpFiles << "/output.log." << filelogtemp << endl ; - tempOutputFile << "#$ -e " << home << "/" << dirForTmpFiles << "/error.log." << filelogtemp << endl ; - } - else{ - tempOutputFile << "#$ -o " << dirForTmpFiles << "/" << env["LOGFILE"] << ".output.log" << endl ; - tempOutputFile << "#$ -e " << dirForTmpFiles << "/" << env["LOGFILE"] << ".error.log" << endl ; - } - if( workDir.size() > 0 ) - tempOutputFile << "cd " << workDir << endl ; - if( fileToExecute.size() > 0 ){ - tempOutputFile << _mpiImpl->boot("",nbproc); - tempOutputFile << _mpiImpl->run("${TMPDIR}/machines",nbproc,fileNameToExecute); - tempOutputFile << _mpiImpl->halt(); - } - else{ - tempOutputFile << "source " << env["SOURCEFILE"] << endl ; - tempOutputFile << env["COMMAND"]; - } + tempOutputFile << "#$ -o " << workDir << "/logs/output.log." << rootNameToExecute << endl ; + tempOutputFile << "#$ -e " << workDir << "/logs/error.log." << rootNameToExecute << endl ; + // Abstraction of PBS_NODEFILE - TODO + tempOutputFile << "export LIBBATCH_NODEFILE=$TMPDIR/machines" << endl; + + // Launch the executable + tempOutputFile << "cd " << workDir << endl ; + tempOutputFile << "./" + fileNameToExecute << endl; tempOutputFile.flush(); tempOutputFile.close(); - chmod(TmpFileName.c_str(), 0x1ED); - cerr << TmpFileName.c_str() << endl; + + BATCH_CHMOD(TmpFileName.c_str(), 0x1ED); + cerr << "Batch script file generated is: " << TmpFileName.c_str() << endl; int status = _protocol.copyFile(TmpFileName, "", "", - dirForTmpFiles + "/" + rootNameToExecute + "_Batch.sh", + workDir + "/" + rootNameToExecute + "_Batch.sh", _hostname, _username); if (status) throw EmulationException("Error of connection on remote host"); - remove(TmpFileName.c_str()); #endif //WIN32 } diff --git a/src/SGE/Batch_FactBatchManager_eSGE.cxx b/src/SGE/Batch_FactBatchManager_eSGE.cxx index 7bc44c0..a1bdcc2 100644 --- a/src/SGE/Batch_FactBatchManager_eSGE.cxx +++ b/src/SGE/Batch_FactBatchManager_eSGE.cxx @@ -56,7 +56,8 @@ namespace Batch { BatchManager_eClient * FactBatchManager_eSGE::operator() (const char * hostname, CommunicationProtocolType protocolType, - const char * mpiImpl) const + const char * mpiImpl, + int nb_proc_per_node) const { // MESSAGE("Building new BatchManager_SGE on host '" << hostname << "'"); return new BatchManager_eSGE(this, hostname, protocolType, mpiImpl); diff --git a/src/SGE/Batch_FactBatchManager_eSGE.hxx b/src/SGE/Batch_FactBatchManager_eSGE.hxx index 6dae360..509220a 100644 --- a/src/SGE/Batch_FactBatchManager_eSGE.hxx +++ b/src/SGE/Batch_FactBatchManager_eSGE.hxx @@ -48,7 +48,8 @@ namespace Batch { virtual BatchManager * operator() (const char * hostname) const; virtual BatchManager_eClient * operator() (const char * hostname, CommunicationProtocolType protocolType, - const char * mpiImpl) const; + const char * mpiImpl, + int nb_proc_per_node = 1) const; protected: diff --git a/src/SSH/Batch_BatchManager_eSSH.cxx b/src/SSH/Batch_BatchManager_eSSH.cxx new file mode 100644 index 0000000..11784b3 --- /dev/null +++ b/src/SSH/Batch_BatchManager_eSSH.cxx @@ -0,0 +1,226 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +/* + * BatchManager_eSSH.cxx : emulation of SSH client + * + * Auteur : André RIBES - EDF R&D + * Date : Octobre 2009 + */ + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef MSVC +#include +#else +#include +#endif + +#include "Batch_BatchManager_eSSH.hxx" +#include "Batch_JobInfo_eSSH.hxx" + +using namespace std; + +namespace Batch { + + BatchManager_eSSH::BatchManager_eSSH(const FactBatchManager * parent, const char * host, + CommunicationProtocolType protocolType, const char * mpiImpl) + : BatchManager_eClient(parent, host, protocolType, mpiImpl), + BatchManager_Local(parent, host, protocolType), + BatchManager(parent, host) + { + // Nothing to do + } + + // Destructeur + BatchManager_eSSH::~BatchManager_eSSH() + { + // Nothing to do + } + + // Methode pour le controle des jobs : soumet un job au gestionnaire + const JobId BatchManager_eSSH::submitJob(const Job & job) + { + // export input files on cluster + std::cerr << "BatchManager_eSSH::submitJob exportInputFiles" << std::endl; + Parametre param = job.getParametre(); + + // Input files copy + exportInputFiles(job); + + // Launch job + // Patch until Local Manager is patched + std::string executable = param[EXECUTABLE].str(); + std::string::size_type p1 = executable.find_last_of("/"); + std::string fileNameToExecute = "./" + executable.substr(p1+1); + Parametre new_param(param); + new_param[INFILE].eraseAll(); + new_param[OUTFILE].eraseAll(); + new_param[EXECUTABLE] = fileNameToExecute; + new_param[EXECUTIONHOST] = _hostname; + Job * j = new Job(new_param); + + + std::cerr << "BatchManager_eSSH::submitJob Local submitJob" << std::endl; + JobId id = BatchManager_Local::submitJob(*j); + delete j; + return id; + } + + // Methode pour le controle des jobs : retire un job du gestionnaire + void BatchManager_eSSH::deleteJob(const JobId & jobid) + { + BatchManager_Local::deleteJob(jobid); + } + + // Methode pour le controle des jobs : renvoie l'etat du job + JobInfo BatchManager_eSSH::queryJob(const JobId & jobid) + { + return BatchManager_Local::queryJob(jobid); + } + + // Methode pour le controle des jobs : suspend un job en file d'attente + void BatchManager_eSSH::holdJob(const JobId & jobid) + { + BatchManager_Local::holdJob(jobid); + } + + // Methode pour le controle des jobs : relache un job suspendu + void BatchManager_eSSH::releaseJob(const JobId & jobid) + { + BatchManager_Local::releaseJob(jobid); + } + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_eSSH::alterJob(const JobId & jobid, const Parametre & param, const Environnement & env) + { + BatchManager_Local::alterJob(jobid, param, env); + } + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_eSSH::alterJob(const JobId & jobid, const Parametre & param) + { + BatchManager_Local::alterJob(jobid, param); + } + + // Methode pour le controle des jobs : modifie un job en file d'attente + void BatchManager_eSSH::alterJob(const JobId & jobid, const Environnement & env) + { + BatchManager_Local::alterJob(jobid, env); + } + + void BatchManager_eSSH::buildBatchScript(const Job & job) + { + Parametre params = job.getParametre(); + Environnement env = job.getEnvironnement(); + const long nbproc = params[NBPROC]; + const long edt = params[MAXWALLTIME]; + const long mem = params[MAXRAMSIZE]; + const string workDir = params[WORKDIR]; + const std::string dirForTmpFiles = params[TMPDIR]; + const string fileToExecute = params[EXECUTABLE]; + const string home = params[HOMEDIR]; + const std::string queue = params[QUEUE]; + std::string rootNameToExecute; + std::string fileNameToExecute; + std::string filelogtemp; + if( fileToExecute.size() > 0 ){ + string::size_type p1 = fileToExecute.find_last_of("/"); + string::size_type p2 = fileToExecute.find_last_of("."); + rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1); + +#ifdef MSVC + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + _splitpath_s(fileToExecute.c_str(), NULL, 0, NULL, 0, fname, _MAX_FNAME, ext, _MAX_EXT); + string execBaseName = string(fname) + ext; +#else + char* basec=strdup(fileToExecute.c_str()); + string execBaseName = string(basename(basec)); + free(basec); +#endif + + fileNameToExecute = "~/" + dirForTmpFiles + "/" + execBaseName; + + int idx = dirForTmpFiles.find("Batch/"); + filelogtemp = dirForTmpFiles.substr(idx+6, dirForTmpFiles.length()); + } + else{ + rootNameToExecute = "command"; + } + + ofstream tempOutputFile; + std::string TmpFileName = createAndOpenTemporaryFile("SSH-script", tempOutputFile); + + tempOutputFile << "#! /bin/sh -f" << endl; + if (queue != "") + tempOutputFile << "#BSUB -q " << queue << endl; + if( edt > 0 ) + tempOutputFile << "#SSH -l walltime=" << edt*60 << endl ; + if( mem > 0 ) + tempOutputFile << "#SSH -l mem=" << mem << "mb" << endl ; + if( fileToExecute.size() > 0 ){ + tempOutputFile << "#SSH -o " << home << "/" << dirForTmpFiles << "/output.log." << filelogtemp << endl ; + tempOutputFile << "#SSH -e " << home << "/" << dirForTmpFiles << "/error.log." << filelogtemp << endl ; + } + else{ + tempOutputFile << "#SSH -o " << dirForTmpFiles << "/" << env["LOGFILE"] << ".output.log" << endl ; + tempOutputFile << "#SSH -e " << dirForTmpFiles << "/" << env["LOGFILE"] << ".error.log" << endl ; + } + if( workDir.size() > 0 ) + tempOutputFile << "cd " << workDir << endl ; + if( fileToExecute.size() > 0 ){ + tempOutputFile << _mpiImpl->boot("${SSH_NODEFILE}",nbproc); + tempOutputFile << _mpiImpl->run("${SSH_NODEFILE}",nbproc,fileNameToExecute); + tempOutputFile << _mpiImpl->halt(); + } + else{ + tempOutputFile << "source " << env["SOURCEFILE"] << endl ; + tempOutputFile << env["COMMAND"]; + } + + tempOutputFile.flush(); + tempOutputFile.close(); +#ifdef WIN32 + _chmod( +#else + chmod( +#endif + TmpFileName.c_str(), 0x1ED); + cerr << TmpFileName.c_str() << endl; + + int status = Batch::BatchManager_eClient::_protocol.copyFile(TmpFileName, "", "", + dirForTmpFiles + "/" + rootNameToExecute + "_Batch.sh", + _hostname, _username); + if (status) + throw EmulationException("Error of connection on remote host"); + + remove(TmpFileName.c_str()); + } + +} diff --git a/src/SSH/Batch_BatchManager_eSSH.hxx b/src/SSH/Batch_BatchManager_eSSH.hxx new file mode 100644 index 0000000..a95f2aa --- /dev/null +++ b/src/SSH/Batch_BatchManager_eSSH.hxx @@ -0,0 +1,81 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +/* + * BatchManager_eSSH.hxx : emulation of SSH client + * + * Auteur : André RIBES - EDF R&D + * Date : Octobre 2009 + */ + +#ifndef _BATCHMANAGER_ESSH_H_ +#define _BATCHMANAGER_ESSH_H_ + +#include "Batch_Defines.hxx" +#include "Batch_JobId.hxx" +#include "Batch_JobInfo.hxx" +#include "Batch_FactBatchManager.hxx" +#include "Batch_BatchManager_eClient.hxx" +#include "Batch_BatchManager_Local.hxx" + +namespace Batch { + + class BATCH_EXPORT BatchManager_eSSH : + virtual public BatchManager_eClient, + virtual public BatchManager_Local + { + public: + // Constructeur et destructeur + BatchManager_eSSH(const FactBatchManager * parent, const char * host="localhost", + CommunicationProtocolType protocolType = SSH, const char * mpiImpl="nompi"); // connexion a la machine host + virtual ~BatchManager_eSSH(); + + // Recupere le nom du serveur par defaut + // static string BatchManager_LSF::getDefaultServer(); + + // Methodes pour le controle des jobs + virtual const JobId submitJob(const Job & job); // soumet un job au gestionnaire + virtual void deleteJob(const JobId & jobid); // retire un job du gestionnaire + virtual JobInfo queryJob(const JobId & jobid); // renvoie l'etat du job + + // Non implanté... + virtual void holdJob(const JobId & jobid); // suspend un job en file d'attente + virtual void releaseJob(const JobId & jobid); // relache un job suspendu + virtual void alterJob(const JobId & jobid, const Parametre & param, const Environnement & env); // modifie un job en file d'attente + virtual void alterJob(const JobId & jobid, const Parametre & param); // modifie un job en file d'attente + virtual void alterJob(const JobId & jobid, const Environnement & env); // modifie un job en file d'attente + + + protected: + void buildBatchScript(const Job & job); + + private: + +#ifdef SWIG + public: + // Recupere le l'identifiant d'un job deja soumis au BatchManager + //virtual const JobId getJobIdByReference(const string & ref) { return BatchManager::getJobIdByReference(ref); } + virtual const JobId getJobIdByReference(const char * ref) { return BatchManager::getJobIdByReference(ref); } +#endif + }; +} + +#endif diff --git a/src/SSH/Batch_FactBatchManager_eSSH.cxx b/src/SSH/Batch_FactBatchManager_eSSH.cxx new file mode 100644 index 0000000..0c8d153 --- /dev/null +++ b/src/SSH/Batch_FactBatchManager_eSSH.cxx @@ -0,0 +1,53 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +/* + * FactBatchManager_eSSH.cxx : + * + * Auteur : André RIBES : EDF R&D + * Date : Octobre 2009 + */ + +#include +#include "Batch_BatchManager_eSSH.hxx" +#include "Batch_FactBatchManager_eSSH.hxx" + +Batch::FactBatchManager_eSSH::FactBatchManager_eSSH() : FactBatchManager_eClient("eSSH") {} + +Batch::FactBatchManager_eSSH::~FactBatchManager_eSSH() {} + +Batch::BatchManager * +Batch::FactBatchManager_eSSH::operator() (const char * hostname) const +{ + return new Batch::BatchManager_eSSH(this, hostname); +} + +Batch::BatchManager_eClient * +Batch::FactBatchManager_eSSH::operator() (const char * hostname, + CommunicationProtocolType protocolType, + const char * mpiImpl, + int nb_proc_per_node) const +{ + //protocolType and mpiImpl are ignored. + std::cerr << "[Batch::FactBatchManager_eSSH] creating new Batch::BatchManager_eSSH with hostname = " << hostname << std::endl; + + return new Batch::BatchManager_eSSH(this, hostname); +} diff --git a/src/SSH/Batch_FactBatchManager_eSSH.hxx b/src/SSH/Batch_FactBatchManager_eSSH.hxx new file mode 100644 index 0000000..f3210e6 --- /dev/null +++ b/src/SSH/Batch_FactBatchManager_eSSH.hxx @@ -0,0 +1,57 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +/* + * FactBatchManager_eSSH.hxx : + * + * Auteur : André RIBES : EDF R&D + * Date : Octobre 2009 + */ + +#ifndef _FACTBATCHMANAGER_eSSH_H_ +#define _FACTBATCHMANAGER_eSSH_H_ + +#include "Batch_Defines.hxx" + +#include +#include +#include "Batch_BatchManager_eClient.hxx" +#include "Batch_FactBatchManager_eClient.hxx" + +namespace Batch { + + class BatchManager_eSSH; + + class BATCH_EXPORT FactBatchManager_eSSH : public FactBatchManager_eClient + { + public: + FactBatchManager_eSSH(); + virtual ~FactBatchManager_eSSH(); + + virtual BatchManager * operator() (const char * hostname) const; // From FactBacthManager + virtual BatchManager_eClient * operator() (const char * hostname, + CommunicationProtocolType protocolType, + const char * mpiImpl, + int nb_proc_per_node = 1) const; // From FactBatchManager_eClient + }; +} + +#endif diff --git a/src/SSH/Batch_JobInfo_eSSH.cxx b/src/SSH/Batch_JobInfo_eSSH.cxx new file mode 100644 index 0000000..fd899de --- /dev/null +++ b/src/SSH/Batch_JobInfo_eSSH.cxx @@ -0,0 +1,71 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +/* + * JobInfo_eSSH.cxx : emulation of SSH client + * + * Auteur : André RIBES - EDF R&D + * Date : Octobre 2009 + */ + +#include +#include +#include +#include +#include "Batch_Parametre.hxx" +#include "Batch_Environnement.hxx" +#include "Batch_RunTimeException.hxx" +#include "Batch_APIInternalFailureException.hxx" +#include "Batch_JobInfo_eSSH.hxx" + +using namespace std; + +namespace Batch { + + // Constructeurs + JobInfo_eSSH::JobInfo_eSSH(int id, string status) : JobInfo() + { + // On remplit les membres _param et _env + ostringstream oss; + oss << id; + _param[ID] = oss.str(); + _param[STATE] = status; + } + + // Destructeur + JobInfo_eSSH::~JobInfo_eSSH() + { + // Nothing to do + } + + // Methode pour l'interfacage avec Python (SWIG) : affichage en Python + string JobInfo_eSSH::__str__() const + { + ostringstream sst; + sst << "