1 // Copyright (C) 2007-2008 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
22 #include "BatchTest.hxx"
23 #include "Launcher.hxx"
26 #include <Batch/Batch_Date.hxx>
27 #include <Batch/Batch_MpiImpl.hxx>
30 #include "utilities.h"
38 BatchTest::BatchTest(const Engines::ResourceDefinition& batch_descr)
41 _batch_descr = batch_descr;
44 Batch::Date date = Batch::Date(time(0));
46 int lend = _date.size() ;
50 if (_date[i] == '/' || _date[i] == '-' || _date[i] == ':' )
57 // Creating test temporary file
58 _test_filename = "/tmp/";
59 _test_filename += _date + "_test_cluster_file_";
60 _test_filename += _batch_descr.hostname.in();
61 _base_filename = _date + "_test_cluster_file_" + _batch_descr.hostname.in();
65 BatchTest::~BatchTest() {}
72 << "--- Testing batch Machine :" << std::endl
73 << "--- Name : " << _batch_descr.hostname << std::endl
74 << "--- hostname : " << _batch_descr.hostname << std::endl
75 << "--- Protocol : " << _batch_descr.protocol << std::endl
76 << "--- User Name : " << _batch_descr.username << std::endl
77 << "--- Batch Type : " << _batch_descr.batch << std::endl
78 << "--- MPI Impl : " << _batch_descr.mpiImpl << std::endl
79 << "--- Appli Path : " << _batch_descr.applipath << std::endl
82 std::string result_connection("Not Tested");
83 std::string result_filecopy("Not Tested");
84 std::string result_getresult("Not Tested");
85 std::string result_jobsubmit_simple("Not Tested");
86 std::string result_jobsubmit_mpi("Not Tested");
87 std::string result_appli("Not Tested");
89 result_connection = test_connection();
90 result_filecopy = test_filecopy();
91 result_getresult = test_getresult();
92 result_jobsubmit_simple = test_jobsubmit_simple();
93 result_jobsubmit_mpi = test_jobsubmit_mpi();
94 result_appli = test_appli();
97 << "--- Test results" << std::endl
98 << "--- Connection : " << result_connection << std::endl
99 << "--- File copy : " << result_filecopy << std::endl
100 << "--- Get results : " << result_getresult << std::endl
101 << "--- Submit simple job : " << result_jobsubmit_simple << std::endl
102 << "--- Submit mpi job : " << result_jobsubmit_mpi << std::endl
103 << "--- Application : " << result_appli << std::endl
106 if (result_connection == "OK" &&
107 result_filecopy == "OK" &&
108 result_getresult == "OK" &&
109 result_jobsubmit_simple == "OK" &&
110 result_jobsubmit_mpi == "OK" &&
111 result_appli == "OK")
117 // For this test we use : hostname, protocol, username
119 BatchTest::test_connection()
123 std::string result("Failed : ");
124 std::string hostname = _batch_descr.hostname.in();
125 std::string username = _batch_descr.username.in();
126 std::string protocol = _batch_descr.protocol.in();
131 result += "hostname is empty !";
136 result += "username is empty !";
139 if( protocol != "rsh" && protocol != "ssh")
141 result += "protocol unknown ! (" + protocol + ")";
148 + username + "@" + hostname;
151 status = system(command.c_str());
153 std::ostringstream oss;
155 result += "Error of connection on remote host ! status = ";
164 // For this test we use : hostname, protocol, username
166 BatchTest::test_filecopy()
171 std::string result("Failed : ");
172 std::string hostname = _batch_descr.hostname.in();
173 std::string username = _batch_descr.username.in();
174 std::string protocol = _batch_descr.protocol.in();
176 // Getting home directory
177 std::string rst = get_home(&home);
183 // Writing into the tempory file
184 command = "echo Hello > " + _test_filename;
185 status = system(command.c_str());
187 std::ostringstream oss;
189 result += "Error in creating tempory file ! status = ";
196 if(protocol == "rsh")
198 command += " " + _test_filename + " "
199 + username + "@" + hostname + ":" + home;
202 status = system(command.c_str());
204 std::ostringstream oss;
206 result += "Error in copy file on remote host ! status = ";
215 // For this test we use : hostname, protocol, username
217 BatchTest::test_getresult()
222 std::string result("Failed : ");
223 std::string hostname = _batch_descr.hostname.in();
224 std::string username = _batch_descr.username.in();
225 std::string protocol = _batch_descr.protocol.in();
227 // Getting home directory
228 std::string rst = get_home(&home);
236 if(protocol == "rsh")
238 command += " " + username + "@" + hostname + ":" + home
239 + "/" + _base_filename + " " + _test_filename + "_copy";
242 status = system(command.c_str());
244 std::ostringstream oss;
246 result += "Error in copy file from remote host ! status = ";
252 std::ifstream src_file(_test_filename.c_str());
255 result += "Error in reading temporary file ! filename = " + _test_filename;
258 std::string cp_filename = _test_filename + "_copy";
259 std::ifstream cp_file(cp_filename.c_str());
262 result += "Error in reading temporary copy file ! filename = " + cp_filename;
265 std::string src_firstline;
266 std::string cp_firstline;
267 std::getline(src_file, src_firstline);
268 std::getline(cp_file, cp_firstline);
271 if (src_firstline != cp_firstline)
273 result += "Error source file and copy file are not equa ! source = " + src_firstline + " copy = " + cp_firstline;
282 BatchTest::test_jobsubmit_simple()
287 std::string result("Failed : ");
288 std::string hostname = _batch_descr.hostname.in();
289 std::string username = _batch_descr.username.in();
290 std::string protocol = _batch_descr.protocol.in();
291 std::string batch_type = _batch_descr.batch.in();
294 if (batch_type == "lsf")
296 INFOS("test_jobsubmit_simple not yet implemented for lsf... return OK");
300 if (batch_type == "sge")
302 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
306 if (batch_type != "pbs")
308 result += "Batch type unknown ! : " + batch_type;
312 // Getting home directory
313 std::string rst = get_home(&home);
320 std::string _test_file_simple = _test_filename + "_simple";
322 file.open(_test_file_simple.c_str(), std::ofstream::out);
323 file << "#!/bin/bash\n"
324 << "#PBS -l nodes=1\n"
325 << "#PBS -l walltime=00:01:00\n"
326 << "#PBS -o " + home + "/" + _date + "_simple_output.log\n"
327 << "#PBS -e " + home + "/" + _date + "_simple_error.log\n"
329 << "echo Error >&2\n";
334 // Build command for copy
336 if(protocol == "rsh")
338 command += " " + _test_file_simple + " "
339 + username + "@" + hostname + ":" + home;
340 status = system(command.c_str());
342 std::ostringstream oss;
344 result += "Error in copy job file to remote host ! status = ";
349 // Build command for submit job
350 std::string file_job_name = _test_filename + "_jobid";
351 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_simple > " + file_job_name;
352 status = system(command.c_str());
354 std::ostringstream oss;
356 result += "Error in sending qsub to remote host ! status = ";
361 std::ifstream file_job(file_job_name.c_str());
364 result += "Error in reading temporary file ! filename = " + file_job_name;
367 std::getline(file_job, jobid);
370 // Wait the end of the job
371 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
375 status = system(command.c_str());
376 if(status && status != 153 && status != 256*153)
378 std::ostringstream oss;
380 result += "Error in sending qstat to remote host ! status = ";
385 if(status == 153 || status == 256*153 )
394 // Build command for getting results
396 if(protocol == "rsh")
399 + username + "@" + hostname + ":" + home + "/" + _date + "_simple* /tmp";
400 status = system(command.c_str());
402 std::ostringstream oss;
404 result += "error in getting file result of qsub simple to remote host ! status = ";
410 std::string normal_input;
411 std::string file_normal_name = "/tmp/" + _date + "_simple_output.log";
412 std::ifstream file_normal(file_normal_name.c_str());
415 result += "Error in reading temporary file ! filename = " + file_normal_name;
418 std::getline(file_normal, normal_input);
420 if (normal_input != "Bonjour")
422 result += "error from simple ouput file ! waiting for Bonjour and get : " + normal_input;
425 std::string error_input;
426 std::string file_error_name = "/tmp/" + _date + "_simple_error.log";
427 std::ifstream file_error(file_error_name.c_str());
430 result += "Error in reading temporary file ! filename = " + file_error_name;
433 std::getline(file_error, error_input);
435 if (error_input != "Error")
437 result += "error from simple error file ! waiting for Error and get : " + error_input;
445 BatchTest::test_jobsubmit_mpi()
452 std::string result("Failed : ");
453 std::string hostname = _batch_descr.hostname.in();
454 std::string username = _batch_descr.username.in();
455 std::string protocol = _batch_descr.protocol.in();
456 std::string batch_type = _batch_descr.batch.in();
457 std::string mpi_type = _batch_descr.mpiImpl.in();
460 if(mpi_type == "lam")
461 mpiImpl = new MpiImpl_LAM();
462 else if(mpi_type == "mpich1")
463 mpiImpl = new MpiImpl_MPICH1();
464 else if(mpi_type == "mpich2")
465 mpiImpl = new MpiImpl_MPICH2();
466 else if(mpi_type == "openmpi")
467 mpiImpl = new MpiImpl_OPENMPI();
468 else if(mpi_type == "slurm")
469 mpiImpl = new MpiImpl_SLURM();
472 result += "Error MPI impl not supported : " + mpi_type;
476 // LSF et SGE not yet implemented...
477 if (batch_type == "lsf")
479 INFOS("test_jobsubmit_simple not yet implemented for lsf... return OK");
484 if (batch_type == "sge")
486 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
491 // Getting home directory
492 std::string rst = get_home(&home);
499 std::string _test_file_script = _test_filename + "_script";
500 std::ofstream file_script;
501 file_script.open(_test_file_script.c_str(), std::ofstream::out);
502 file_script << "#!/bin/bash\n"
503 << "echo HELLO MPI\n";
511 (_test_file_script.c_str(), 0x1ED);
513 std::string _test_file_mpi = _test_filename + "_mpi";
514 std::ofstream file_mpi;
515 file_mpi.open(_test_file_mpi.c_str(), std::ofstream::out);
516 file_mpi << "#!/bin/bash\n"
517 << "#PBS -l nodes=1\n"
518 << "#PBS -l walltime=00:01:00\n"
519 << "#PBS -o " << home << "/" << _date << "_mpi_output.log\n"
520 << "#PBS -e " << home << "/" << _date << "_mpi_error.log\n"
521 << mpiImpl->boot("${PBS_NODEFILE}", 1)
522 << mpiImpl->run("${PBS_NODEFILE}", 1, _base_filename + "_script")
528 // Build command for copy
530 if(protocol == "rsh")
532 command += " " + _test_file_script + " "
533 + username + "@" + hostname + ":" + home;
534 status = system(command.c_str());
536 std::ostringstream oss;
538 result += "Error in copy job file to remote host ! status = ";
543 if(protocol == "rsh")
545 command += " " + _test_file_mpi + " "
546 + username + "@" + hostname + ":" + home;
547 status = system(command.c_str());
549 std::ostringstream oss;
551 result += "Error in copy job file to remote host ! status = ";
556 // Build command for submit job
557 std::string file_job_name = _test_filename + "_jobid";
558 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_mpi > " + file_job_name;
559 status = system(command.c_str());
561 std::ostringstream oss;
563 result += "Error in sending qsub to remote host ! status = ";
568 std::ifstream file_job(file_job_name.c_str());
571 result += "Error in reading temporary file ! filename = " + file_job_name;
574 std::getline(file_job, jobid);
577 // Wait the end of the job
578 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
582 status = system(command.c_str());
583 if(status && status != 153 && status != 256*153)
585 std::ostringstream oss;
587 result += "Error in sending qstat to remote host ! status = ";
592 if(status == 153 || status == 256*153 )
601 // Build command for getting results
603 if(protocol == "rsh")
606 + username + "@" + hostname + ":" + home + "/" + _date + "_mpi* /tmp";
607 status = system(command.c_str());
609 std::ostringstream oss;
611 result += "error in getting file result of qsub mpi from remote host ! status = ";
617 std::string normal_input;
618 std::string file_normal_name = "/tmp/" + _date + "_mpi_output.log";
619 std::ifstream file_normal(file_normal_name.c_str());
622 result += "Error in reading temporary file ! filename = " + file_normal_name;
625 bool test_ok = false;
626 while (std::getline(file_normal, normal_input))
628 if (normal_input == "HELLO MPI")
634 result += "error from mpi ouput file ! waiting for HELLO MPI please watch /tmp/" + _date + "_mpi_output.log file";
640 throw LauncherException("Method BatchTest::test_jobsubmit_mpi is not available "
641 "(libBatch was not present at compilation time)");
646 BatchTest::test_appli()
651 std::string result("Failed : ");
652 std::string hostname = _batch_descr.hostname.in();
653 std::string username = _batch_descr.username.in();
654 std::string protocol = _batch_descr.protocol.in();
655 std::string applipath = _batch_descr.applipath.in();
657 // Getting home directory
658 std::string rst = get_home(&home);
664 std::string _test_file_appli = _test_filename + "_appli_test";
665 std::ofstream file_appli;
666 file_appli.open(_test_file_appli.c_str(), std::ofstream::out);
667 file_appli << "#!/bin/bash\n"
668 << "if [ -f " << applipath << "/runAppli ]\n"
677 // Build command for copy
679 if(protocol == "rsh")
681 command += " " + _test_file_appli + " "
682 + username + "@" + hostname + ":" + home;
683 status = system(command.c_str());
685 std::ostringstream oss;
687 result += "Error in copy appli test file to remote host ! status = ";
693 command = protocol + " " + username + "@" + hostname
694 + " sh " + home + "/" + _base_filename + "_appli_test > "
695 + _test_filename + "_appli_test_result";
697 status = system(command.c_str());
699 std::ostringstream oss;
701 result += "Error in launching appli test on remote host ! status = ";
707 std::string rst_appli;
708 std::string file_appli_result_name = _test_filename + "_appli_test_result";
709 std::ifstream file_appli_result(file_appli_result_name.c_str());
710 if (!file_appli_result)
712 result += "Error in reading temporary file ! filename = " + file_appli_result_name;
715 std::getline(file_appli_result, rst_appli);
716 file_appli_result.close();
718 if (rst_appli != "OK")
720 result += "Error checking application on remote host ! result = " + rst;
730 BatchTest::get_home(std::string * home)
733 std::string result = "";
735 std::string hostname = _batch_descr.hostname.in();
736 std::string username = _batch_descr.username.in();
737 std::string protocol = _batch_descr.protocol.in();
738 std::string file_home_name = _test_filename + "_home";
740 command = protocol + " " + username + "@" + hostname + " 'echo $HOME' > " + file_home_name;
741 status = system(command.c_str());
743 std::ostringstream oss;
745 result += "Error in getting home directory ! status = ";
750 std::ifstream file_home(file_home_name.c_str());
753 result += "Error in reading temporary file ! filename = " + file_home_name;
756 std::getline(file_home, *home);