1 // Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "BatchTest.hxx"
24 #include "Launcher.hxx"
27 #include <Batch/Batch_Date.hxx>
28 #include <Batch/Batch_MpiImpl.hxx>
31 #include "utilities.h"
39 BatchTest::BatchTest(const Engines::ResourceDefinition& batch_descr)
42 _batch_descr = batch_descr;
45 Batch::Date date = Batch::Date(time(0));
47 int lend = _date.size() ;
51 if (_date[i] == '/' || _date[i] == '-' || _date[i] == ':' )
58 // Creating test temporary file
59 _test_filename = "/tmp/";
60 _test_filename += _date + "_test_cluster_file_";
61 _test_filename += _batch_descr.hostname.in();
62 _base_filename = _date + "_test_cluster_file_" + _batch_descr.hostname.in();
66 BatchTest::~BatchTest() {}
73 << "--- Testing batch Machine :" << std::endl
74 << "--- Name : " << _batch_descr.hostname << std::endl
75 << "--- hostname : " << _batch_descr.hostname << std::endl
76 << "--- Protocol : " << _batch_descr.protocol << std::endl
77 << "--- User Name : " << _batch_descr.username << std::endl
78 << "--- Batch Type : " << _batch_descr.batch << std::endl
79 << "--- MPI Impl : " << _batch_descr.mpiImpl << std::endl
80 << "--- Appli Path : " << _batch_descr.applipath << std::endl
83 std::string result_connection("Not Tested");
84 std::string result_filecopy("Not Tested");
85 std::string result_getresult("Not Tested");
86 std::string result_jobsubmit_simple("Not Tested");
87 std::string result_jobsubmit_mpi("Not Tested");
88 std::string result_appli("Not Tested");
90 result_connection = test_connection();
91 result_filecopy = test_filecopy();
92 result_getresult = test_getresult();
93 result_jobsubmit_simple = test_jobsubmit_simple();
94 result_jobsubmit_mpi = test_jobsubmit_mpi();
95 result_appli = test_appli();
98 << "--- Test results" << std::endl
99 << "--- Connection : " << result_connection << std::endl
100 << "--- File copy : " << result_filecopy << std::endl
101 << "--- Get results : " << result_getresult << std::endl
102 << "--- Submit simple job : " << result_jobsubmit_simple << std::endl
103 << "--- Submit mpi job : " << result_jobsubmit_mpi << std::endl
104 << "--- Application : " << result_appli << std::endl
107 if (result_connection == "OK" &&
108 result_filecopy == "OK" &&
109 result_getresult == "OK" &&
110 result_jobsubmit_simple == "OK" &&
111 result_jobsubmit_mpi == "OK" &&
112 result_appli == "OK")
118 // For this test we use : hostname, protocol, username
120 BatchTest::test_connection()
124 std::string result("Failed : ");
125 std::string hostname = _batch_descr.hostname.in();
126 std::string username = _batch_descr.username.in();
127 std::string protocol = _batch_descr.protocol.in();
132 result += "hostname is empty !";
137 result += "username is empty !";
140 if( protocol != "rsh" && protocol != "ssh")
142 result += "protocol unknown ! (" + protocol + ")";
149 + username + "@" + hostname;
152 status = system(command.c_str());
154 std::ostringstream oss;
156 result += "Error of connection on remote host ! status = ";
165 // For this test we use : hostname, protocol, username
167 BatchTest::test_filecopy()
172 std::string result("Failed : ");
173 std::string hostname = _batch_descr.hostname.in();
174 std::string username = _batch_descr.username.in();
175 std::string protocol = _batch_descr.protocol.in();
177 // Getting home directory
178 std::string rst = get_home(&home);
184 // Writing into the tempory file
185 command = "echo Hello > " + _test_filename;
186 status = system(command.c_str());
188 std::ostringstream oss;
190 result += "Error in creating tempory file ! status = ";
197 if(protocol == "rsh")
199 command += " " + _test_filename + " "
200 + username + "@" + hostname + ":" + home;
203 status = system(command.c_str());
205 std::ostringstream oss;
207 result += "Error in copy file on remote host ! status = ";
216 // For this test we use : hostname, protocol, username
218 BatchTest::test_getresult()
223 std::string result("Failed : ");
224 std::string hostname = _batch_descr.hostname.in();
225 std::string username = _batch_descr.username.in();
226 std::string protocol = _batch_descr.protocol.in();
228 // Getting home directory
229 std::string rst = get_home(&home);
237 if(protocol == "rsh")
239 command += " " + username + "@" + hostname + ":" + home
240 + "/" + _base_filename + " " + _test_filename + "_copy";
243 status = system(command.c_str());
245 std::ostringstream oss;
247 result += "Error in copy file from remote host ! status = ";
253 std::ifstream src_file(_test_filename.c_str());
256 result += "Error in reading temporary file ! filename = " + _test_filename;
259 std::string cp_filename = _test_filename + "_copy";
260 std::ifstream cp_file(cp_filename.c_str());
263 result += "Error in reading temporary copy file ! filename = " + cp_filename;
266 std::string src_firstline;
267 std::string cp_firstline;
268 std::getline(src_file, src_firstline);
269 std::getline(cp_file, cp_firstline);
272 if (src_firstline != cp_firstline)
274 result += "Error source file and copy file are not equa ! source = " + src_firstline + " copy = " + cp_firstline;
283 BatchTest::test_jobsubmit_simple()
288 std::string result("Failed : ");
289 std::string hostname = _batch_descr.hostname.in();
290 std::string username = _batch_descr.username.in();
291 std::string protocol = _batch_descr.protocol.in();
292 std::string batch_type = _batch_descr.batch.in();
295 if (batch_type == "lsf")
297 INFOS("test_jobsubmit_simple not yet implemented for lsf... return OK");
301 if (batch_type == "sge")
303 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
307 if (batch_type != "pbs")
309 result += "Batch type unknown ! : " + batch_type;
313 // Getting home directory
314 std::string rst = get_home(&home);
321 std::string _test_file_simple = _test_filename + "_simple";
323 file.open(_test_file_simple.c_str(), std::ofstream::out);
324 file << "#!/bin/bash\n"
325 << "#PBS -l nodes=1\n"
326 << "#PBS -l walltime=00:01:00\n"
327 << "#PBS -o " + home + "/" + _date + "_simple_output.log\n"
328 << "#PBS -e " + home + "/" + _date + "_simple_error.log\n"
330 << "echo Error >&2\n";
335 // Build command for copy
337 if(protocol == "rsh")
339 command += " " + _test_file_simple + " "
340 + username + "@" + hostname + ":" + home;
341 status = system(command.c_str());
343 std::ostringstream oss;
345 result += "Error in copy job file to remote host ! status = ";
350 // Build command for submit job
351 std::string file_job_name = _test_filename + "_jobid";
352 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_simple > " + file_job_name;
353 status = system(command.c_str());
355 std::ostringstream oss;
357 result += "Error in sending qsub to remote host ! status = ";
362 std::ifstream file_job(file_job_name.c_str());
365 result += "Error in reading temporary file ! filename = " + file_job_name;
368 std::getline(file_job, jobid);
371 // Wait the end of the job
372 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
376 status = system(command.c_str());
377 if(status && status != 153 && status != 256*153)
379 std::ostringstream oss;
381 result += "Error in sending qstat to remote host ! status = ";
386 if(status == 153 || status == 256*153 )
395 // Build command for getting results
397 if(protocol == "rsh")
400 + username + "@" + hostname + ":" + home + "/" + _date + "_simple* /tmp";
401 status = system(command.c_str());
403 std::ostringstream oss;
405 result += "error in getting file result of qsub simple to remote host ! status = ";
411 std::string normal_input;
412 std::string file_normal_name = "/tmp/" + _date + "_simple_output.log";
413 std::ifstream file_normal(file_normal_name.c_str());
416 result += "Error in reading temporary file ! filename = " + file_normal_name;
419 std::getline(file_normal, normal_input);
421 if (normal_input != "Bonjour")
423 result += "error from simple ouput file ! waiting for Bonjour and get : " + normal_input;
426 std::string error_input;
427 std::string file_error_name = "/tmp/" + _date + "_simple_error.log";
428 std::ifstream file_error(file_error_name.c_str());
431 result += "Error in reading temporary file ! filename = " + file_error_name;
434 std::getline(file_error, error_input);
436 if (error_input != "Error")
438 result += "error from simple error file ! waiting for Error and get : " + error_input;
446 BatchTest::test_jobsubmit_mpi()
453 std::string result("Failed : ");
454 std::string hostname = _batch_descr.hostname.in();
455 std::string username = _batch_descr.username.in();
456 std::string protocol = _batch_descr.protocol.in();
457 std::string batch_type = _batch_descr.batch.in();
458 std::string mpi_type = _batch_descr.mpiImpl.in();
461 if(mpi_type == "lam")
462 mpiImpl = new MpiImpl_LAM();
463 else if(mpi_type == "mpich1")
464 mpiImpl = new MpiImpl_MPICH1();
465 else if(mpi_type == "mpich2")
466 mpiImpl = new MpiImpl_MPICH2();
467 else if(mpi_type == "openmpi")
468 mpiImpl = new MpiImpl_OPENMPI();
469 else if(mpi_type == "slurm")
470 mpiImpl = new MpiImpl_SLURM();
473 result += "Error MPI impl not supported : " + mpi_type;
477 // LSF et SGE not yet implemented...
478 if (batch_type == "lsf")
480 INFOS("test_jobsubmit_simple not yet implemented for lsf... return OK");
485 if (batch_type == "sge")
487 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
492 // Getting home directory
493 std::string rst = get_home(&home);
500 std::string _test_file_script = _test_filename + "_script";
501 std::ofstream file_script;
502 file_script.open(_test_file_script.c_str(), std::ofstream::out);
503 file_script << "#!/bin/bash\n"
504 << "echo HELLO MPI\n";
512 (_test_file_script.c_str(), 0x1ED);
514 std::string _test_file_mpi = _test_filename + "_mpi";
515 std::ofstream file_mpi;
516 file_mpi.open(_test_file_mpi.c_str(), std::ofstream::out);
517 file_mpi << "#!/bin/bash\n"
518 << "#PBS -l nodes=1\n"
519 << "#PBS -l walltime=00:01:00\n"
520 << "#PBS -o " << home << "/" << _date << "_mpi_output.log\n"
521 << "#PBS -e " << home << "/" << _date << "_mpi_error.log\n"
522 << mpiImpl->boot("${PBS_NODEFILE}", 1)
523 << mpiImpl->run("${PBS_NODEFILE}", 1, _base_filename + "_script")
529 // Build command for copy
531 if(protocol == "rsh")
533 command += " " + _test_file_script + " "
534 + username + "@" + hostname + ":" + home;
535 status = system(command.c_str());
537 std::ostringstream oss;
539 result += "Error in copy job file to remote host ! status = ";
544 if(protocol == "rsh")
546 command += " " + _test_file_mpi + " "
547 + username + "@" + hostname + ":" + home;
548 status = system(command.c_str());
550 std::ostringstream oss;
552 result += "Error in copy job file to remote host ! status = ";
557 // Build command for submit job
558 std::string file_job_name = _test_filename + "_jobid";
559 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_mpi > " + file_job_name;
560 status = system(command.c_str());
562 std::ostringstream oss;
564 result += "Error in sending qsub to remote host ! status = ";
569 std::ifstream file_job(file_job_name.c_str());
572 result += "Error in reading temporary file ! filename = " + file_job_name;
575 std::getline(file_job, jobid);
578 // Wait the end of the job
579 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
583 status = system(command.c_str());
584 if(status && status != 153 && status != 256*153)
586 std::ostringstream oss;
588 result += "Error in sending qstat to remote host ! status = ";
593 if(status == 153 || status == 256*153 )
602 // Build command for getting results
604 if(protocol == "rsh")
607 + username + "@" + hostname + ":" + home + "/" + _date + "_mpi* /tmp";
608 status = system(command.c_str());
610 std::ostringstream oss;
612 result += "error in getting file result of qsub mpi from remote host ! status = ";
618 std::string normal_input;
619 std::string file_normal_name = "/tmp/" + _date + "_mpi_output.log";
620 std::ifstream file_normal(file_normal_name.c_str());
623 result += "Error in reading temporary file ! filename = " + file_normal_name;
626 bool test_ok = false;
627 while (std::getline(file_normal, normal_input))
629 if (normal_input == "HELLO MPI")
635 result += "error from mpi ouput file ! waiting for HELLO MPI please watch /tmp/" + _date + "_mpi_output.log file";
641 throw LauncherException("Method BatchTest::test_jobsubmit_mpi is not available "
642 "(libBatch was not present at compilation time)");
647 BatchTest::test_appli()
652 std::string result("Failed : ");
653 std::string hostname = _batch_descr.hostname.in();
654 std::string username = _batch_descr.username.in();
655 std::string protocol = _batch_descr.protocol.in();
656 std::string applipath = _batch_descr.applipath.in();
658 // Getting home directory
659 std::string rst = get_home(&home);
665 std::string _test_file_appli = _test_filename + "_appli_test";
666 std::ofstream file_appli;
667 file_appli.open(_test_file_appli.c_str(), std::ofstream::out);
668 file_appli << "#!/bin/bash\n"
669 << "if [ -f " << applipath << "/runAppli ]\n"
678 // Build command for copy
680 if(protocol == "rsh")
682 command += " " + _test_file_appli + " "
683 + username + "@" + hostname + ":" + home;
684 status = system(command.c_str());
686 std::ostringstream oss;
688 result += "Error in copy appli test file to remote host ! status = ";
694 command = protocol + " " + username + "@" + hostname
695 + " sh " + home + "/" + _base_filename + "_appli_test > "
696 + _test_filename + "_appli_test_result";
698 status = system(command.c_str());
700 std::ostringstream oss;
702 result += "Error in launching appli test on remote host ! status = ";
708 std::string rst_appli;
709 std::string file_appli_result_name = _test_filename + "_appli_test_result";
710 std::ifstream file_appli_result(file_appli_result_name.c_str());
711 if (!file_appli_result)
713 result += "Error in reading temporary file ! filename = " + file_appli_result_name;
716 std::getline(file_appli_result, rst_appli);
717 file_appli_result.close();
719 if (rst_appli != "OK")
721 result += "Error checking application on remote host ! result = " + rst;
731 BatchTest::get_home(std::string * home)
734 std::string result = "";
736 std::string hostname = _batch_descr.hostname.in();
737 std::string username = _batch_descr.username.in();
738 std::string protocol = _batch_descr.protocol.in();
739 std::string file_home_name = _test_filename + "_home";
741 command = protocol + " " + username + "@" + hostname + " 'echo $HOME' > " + file_home_name;
742 status = system(command.c_str());
744 std::ostringstream oss;
746 result += "Error in getting home directory ! status = ";
751 std::ifstream file_home(file_home_name.c_str());
754 result += "Error in reading temporary file ! filename = " + file_home_name;
757 std::getline(file_home, *home);