]> SALOME platform Git repositories - modules/kernel.git/blob - src/Launcher/BatchTest.cxx
Salome HOME
Porting functionality on Win32 Platform
[modules/kernel.git] / src / Launcher / BatchTest.cxx
1 #include "BatchTest.hxx"
2
3 #include "Batch_Date.hxx"
4 #include "MpiImpl.hxx"
5 #include "utilities.h"
6
7 #include <sys/stat.h>
8 #include <iostream>
9 #include <fstream>
10 #ifdef WIN32
11 # include <io.h>
12 #endif
13 BatchTest::BatchTest(const Engines::MachineParameters& batch_descr) 
14 {
15   _batch_descr = batch_descr;
16
17   // Getting date
18   Batch::Date date = Batch::Date(time(0));
19   _date = date.str();
20   int lend = _date.size() ;
21   int i = 0 ;
22   while (i < lend) 
23   {
24     if (_date[i] == '/' || _date[i] == '-' || _date[i] == ':' ) 
25     {
26       _date[i] = '_' ;
27     }
28     i++ ;
29   }
30   
31   // Creating test temporary file
32   _test_filename =  "/tmp/";
33   _test_filename +=  _date + "_test_cluster_file_";
34   _test_filename += _batch_descr.alias.in();
35   _base_filename = _date + "_test_cluster_file_" + _batch_descr.alias.in();
36 }
37
38 BatchTest::~BatchTest() {}
39
40 bool
41 BatchTest::test()
42 {
43   bool rtn = false;
44   INFOS(std::endl 
45         << "--- Testing batch Machine :" << std::endl
46         << "--- Name       : " << _batch_descr.hostname << std::endl
47         << "--- Alias      : " << _batch_descr.alias << std::endl
48         << "--- Protocol   : " << _batch_descr.protocol << std::endl
49         << "--- User Name  : " << _batch_descr.username << std::endl
50         << "--- Batch Type : " << _batch_descr.batch << std::endl
51         << "--- MPI Impl   : " << _batch_descr.mpiImpl << std::endl
52         << "--- Appli Path : " << _batch_descr.applipath << std::endl
53        );
54
55   std::string result_connection("Not Tested");
56   std::string result_filecopy("Not Tested");
57   std::string result_getresult("Not Tested");
58   std::string result_jobsubmit_simple("Not Tested");
59   std::string result_jobsubmit_mpi("Not Tested");
60   std::string result_appli("Not Tested");
61
62   result_connection = test_connection();
63   result_filecopy = test_filecopy();
64   result_getresult = test_getresult();
65   result_jobsubmit_simple = test_jobsubmit_simple();
66   result_jobsubmit_mpi = test_jobsubmit_mpi();
67   result_appli = test_appli();
68
69   INFOS(std::endl
70         << "--- Test results" << std::endl
71         << "--- Connection          : " << result_connection << std::endl
72         << "--- File copy           : " << result_filecopy << std::endl
73         << "--- Get results         : " << result_getresult << std::endl
74         << "--- Submit simple job   : " << result_jobsubmit_simple << std::endl
75         << "--- Submit mpi job      : " << result_jobsubmit_mpi << std::endl
76         << "--- Application         : " << result_appli << std::endl
77        );
78   
79   if (result_connection == "OK"       && 
80       result_filecopy == "OK"         &&
81       result_getresult == "OK"        &&
82       result_jobsubmit_simple == "OK" &&
83       result_jobsubmit_mpi == "OK"    &&
84       result_appli == "OK")
85     rtn = true;
86       
87   return rtn;
88 }
89
90 // For this test we use : alias, protocol, username
91 std::string
92 BatchTest::test_connection()
93 {
94   int status;
95   std::string command;
96   std::string result("Failed : ");
97   std::string alias = _batch_descr.alias.in();
98   std::string username = _batch_descr.username.in();
99   std::string protocol = _batch_descr.protocol.in();
100
101   // Basic tests
102   if(alias == "")
103   {
104     result += "alias is empty !";
105     return result;
106   }
107   if(username == "")
108   {
109     result += "username is empty !";
110     return result;
111   }
112   if( protocol != "rsh" && protocol != "ssh")
113   {
114     result += "protocol unknown ! (" + protocol + ")";
115     return result;
116   }
117
118   // Build command
119   command += protocol
120           + " "
121           + username + "@" + alias;
122
123   // Test
124   status = system(command.c_str());
125   if(status) {
126     std::ostringstream oss;
127     oss << status;
128     result += "Error of connection on remote host ! status = ";
129     result += oss.str();
130     return result;
131   }
132
133   result = "OK";
134   return result;
135 }
136
137 // For this test we use : alias, protocol, username
138 std::string
139 BatchTest::test_filecopy()
140 {
141   int status;
142   std::string home;
143   std::string command;
144   std::string result("Failed : ");
145   std::string alias = _batch_descr.alias.in();
146   std::string username = _batch_descr.username.in();
147   std::string protocol = _batch_descr.protocol.in();
148
149   // Getting home directory
150   std::string rst = get_home(&home);
151   if(rst != "") {
152     result += rst;
153     return result;
154   }
155
156   // Writing into the tempory file
157   command = "echo Hello > " +  _test_filename;
158   status = system(command.c_str());
159   if(status) {
160     std::ostringstream oss;
161     oss << status;
162     result += "Error in creating tempory file ! status = ";
163     result += oss.str();
164     return result;
165   }
166
167   // Build command
168   command = "scp";
169   if(protocol == "rsh")
170     command = "rcp";
171   command += " " + _test_filename + " "
172           + username + "@" + alias + ":" + home;
173
174   // Test
175   status = system(command.c_str());
176   if(status) {
177     std::ostringstream oss;
178     oss << status;
179     result += "Error in copy file on remote host ! status = ";
180     result += oss.str();
181     return result;
182   }
183
184   result = "OK";
185   return result;
186 }
187
188 // For this test we use : alias, protocol, username
189 std::string
190 BatchTest::test_getresult()
191 {
192   int status;
193   std::string home;
194   std::string command;
195   std::string result("Failed : ");
196   std::string alias = _batch_descr.alias.in();
197   std::string username = _batch_descr.username.in();
198   std::string protocol = _batch_descr.protocol.in();
199
200   // Getting home directory
201   std::string rst = get_home(&home);
202   if(rst != "") {
203     result += rst;
204     return result;
205   }
206
207   // Build command
208   command = "scp";
209   if(protocol == "rsh")
210     command = "rcp";
211   command += " " + username + "@" + alias + ":" + home 
212           + "/" + _base_filename + " " + _test_filename + "_copy";
213
214   // Test
215   status = system(command.c_str());
216   if(status) {
217     std::ostringstream oss;
218     oss << status;
219     result += "Error in copy file from remote host ! status = ";
220     result += oss.str();
221     return result;
222   }
223   
224   // Compare files
225   std::ifstream src_file(_test_filename.c_str());
226   if (!src_file)
227   {
228     result += "Error in reading temporary file ! filename = " + _test_filename;
229     return result;
230   }
231   std::string cp_filename = _test_filename + "_copy";
232   std::ifstream cp_file(cp_filename.c_str());
233   if (!cp_file)
234   {
235     result += "Error in reading temporary copy file ! filename = " + cp_filename;
236     return result;
237   }
238   std::string src_firstline;
239   std::string cp_firstline;
240   std::getline(src_file, src_firstline);
241   std::getline(cp_file, cp_firstline);
242   src_file.close();
243   cp_file.close();
244   if (src_firstline != cp_firstline)
245   {
246     result += "Error source file and copy file are not equa ! source = " + src_firstline + " copy = " + cp_firstline;
247     return result;
248   }
249
250   result = "OK";
251   return result;
252 }
253
254 std::string 
255 BatchTest::test_jobsubmit_simple() 
256 {
257   int status;
258   std::string home;
259   std::string command;
260   std::string result("Failed : ");
261   std::string alias = _batch_descr.alias.in();
262   std::string username = _batch_descr.username.in();
263   std::string protocol = _batch_descr.protocol.in();
264   std::string batch_type = _batch_descr.batch.in();
265
266   // Basic test
267   if (batch_type == "slurm")
268   {
269     INFOS("test_jobsubmit_simple not yet implemented for slurm... return OK");
270     result = "OK";
271     return result;
272   }
273   if (batch_type != "pbs")
274   {
275     result += "Batch type unknown ! : " + batch_type;
276     return result;
277   }
278
279   // Getting home directory
280   std::string rst = get_home(&home);
281   if(rst != "") {
282     result += rst;
283     return result;
284   }
285
286   // PBS test
287   std::string _test_file_simple = _test_filename + "_simple";
288   std::ofstream file;
289   file.open(_test_file_simple.c_str(), std::ofstream::out);
290   file << "#!/bin/bash\n"
291        << "#PBS -l nodes=1\n"
292        << "#PBS -l walltime=00:01:00\n"
293        << "#PBS -o " + home + "/" + _date + "_simple_output.log\n"
294        << "#PBS -e " + home + "/" + _date + "_simple_error.log\n"
295        << "echo Bonjour\n"
296        << "echo Error >&2\n";
297   file.flush();
298   file.close();
299
300
301   // Build command for copy
302   command = "scp";
303   if(protocol == "rsh")
304     command = "rcp";
305   command += " " + _test_file_simple + " "
306           + username + "@" + alias + ":" + home;
307   status = system(command.c_str());
308   if(status) {
309     std::ostringstream oss;
310     oss << status;
311     result += "Error in copy job file to remote host ! status = ";
312     result += oss.str();
313     return result;
314   }
315
316   // Build command for submit job
317   std::string file_job_name = _test_filename + "_jobid";
318   command = protocol + " " + username + "@" + alias + " qsub " + _base_filename + "_simple > " + file_job_name;
319   status = system(command.c_str());
320   if(status) {
321     std::ostringstream oss;
322     oss << status;
323     result += "Error in sending qsub to remote host ! status = ";
324     result += oss.str();
325     return result;
326   }
327   std::string jobid;
328   std::ifstream file_job(file_job_name.c_str());
329   if (!file_job)
330   {
331     result += "Error in reading temporary file ! filename = " + file_job_name;
332     return result;
333   }
334   std::getline(file_job, jobid);
335   file_job.close();
336  
337   // Wait the end of the job
338   command = protocol + " " + username + "@" + alias + " qstat -f " + jobid + " > " + file_job_name;
339   bool stop = false;
340   while (!stop) 
341   {
342     status = system(command.c_str());
343     if(status && status != 153 && status != 256*153)
344     {
345       std::ostringstream oss;
346       oss << status;
347       result += "Error in sending qstat to remote host ! status = ";
348       result += oss.str();
349       return result;
350     }
351
352     if(status == 153 || status == 256*153 )
353       stop = true;
354 #ifdef WIN32
355     Sleep(1);
356 #else
357     sleep(1);
358 #endif
359   }
360
361   // Build command for getting results
362   command = "scp";
363   if(protocol == "rsh")
364     command = "rcp";
365   command += " " 
366           + username + "@" + alias + ":" + home + "/" + _date + "_simple* /tmp";
367   status = system(command.c_str());
368   if(status) {
369     std::ostringstream oss;
370     oss << status;
371     result += "error in getting file result of qsub simple to remote host ! status = ";
372     result += oss.str();
373     return result;
374   }
375   
376   // Test results
377   std::string normal_input;
378   std::string file_normal_name = "/tmp/" + _date + "_simple_output.log";
379   std::ifstream file_normal(file_normal_name.c_str());
380   if (!file_normal)
381   {
382     result += "Error in reading temporary file ! filename = " + file_normal_name;
383     return result;
384   }
385   std::getline(file_normal, normal_input);
386   file_normal.close();
387   if (normal_input != "Bonjour")
388   {
389     result += "error from simple ouput file ! waiting for Bonjour and get : " + normal_input;
390     return result;
391   }
392   std::string error_input;
393   std::string file_error_name = "/tmp/" + _date + "_simple_error.log";
394   std::ifstream file_error(file_error_name.c_str());
395   if (!file_error)
396   {
397     result += "Error in reading temporary file ! filename = " + file_error_name;
398     return result;
399   }
400   std::getline(file_error, error_input);
401   file_error.close();
402   if (error_input != "Error")
403   {
404     result += "error from simple error file ! waiting for Error and get : " + error_input;
405     return result;
406   }
407   result = "OK";
408   return result;
409 }
410
411 std::string 
412 BatchTest::test_jobsubmit_mpi() 
413 {
414   int status;
415   std::string home;
416   std::string command;
417   MpiImpl * mpiImpl;
418   std::string result("Failed : ");
419   std::string alias = _batch_descr.alias.in();
420   std::string username = _batch_descr.username.in();
421   std::string protocol = _batch_descr.protocol.in();
422   std::string batch_type = _batch_descr.batch.in();
423   std::string mpi_type = _batch_descr.mpiImpl.in();
424
425   // Basic test
426   if(mpi_type == "lam")
427     mpiImpl = new MpiImpl_LAM();
428   else if(mpi_type == "mpich1")
429     mpiImpl = new MpiImpl_MPICH1();
430   else if(mpi_type == "mpich2")
431     mpiImpl = new MpiImpl_MPICH2();
432   else if(mpi_type == "openmpi")
433     mpiImpl = new MpiImpl_OPENMPI();
434   else
435   {
436     result += "Error MPI impl not supported : " + mpi_type;
437     return result;
438   }
439
440   // SLURM not yet implemented...
441   if (batch_type == "slurm")
442   {
443     INFOS("test_jobsubmit_simple not yet implemented for slurm... return OK");
444     result = "OK";
445     return result;
446   }
447
448   // Getting home directory
449   std::string rst = get_home(&home);
450   if(rst != "") {
451     result += rst;
452     return result;
453   }
454
455   // MPI test
456   std::string _test_file_script = _test_filename + "_script";
457   std::ofstream file_script;
458   file_script.open(_test_file_script.c_str(), std::ofstream::out);
459   file_script << "#!/bin/bash\n"
460               << "echo HELLO MPI\n";
461   file_script.flush();
462   file_script.close();
463 #ifdef WIN32
464   _chmod
465 #else
466   chmod
467 #endif
468     (_test_file_script.c_str(), 0x1ED);
469
470   std::string _test_file_mpi = _test_filename + "_mpi";
471   std::ofstream file_mpi;
472   file_mpi.open(_test_file_mpi.c_str(), std::ofstream::out);
473   file_mpi << "#!/bin/bash\n"
474            << "#PBS -l nodes=1\n"
475            << "#PBS -l walltime=00:01:00\n"
476            << "#PBS -o " << home << "/" << _date << "_mpi_output.log\n"
477            << "#PBS -e " << home << "/" << _date << "_mpi_error.log\n"
478            << mpiImpl->boot("${PBS_NODEFILE}", 1)
479            << mpiImpl->run("${PBS_NODEFILE}", 1, _base_filename + "_script")
480            << mpiImpl->halt();
481   file_mpi.flush();
482   file_mpi.close();
483
484
485   // Build command for copy
486   command = "scp";
487   if(protocol == "rsh")
488     command = "rcp";
489   command += " " + _test_file_script + " "
490           + username + "@" + alias + ":" + home;
491   status = system(command.c_str());
492   if(status) {
493     std::ostringstream oss;
494     oss << status;
495     result += "Error in copy job file to remote host ! status = ";
496     result += oss.str();
497     return result;
498   }
499   command = "scp";
500   if(protocol == "rsh")
501     command = "rcp";
502   command += " " + _test_file_mpi + " "
503           + username + "@" + alias + ":" + home;
504   status = system(command.c_str());
505   if(status) {
506     std::ostringstream oss;
507     oss << status;
508     result += "Error in copy job file to remote host ! status = ";
509     result += oss.str();
510     return result;
511   }
512
513   // Build command for submit job
514   std::string file_job_name = _test_filename + "_jobid";
515   command = protocol + " " + username + "@" + alias + " qsub " + _base_filename + "_mpi > " + file_job_name;
516   status = system(command.c_str());
517   if(status) {
518     std::ostringstream oss;
519     oss << status;
520     result += "Error in sending qsub to remote host ! status = ";
521     result += oss.str();
522     return result;
523   }
524   std::string jobid;
525   std::ifstream file_job(file_job_name.c_str());
526   if (!file_job)
527   {
528     result += "Error in reading temporary file ! filename = " + file_job_name;
529     return result;
530   }
531   std::getline(file_job, jobid);
532   file_job.close();
533  
534   // Wait the end of the job
535   command = protocol + " " + username + "@" + alias + " qstat -f " + jobid + " > " + file_job_name;
536   bool stop = false;
537   while (!stop) 
538   {
539     status = system(command.c_str());
540     if(status && status != 153 && status != 256*153)
541     {
542       std::ostringstream oss;
543       oss << status;
544       result += "Error in sending qstat to remote host ! status = ";
545       result += oss.str();
546       return result;
547     }
548
549     if(status == 153 || status == 256*153 )
550       stop = true;
551 #ifdef WIN32
552     Sleep(1);
553 #else
554     sleep(1);
555 #endif
556   }
557
558   // Build command for getting results
559   command = "scp";
560   if(protocol == "rsh")
561     command = "rcp";
562   command += " " 
563           + username + "@" + alias + ":" + home + "/" + _date + "_mpi* /tmp";
564   status = system(command.c_str());
565   if(status) {
566     std::ostringstream oss;
567     oss << status;
568     result += "error in getting file result of qsub mpi from remote host ! status = ";
569     result += oss.str();
570     return result;
571   }
572   
573   // Test results
574   std::string normal_input;
575   std::string file_normal_name = "/tmp/" + _date + "_mpi_output.log";
576   std::ifstream file_normal(file_normal_name.c_str());
577   if (!file_normal)
578   {
579     result += "Error in reading temporary file ! filename = " + file_normal_name;
580     return result;
581   }
582   bool test_ok = false;
583   while (std::getline(file_normal, normal_input))
584   {
585     if (normal_input == "HELLO MPI")
586       test_ok = true;
587   }
588   file_normal.close();
589   if (!test_ok)
590   {
591     result += "error from mpi ouput file ! waiting for HELLO MPI please watch /tmp/" + _date + "_mpi_output.log file";
592     return result;
593   }
594   result = "OK";
595   return result;  
596 }
597
598 std::string 
599 BatchTest::test_appli()
600 {
601   int status;
602   std::string home;
603   std::string command;
604   std::string result("Failed : ");
605   std::string alias = _batch_descr.alias.in();
606   std::string username = _batch_descr.username.in();
607   std::string protocol = _batch_descr.protocol.in();
608   std::string applipath = _batch_descr.applipath.in();
609   
610   // Getting home directory
611   std::string rst = get_home(&home);
612   if(rst != "") {
613     result += rst;
614     return result;
615   }
616
617   std::string _test_file_appli = _test_filename + "_appli_test";
618   std::ofstream file_appli;
619   file_appli.open(_test_file_appli.c_str(), std::ofstream::out);
620   file_appli << "#!/bin/bash\n"
621              << "if [ -f " << applipath << "/runAppli ]\n"
622              << "then\n"
623              << "  echo OK\n"
624              << "else\n"
625              << "  echo NOK\n"
626              << "fi\n";
627   file_appli.flush();
628   file_appli.close();
629
630   // Build command for copy
631   command = "scp";
632   if(protocol == "rsh")
633     command = "rcp";
634   command += " " + _test_file_appli + " "
635           + username + "@" + alias + ":" + home;
636   status = system(command.c_str());
637   if(status) {
638     std::ostringstream oss;
639     oss << status;
640     result += "Error in copy appli test file to remote host ! status = ";
641     result += oss.str();
642     return result;
643   }
644
645   // Launch test
646   command = protocol + " " + username + "@" + alias 
647           + " sh " + home + "/" + _base_filename + "_appli_test > " 
648           + _test_filename + "_appli_test_result";
649
650   status = system(command.c_str());
651   if(status) {
652     std::ostringstream oss;
653     oss << status;
654     result += "Error in launching appli test on remote host ! status = ";
655     result += oss.str();
656     return result;
657   }
658
659   // Read test result
660   std::string rst_appli;
661   std::string file_appli_result_name = _test_filename + "_appli_test_result";
662   std::ifstream file_appli_result(file_appli_result_name.c_str());
663   if (!file_appli_result)
664   {
665     result += "Error in reading temporary file ! filename = " + file_appli_result_name;
666     return result;
667   }
668   std::getline(file_appli_result, rst_appli);
669   file_appli_result.close();
670   
671   if (rst_appli != "OK")
672   {
673     result += "Error checking application on remote host ! result = " + rst;
674     return result;
675   }
676
677   result = "OK";
678   return result;
679 }
680
681 // Useful methods
682 std::string
683 BatchTest::get_home(std::string * home)
684 {
685   int status;
686   std::string result = "";
687   std::string command;
688   std::string alias = _batch_descr.alias.in();
689   std::string username = _batch_descr.username.in();
690   std::string protocol = _batch_descr.protocol.in();
691   std::string file_home_name = _test_filename + "_home";
692
693   command = protocol + " " + username + "@" + alias + " 'echo $HOME' > " + file_home_name; 
694   status = system(command.c_str());
695   if(status) {
696     std::ostringstream oss;
697     oss << status;
698     result += "Error in getting home directory ! status = ";
699     result += oss.str();
700     return result;
701   }
702
703   std::ifstream file_home(file_home_name.c_str());
704   if (!file_home)
705   {
706     result += "Error in reading temporary file ! filename = " + file_home_name;
707     return result;
708   }
709   std::getline(file_home, *home);
710   file_home.close();
711   return result;
712 }