1 // Copyright (C) 2007-2011 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 == "slurm")
309 INFOS("test_jobsubmit_simple not yet implemented for slurm... return OK");
313 if (batch_type == "sge")
315 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
319 if (batch_type != "pbs")
321 result += "Batch type unknown ! : " + batch_type;
325 // Getting home directory
326 std::string rst = get_home(&home);
333 std::string _test_file_simple = _test_filename + "_simple";
335 file.open(_test_file_simple.c_str(), std::ofstream::out);
336 file << "#!/bin/bash\n"
337 << "#PBS -l nodes=1\n"
338 << "#PBS -l walltime=00:01:00\n"
339 << "#PBS -o " + home + "/" + _date + "_simple_output.log\n"
340 << "#PBS -e " + home + "/" + _date + "_simple_error.log\n"
342 << "echo Error >&2\n";
347 // Build command for copy
349 if(protocol == "rsh")
351 command += " " + _test_file_simple + " "
352 + username + "@" + hostname + ":" + home;
353 status = system(command.c_str());
355 std::ostringstream oss;
357 result += "Error in copy job file to remote host ! status = ";
362 // Build command for submit job
363 std::string file_job_name = _test_filename + "_jobid";
364 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_simple > " + file_job_name;
365 status = system(command.c_str());
367 std::ostringstream oss;
369 result += "Error in sending qsub to remote host ! status = ";
374 std::ifstream file_job(file_job_name.c_str());
377 result += "Error in reading temporary file ! filename = " + file_job_name;
380 std::getline(file_job, jobid);
383 // Wait the end of the job
384 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
388 status = system(command.c_str());
389 if(status && status != 153 && status != 256*153)
391 std::ostringstream oss;
393 result += "Error in sending qstat to remote host ! status = ";
398 if(status == 153 || status == 256*153 )
407 // Build command for getting results
409 if(protocol == "rsh")
412 + username + "@" + hostname + ":" + home + "/" + _date + "_simple* /tmp";
413 status = system(command.c_str());
415 std::ostringstream oss;
417 result += "error in getting file result of qsub simple to remote host ! status = ";
423 std::string normal_input;
424 std::string file_normal_name = "/tmp/" + _date + "_simple_output.log";
425 std::ifstream file_normal(file_normal_name.c_str());
428 result += "Error in reading temporary file ! filename = " + file_normal_name;
431 std::getline(file_normal, normal_input);
433 if (normal_input != "Bonjour")
435 result += "error from simple ouput file ! waiting for Bonjour and get : " + normal_input;
438 std::string error_input;
439 std::string file_error_name = "/tmp/" + _date + "_simple_error.log";
440 std::ifstream file_error(file_error_name.c_str());
443 result += "Error in reading temporary file ! filename = " + file_error_name;
446 std::getline(file_error, error_input);
448 if (error_input != "Error")
450 result += "error from simple error file ! waiting for Error and get : " + error_input;
458 BatchTest::test_jobsubmit_mpi()
465 std::string result("Failed : ");
466 std::string hostname = _batch_descr.hostname.in();
467 std::string username = _batch_descr.username.in();
468 std::string protocol = _batch_descr.protocol.in();
469 std::string batch_type = _batch_descr.batch.in();
470 std::string mpi_type = _batch_descr.mpiImpl.in();
473 if(mpi_type == "lam")
474 mpiImpl = new MpiImpl_LAM();
475 else if(mpi_type == "mpich1")
476 mpiImpl = new MpiImpl_MPICH1();
477 else if(mpi_type == "mpich2")
478 mpiImpl = new MpiImpl_MPICH2();
479 else if(mpi_type == "openmpi")
480 mpiImpl = new MpiImpl_OPENMPI();
481 else if(mpi_type == "slurmmpi")
482 mpiImpl = new MpiImpl_SLURM();
485 result += "Error MPI impl not supported : " + mpi_type;
489 // LSF et SGE not yet implemented...
490 if (batch_type == "lsf")
492 INFOS("test_jobsubmit_simple not yet implemented for lsf... return OK");
497 if (batch_type == "ccc")
499 INFOS("test_jobsubmit_simple not yet implemented for ccc... return OK");
504 if (batch_type == "slurm")
506 INFOS("test_jobsubmit_simple not yet implemented for slurm... return OK");
511 if (batch_type == "sge")
513 INFOS("test_jobsubmit_simple not yet implemented for sge... return OK");
518 // Getting home directory
519 std::string rst = get_home(&home);
526 std::string _test_file_script = _test_filename + "_script";
527 std::ofstream file_script;
528 file_script.open(_test_file_script.c_str(), std::ofstream::out);
529 file_script << "#!/bin/bash\n"
530 << "echo HELLO MPI\n";
538 (_test_file_script.c_str(), 0x1ED);
540 std::string _test_file_mpi = _test_filename + "_mpi";
541 std::ofstream file_mpi;
542 file_mpi.open(_test_file_mpi.c_str(), std::ofstream::out);
543 file_mpi << "#!/bin/bash\n"
544 << "#PBS -l nodes=1\n"
545 << "#PBS -l walltime=00:01:00\n"
546 << "#PBS -o " << home << "/" << _date << "_mpi_output.log\n"
547 << "#PBS -e " << home << "/" << _date << "_mpi_error.log\n"
548 << mpiImpl->boot("${PBS_NODEFILE}", 1)
549 << mpiImpl->run("${PBS_NODEFILE}", 1, _base_filename + "_script")
555 // Build command for copy
557 if(protocol == "rsh")
559 command += " " + _test_file_script + " "
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 if(protocol == "rsh")
572 command += " " + _test_file_mpi + " "
573 + username + "@" + hostname + ":" + home;
574 status = system(command.c_str());
576 std::ostringstream oss;
578 result += "Error in copy job file to remote host ! status = ";
583 // Build command for submit job
584 std::string file_job_name = _test_filename + "_jobid";
585 command = protocol + " " + username + "@" + hostname + " qsub " + _base_filename + "_mpi > " + file_job_name;
586 status = system(command.c_str());
588 std::ostringstream oss;
590 result += "Error in sending qsub to remote host ! status = ";
595 std::ifstream file_job(file_job_name.c_str());
598 result += "Error in reading temporary file ! filename = " + file_job_name;
601 std::getline(file_job, jobid);
604 // Wait the end of the job
605 command = protocol + " " + username + "@" + hostname + " qstat -f " + jobid + " > " + file_job_name;
609 status = system(command.c_str());
610 if(status && status != 153 && status != 256*153)
612 std::ostringstream oss;
614 result += "Error in sending qstat to remote host ! status = ";
619 if(status == 153 || status == 256*153 )
628 // Build command for getting results
630 if(protocol == "rsh")
633 + username + "@" + hostname + ":" + home + "/" + _date + "_mpi* /tmp";
634 status = system(command.c_str());
636 std::ostringstream oss;
638 result += "error in getting file result of qsub mpi from remote host ! status = ";
644 std::string normal_input;
645 std::string file_normal_name = "/tmp/" + _date + "_mpi_output.log";
646 std::ifstream file_normal(file_normal_name.c_str());
649 result += "Error in reading temporary file ! filename = " + file_normal_name;
652 bool test_ok = false;
653 while (std::getline(file_normal, normal_input))
655 if (normal_input == "HELLO MPI")
661 result += "error from mpi ouput file ! waiting for HELLO MPI please watch /tmp/" + _date + "_mpi_output.log file";
667 throw LauncherException("Method BatchTest::test_jobsubmit_mpi is not available "
668 "(libBatch was not present at compilation time)");
673 BatchTest::test_appli()
678 std::string result("Failed : ");
679 std::string hostname = _batch_descr.hostname.in();
680 std::string username = _batch_descr.username.in();
681 std::string protocol = _batch_descr.protocol.in();
682 std::string applipath = _batch_descr.applipath.in();
684 // Getting home directory
685 std::string rst = get_home(&home);
691 std::string _test_file_appli = _test_filename + "_appli_test";
692 std::ofstream file_appli;
693 file_appli.open(_test_file_appli.c_str(), std::ofstream::out);
694 file_appli << "#!/bin/bash\n"
695 << "if [ -f " << applipath << "/runAppli ]\n"
704 // Build command for copy
706 if(protocol == "rsh")
708 command += " " + _test_file_appli + " "
709 + username + "@" + hostname + ":" + home;
710 status = system(command.c_str());
712 std::ostringstream oss;
714 result += "Error in copy appli test file to remote host ! status = ";
720 command = protocol + " " + username + "@" + hostname
721 + " sh " + home + "/" + _base_filename + "_appli_test > "
722 + _test_filename + "_appli_test_result";
724 status = system(command.c_str());
726 std::ostringstream oss;
728 result += "Error in launching appli test on remote host ! status = ";
734 std::string rst_appli;
735 std::string file_appli_result_name = _test_filename + "_appli_test_result";
736 std::ifstream file_appli_result(file_appli_result_name.c_str());
737 if (!file_appli_result)
739 result += "Error in reading temporary file ! filename = " + file_appli_result_name;
742 std::getline(file_appli_result, rst_appli);
743 file_appli_result.close();
745 if (rst_appli != "OK")
747 result += "Error checking application on remote host ! result = " + rst;
757 BatchTest::get_home(std::string * home)
760 std::string result = "";
762 std::string hostname = _batch_descr.hostname.in();
763 std::string username = _batch_descr.username.in();
764 std::string protocol = _batch_descr.protocol.in();
765 std::string file_home_name = _test_filename + "_home";
767 command = protocol + " " + username + "@" + hostname + " 'echo $HOME' > " + file_home_name;
768 status = system(command.c_str());
770 std::ostringstream oss;
772 result += "Error in getting home directory ! status = ";
777 std::ifstream file_home(file_home_name.c_str());
780 result += "Error in reading temporary file ! filename = " + file_home_name;
783 std::getline(file_home, *home);