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 == "ccc")
303 INFOS("test_jobsubmit_simple not yet implemented for ccc... return OK");
307 if (batch_type == "sge")
309 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
313 if (batch_type != "pbs")
315 result += "Batch type unknown ! : " + batch_type;
319 // Getting home directory
320 std::string rst = get_home(&home);
327 std::string _test_file_simple = _test_filename + "_simple";
329 file.open(_test_file_simple.c_str(), std::ofstream::out);
330 file << "#!/bin/bash\n"
331 << "#PBS -l nodes=1\n"
332 << "#PBS -l walltime=00:01:00\n"
333 << "#PBS -o " + home + "/" + _date + "_simple_output.log\n"
334 << "#PBS -e " + home + "/" + _date + "_simple_error.log\n"
336 << "echo Error >&2\n";
341 // Build command for copy
343 if(protocol == "rsh")
345 command += " " + _test_file_simple + " "
346 + username + "@" + hostname + ":" + home;
347 status = system(command.c_str());
349 std::ostringstream oss;
351 result += "Error in copy job file to remote host ! status = ";
356 // Build command for submit job
357 std::string file_job_name = _test_filename + "_jobid";
358 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_simple > " + file_job_name;
359 status = system(command.c_str());
361 std::ostringstream oss;
363 result += "Error in sending qsub to remote host ! status = ";
368 std::ifstream file_job(file_job_name.c_str());
371 result += "Error in reading temporary file ! filename = " + file_job_name;
374 std::getline(file_job, jobid);
377 // Wait the end of the job
378 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
382 status = system(command.c_str());
383 if(status && status != 153 && status != 256*153)
385 std::ostringstream oss;
387 result += "Error in sending qstat to remote host ! status = ";
392 if(status == 153 || status == 256*153 )
401 // Build command for getting results
403 if(protocol == "rsh")
406 + username + "@" + hostname + ":" + home + "/" + _date + "_simple* /tmp";
407 status = system(command.c_str());
409 std::ostringstream oss;
411 result += "error in getting file result of qsub simple to remote host ! status = ";
417 std::string normal_input;
418 std::string file_normal_name = "/tmp/" + _date + "_simple_output.log";
419 std::ifstream file_normal(file_normal_name.c_str());
422 result += "Error in reading temporary file ! filename = " + file_normal_name;
425 std::getline(file_normal, normal_input);
427 if (normal_input != "Bonjour")
429 result += "error from simple ouput file ! waiting for Bonjour and get : " + normal_input;
432 std::string error_input;
433 std::string file_error_name = "/tmp/" + _date + "_simple_error.log";
434 std::ifstream file_error(file_error_name.c_str());
437 result += "Error in reading temporary file ! filename = " + file_error_name;
440 std::getline(file_error, error_input);
442 if (error_input != "Error")
444 result += "error from simple error file ! waiting for Error and get : " + error_input;
452 BatchTest::test_jobsubmit_mpi()
459 std::string result("Failed : ");
460 std::string hostname = _batch_descr.hostname.in();
461 std::string username = _batch_descr.username.in();
462 std::string protocol = _batch_descr.protocol.in();
463 std::string batch_type = _batch_descr.batch.in();
464 std::string mpi_type = _batch_descr.mpiImpl.in();
467 if(mpi_type == "lam")
468 mpiImpl = new MpiImpl_LAM();
469 else if(mpi_type == "mpich1")
470 mpiImpl = new MpiImpl_MPICH1();
471 else if(mpi_type == "mpich2")
472 mpiImpl = new MpiImpl_MPICH2();
473 else if(mpi_type == "openmpi")
474 mpiImpl = new MpiImpl_OPENMPI();
475 else if(mpi_type == "slurm")
476 mpiImpl = new MpiImpl_SLURM();
479 result += "Error MPI impl not supported : " + mpi_type;
483 // LSF et SGE not yet implemented...
484 if (batch_type == "lsf")
486 INFOS("test_jobsubmit_simple not yet implemented for lsf... return OK");
491 if (batch_type == "ccc")
493 INFOS("test_jobsubmit_simple not yet implemented for ccc... return OK");
498 if (batch_type == "sge")
500 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
505 // Getting home directory
506 std::string rst = get_home(&home);
513 std::string _test_file_script = _test_filename + "_script";
514 std::ofstream file_script;
515 file_script.open(_test_file_script.c_str(), std::ofstream::out);
516 file_script << "#!/bin/bash\n"
517 << "echo HELLO MPI\n";
525 (_test_file_script.c_str(), 0x1ED);
527 std::string _test_file_mpi = _test_filename + "_mpi";
528 std::ofstream file_mpi;
529 file_mpi.open(_test_file_mpi.c_str(), std::ofstream::out);
530 file_mpi << "#!/bin/bash\n"
531 << "#PBS -l nodes=1\n"
532 << "#PBS -l walltime=00:01:00\n"
533 << "#PBS -o " << home << "/" << _date << "_mpi_output.log\n"
534 << "#PBS -e " << home << "/" << _date << "_mpi_error.log\n"
535 << mpiImpl->boot("${PBS_NODEFILE}", 1)
536 << mpiImpl->run("${PBS_NODEFILE}", 1, _base_filename + "_script")
542 // Build command for copy
544 if(protocol == "rsh")
546 command += " " + _test_file_script + " "
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 if(protocol == "rsh")
559 command += " " + _test_file_mpi + " "
560 + username + "@" + hostname + ":" + home;
561 status = system(command.c_str());
563 std::ostringstream oss;
565 result += "Error in copy job file to remote host ! status = ";
570 // Build command for submit job
571 std::string file_job_name = _test_filename + "_jobid";
572 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_mpi > " + file_job_name;
573 status = system(command.c_str());
575 std::ostringstream oss;
577 result += "Error in sending qsub to remote host ! status = ";
582 std::ifstream file_job(file_job_name.c_str());
585 result += "Error in reading temporary file ! filename = " + file_job_name;
588 std::getline(file_job, jobid);
591 // Wait the end of the job
592 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
596 status = system(command.c_str());
597 if(status && status != 153 && status != 256*153)
599 std::ostringstream oss;
601 result += "Error in sending qstat to remote host ! status = ";
606 if(status == 153 || status == 256*153 )
615 // Build command for getting results
617 if(protocol == "rsh")
620 + username + "@" + hostname + ":" + home + "/" + _date + "_mpi* /tmp";
621 status = system(command.c_str());
623 std::ostringstream oss;
625 result += "error in getting file result of qsub mpi from remote host ! status = ";
631 std::string normal_input;
632 std::string file_normal_name = "/tmp/" + _date + "_mpi_output.log";
633 std::ifstream file_normal(file_normal_name.c_str());
636 result += "Error in reading temporary file ! filename = " + file_normal_name;
639 bool test_ok = false;
640 while (std::getline(file_normal, normal_input))
642 if (normal_input == "HELLO MPI")
648 result += "error from mpi ouput file ! waiting for HELLO MPI please watch /tmp/" + _date + "_mpi_output.log file";
654 throw LauncherException("Method BatchTest::test_jobsubmit_mpi is not available "
655 "(libBatch was not present at compilation time)");
660 BatchTest::test_appli()
665 std::string result("Failed : ");
666 std::string hostname = _batch_descr.hostname.in();
667 std::string username = _batch_descr.username.in();
668 std::string protocol = _batch_descr.protocol.in();
669 std::string applipath = _batch_descr.applipath.in();
671 // Getting home directory
672 std::string rst = get_home(&home);
678 std::string _test_file_appli = _test_filename + "_appli_test";
679 std::ofstream file_appli;
680 file_appli.open(_test_file_appli.c_str(), std::ofstream::out);
681 file_appli << "#!/bin/bash\n"
682 << "if [ -f " << applipath << "/runAppli ]\n"
691 // Build command for copy
693 if(protocol == "rsh")
695 command += " " + _test_file_appli + " "
696 + username + "@" + hostname + ":" + home;
697 status = system(command.c_str());
699 std::ostringstream oss;
701 result += "Error in copy appli test file to remote host ! status = ";
707 command = protocol + " " + username + "@" + hostname
708 + " sh " + home + "/" + _base_filename + "_appli_test > "
709 + _test_filename + "_appli_test_result";
711 status = system(command.c_str());
713 std::ostringstream oss;
715 result += "Error in launching appli test on remote host ! status = ";
721 std::string rst_appli;
722 std::string file_appli_result_name = _test_filename + "_appli_test_result";
723 std::ifstream file_appli_result(file_appli_result_name.c_str());
724 if (!file_appli_result)
726 result += "Error in reading temporary file ! filename = " + file_appli_result_name;
729 std::getline(file_appli_result, rst_appli);
730 file_appli_result.close();
732 if (rst_appli != "OK")
734 result += "Error checking application on remote host ! result = " + rst;
744 BatchTest::get_home(std::string * home)
747 std::string result = "";
749 std::string hostname = _batch_descr.hostname.in();
750 std::string username = _batch_descr.username.in();
751 std::string protocol = _batch_descr.protocol.in();
752 std::string file_home_name = _test_filename + "_home";
754 command = protocol + " " + username + "@" + hostname + " 'echo $HOME' > " + file_home_name;
755 status = system(command.c_str());
757 std::ostringstream oss;
759 result += "Error in getting home directory ! status = ";
764 std::ifstream file_home(file_home_name.c_str());
767 result += "Error in reading temporary file ! filename = " + file_home_name;
770 std::getline(file_home, *home);