boinc/tools/boinc_submit

340 lines
8.1 KiB
Plaintext
Raw Normal View History

#!/usr/bin/env php
<?php
// Submit a single job.
// Implementation notes:
// - The jobs use the app "single_job_PLATFORM".
// This app has a single app_version containing the wrapper for that platform
// - the executable is part of the WU, and has the sticky bit set,
// and has a signature
// - The logical and physical name of the executable
// (as stored in the download directory) is "program_platform_cksum"
// where cksum is the last 8 chars of the MD5
// - The physical name of the job file is job_WUID.xml
// - The physical names of the input/output files are name_WUID
// - a file containing the job directory is stored in
// sj_WUID in the upload hierarchy
// - a workunit template sj_WUID is created in templates/
// - the single_job_assimilator copies the output files to the job dir,
// and cleans up the sj_WUID and WU template files
ini_set('error_reporting', E_ALL);
// global vars
//
$project_dir = null;
$job_dir = getcwd();
$platform = 'i686-pc-linux-gnu';
$infiles = array();
$outfiles = array();
$stdin_file = null;
$stdout_file = null;
$program = null;
$cmdline_args = null;
$app_name = null;
$wu_template_filename = null;
// relative to project dir
$result_template_filename = null;
// relative to project dir
function get_project_dir() {
global $project_dir;
$project_dir = getenv('BOINC_PROJECT_DIR');
if (!$project_dir) {
echo "You must set the environment variable BOINC_PROJECT_DIR
to the path of a BOINC project, e.g.:
> setenv BOINC_PROJECT_DIR ~/projects/my_project
";
exit(1);
}
}
function usage() {
echo "Usage: boinc_job [options] program
--platform p
Run the program on platform p
--infile f
The program will use f as an input file
--outfile f
The program will use f as an output file
--stdin f
Direct f to the program's stdin
--stdout f
Direct the program's stdout to f
";
exit(1);
}
function error($msg) {
echo "$msg\n";
exit(1);
}
function download_path($filename) {
global $project_dir;
return dir_hier_path($filename, "$project_dir/download", 1024);
}
function upload_path($filename) {
global $project_dir;
return dir_hier_path($filename, "$project_dir/upload", 1024);
}
function do_includes() {
global $project_dir;
chdir("$project_dir/html/ops");
require_once("../inc/boinc_db.inc");
require_once("../inc/dir_hier.inc");
BoincDb::get();
}
function check_app_version() {
global $platform, $app_name;
$app_name = "single_job_$platform";
$app = BoincApp::lookup("name='$app_name'");
if (!$app) {
error("This project isn't configured to run single jobs.");
}
}
// make the job.xml file used by the wrapper
//
function make_wrapper_job_file() {
global $program, $stdin_file, $stdout_file, $cmdline_args, $wuid;
global $project_dir;
chdir($project_dir);
$filename = "sj_$wuid.xml";
$path = download_path($filename);
$f = fopen($path, "w");
if (!$f) {
error("Can't open $path");
}
fwrite($f,
"<job_desc>
<task>
<application>$program</application>
");
if ($stdin_file) {
fwrite($f, " <stdin_filename>$stdin_file</stdin_filename>\n");
}
if ($stdout_file) {
fwrite($f, " <stdout_filename>$stdout_file</stdout_filename>\n");
}
if ($cmdline_args) {
fwrite($f, " <command_line>$cmdline_args</command_line>\n");
}
fwrite($f, " </task>\n</job_desc>\n");
fclose($f);
}
function make_wu_template() {
global $wuid, $infiles, $stdin_file, $program, $wu_template_filename;
global $project_dir;
chdir($project_dir);
$wu_template_filename = "templates/sj_wu_template_$wuid";
$f = fopen($wu_template_filename, "w");
if (!$f) {
error("Can't open $wu_template_filename");
}
for ($i=0; $i<count($infiles)+2; $i++) {
fwrite($f,
"<file_info>
<number>$i</number>
</file_info>
");
}
fwrite($f, "<workunit>\n");
$i = 0;
foreach($infiles as $infile) {
fwrite($f,
" <file_ref>
<file_number>$i</file_number>
<open_name>$infile</open_name>
<copy_file/>
</file_ref>
");
$i++;
}
if ($stdin_file) {
fwrite($f,
" <file_ref>
<file_number>$i</file_number>
<open_name>stdin</open_name>
</file_ref>
");
$i++;
}
fwrite($f,
" <file_ref>
<file_number>$i</file_number>
<open_name>$program</open_name>
<copy_file/>
</file_ref>
");
fwrite($f,
" <rsc_fpops_bound>1e18</rsc_fpops_bound>
<rsc_fpops_est>1e15</rsc_fpops_est>
</workunit>
");
fclose($f);
}
function make_result_template() {
global $wuid, $outfiles, $stdout_file, $project_dir;
global $result_template_filename;
chdir($project_dir);
$result_template_filename = "templates/sj_result_template_$wuid";
$f = fopen($result_template_filename, "w");
if (!$f) {
error("Can't open $result_template_filename");
}
$i = 0;
foreach($outfiles as $outfile) {
fwrite($f,
"<file_info>
<name><OUTFILE_$i/></name>
<generated_locally/>
<upload_when_present/>
<max_nbytes>1e12</max_nbytes>
<url><UPLOAD_URL/></url>
</file_info>
");
}
fwrite($f, "<result>\n");
$i = 0;
foreach($outfiles as $outfile) {
fwrite($f,
" <file_ref>
<file_name><OUTFILE_$i/></file_name>
<open_name>$outfile</open_name>
<copy_file/>
</file_ref>
");
$i++;
}
if ($stdout_file) {
fwrite($f,
" <file_ref>
<file_name><OUTFILE_$i/></file_name>
<open_name>stdout</open_name>
</file_ref>
");
}
fwrite($f, "</result>\n");
fclose($f);
}
// make the sj_WUID file
//
function make_job_file() {
global $wuid, $job_dir, $project_dir;
chdir($project_dir);
$filename = "sj_$wuid";
$path = upload_path($filename);
$f = fopen($path, "w");
if (!$f) {
error("Can't open $path");
}
fwrite($f,
"<job_dir>$job_dir</job_dir>
");
fclose($f);
}
function create_wu() {
global $wuid;
$name = md5(uniqid(rand(), true));
$wuid = BoincWorkunit::insert("(name, transition_time) values ('$name', ".PHP_INT_MAX.")");
}
function create_job() {
global $wuid, $app_name, $infiles, $program, $project_dir;
global $result_template_filename, $wu_template_filename;
chdir($project_dir);
$cmd = "bin/create_work --appname $app_name --wu_name sj_$wuid --wu_id $wuid --wu_template $wu_template_filename --result_template $result_template_filename";
foreach ($infiles as $infile) {
$cmd .= " $infile";
}
$cmd .= " sj_$wuid.xml";
$cmd .= " $program";
echo "Executing command: $cmd\n";
system($cmd);
}
// copy input files and program file to the download hierarchy
//
function copy_files() {
global $infiles, $wuid, $job_dir, $program;
chdir($job_dir);
foreach ($infiles as $infile) {
$filename = "$infile_$wuid";
$path = download_path($filename);
echo "copying $infile to $path\n";
copy($infile, $path);
}
$path = download_path($program);
echo "copying $program to $path\n";
copy($program, $path);
}
function parse_args($argc, $argv) {
global $platform, $infiles, $outfiles, $stdin_file, $stdout_file;
global $program, $cmdline_args;
for ($i=1; $i<$argc; $i++) {
switch ($argv[$i]) {
case '--platform':
$platform = $argv[++$i];
break;
case '--infile':
$infiles[] = $argv[++$i];
break;
case '--outfile':
$outfiles[] = $argv[++$i];
break;
case '--stdin':
$stdin_file = $argv[++$i];
break;
case '--stdout':
$stdout_file = $argv[++$i];
break;
default:
if ($program) {
$cmdline_args .= ''.$argv[$i];
} else {
$program = $argv[$i];
}
break;
}
}
if (!$program) usage();
}
get_project_dir();
parse_args($argc, $argv);
do_includes();
check_app_version();
create_wu();
make_wrapper_job_file();
make_job_file();
make_wu_template();
make_result_template();
copy_files();
create_job();
?>