Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
Slurm
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
tud-zih-energy
Slurm
Commits
16c112fb
Commit
16c112fb
authored
9 years ago
by
Danny Auble
Browse files
Options
Downloads
Patches
Plain Diff
Rough draft for bsub, not working yet
parent
d584800f
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
contribs/openlava/bsub.pl
+531
-0
531 additions, 0 deletions
contribs/openlava/bsub.pl
with
531 additions
and
0 deletions
contribs/openlava/bsub.pl
+
531
−
0
View file @
16c112fb
#! /usr/bin/perl -w
###############################################################################
#
# bsub - submit jobs in familar openlava format.
#
#
###############################################################################
# Copyright (C) 2015 SchedMD LLC.
# Written by Danny Auble <da@schedmd.com>.
#
# This file is part of SLURM, a resource management program.
# For details, see <http://slurm.schedmd.com/>.
# Please also read the included file: DISCLAIMER.
#
# SLURM is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# In addition, as a special exception, the copyright holders give permission
# to link the code of portions of this program with the OpenSSL library under
# certain conditions as described in each individual source file, and
# distribute linked combinations including the two. You must obey the GNU
# General Public License in all respects for all of the code used other than
# OpenSSL. If you modify file(s) with this exception, you may extend this
# exception to your version of the file(s), but you are not obligated to do
# so. If you do not wish to do so, delete this exception statement from your
# version. If you delete this exception statement from all source files in
# the program, then also delete it here.
#
# SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with SLURM; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
###############################################################################
#use strict;
use
FindBin
;
use
Getopt::
Long
2.24
qw(:config no_ignore_case)
;
use
lib
"
${FindBin
::
Bin}
/../lib/perl
";
use
autouse
'
Pod::Usage
'
=>
qw(pod2usage)
;
use
Slurm
'
:all
';
use
Slurmdb
'
:all
';
# needed for getting the correct cluster dims
use
Switch
;
my
(
#$start_time,
#$account,
#$array,
$err_path
,
#$export_env,
$interactive
,
#$hold,
#$resource_list,
#$mail_options,
#$mail_user_list,
$job_name
,
$node_list
,
$mem_limit
,
$min_proc
,
$out_path
,
#$priority,
$partition
,
#$variable_list,
#@additional_attributes,
$help
,
$man
);
my
$sbatch
=
"
${FindBin
::
Bin}
/sbatch
";
my
$salloc
=
"
${FindBin
::
Bin}
/salloc
";
my
$srun
=
"
${FindBin
::
Bin}
/srun
";
GetOptions
(
#'a=s' => \$start_time,
#'A=s' => \$account,
'
e=s
'
=>
\
$err_path
,
#'h' => \$hold,
'
I
'
=>
\
$interactive
,
#'j:s' => sub { warn "option -j is the default, " .
'
J=s
'
=>
\
$job_name
,
#"stdout/stderr go into the same file\n" },
#'J=s' => \$array,
#'l=s' => \$resource_list,
'
m=s
'
=>
\
$node_list
,
'
M=s
'
=>
\
$mem_limit
,
'
n=s
'
=>
\
$min_proc
,
'
o=s
'
=>
\
$out_path
,
#'p=i' => \$priority,
'
q=s
'
=>
\
$partition
,
#'S=s' => sub { warn "option -S is ignored, " .
# "specify shell via #!<shell> in the job script\n" },
#'t=s' => \$array,
#'v=s' => \$variable_list,
#'V' => \$export_env,
#'W=s' => \@additional_attributes,
'
help|?
'
=>
\
$help
,
'
man
'
=>
\
$man
,
)
or
pod2usage
(
2
);
# Display usage if necessary
pod2usage
(
0
)
if
$help
;
if
(
$man
)
{
if
(
$<
==
0
)
{
# Cannot invoke perldoc as root
my
$id
=
eval
{
getpwnam
("
nobody
")
};
$id
=
eval
{
getpwnam
("
nouser
")
}
unless
defined
$id
;
$id
=
-
2
unless
defined
$id
;
$<
=
$id
;
}
$>
=
$<
;
# Disengage setuid
$ENV
{
PATH
}
=
"
/bin:/usr/bin
";
# Untaint PATH
delete
@ENV
{'
IFS
',
'
CDPATH
',
'
ENV
',
'
BASH_ENV
'};
if
(
$
0
=~
/^([-\/\w\.]+)$/
)
{
$
0
=
$
1
;
}
# Untaint $0
else
{
die
"
Illegal characters were found in
\$
0 ($0)
\n
";
}
pod2usage
(
-
exitstatus
=>
0
,
-
verbose
=>
2
);
}
# Use sole remaining argument as the exe or script
my
$script
;
if
(
$ARGV
[
0
])
{
foreach
(
@ARGV
)
{
$script
.=
"
$_
";
}
}
my
$command
;
if
(
$interactive
||
!
$script
)
{
$command
=
"
$salloc
";
# Always want at least one node in the allocation
if
(
!
$node_opts
{
node_cnt
})
{
$node_opts
{
node_cnt
}
=
1
;
}
}
else
{
if
(
!
$script
)
{
pod2usage
(
2
);
}
if
(
_check_script
(
$script
))
{
$command
=
"
$sbatch
";
}
else
{
$command
=
"
$srun
";
}
$command
.=
"
-e
$err_path
"
if
$err_path
;
$command
.=
"
-o
$out_path
"
if
$out_path
;
}
#################################### HERE IS WHERE I LEFT OFF
$command
.=
"
-n
$node_opts
{task_cnt}
"
if
$ntask_cnt
};
$command
.=
"
-w
$node_opts
{hostlist}
"
if
$node_opts
{
hostlist
};
$command
.=
"
--mincpus=
$res_opts
{ncpus}
"
if
$res_opts
{
ncpus
};
$command
.=
"
--ntasks-per-node=
$res_opts
{mppnppn}
"
if
$res_opts
{
mppnppn
};
if
(
$res_opts
{
walltime
})
{
$command
.=
"
-t
$res_opts
{walltime}
";
}
elsif
(
$res_opts
{
cput
})
{
$command
.=
"
-t
$res_opts
{cput}
";
}
elsif
(
$res_opts
{
pcput
})
{
$command
.=
"
-t
$res_opts
{pcput}
";
}
$command
.=
"
--account='
$group_list
'
"
if
$group_list
;
$command
.=
"
--array='
$array
'
"
if
$array
;
$command
.=
"
--constraint='
$res_opts
{proc}'
"
if
$res_opts
{
proc
};
$command
.=
"
--dependency=
$depend
"
if
$depend
;
$command
.=
"
--tmp=
$res_opts
{file}
"
if
$res_opts
{
file
};
$command
.=
"
--mem=
$res_opts
{mem}
"
if
$res_opts
{
mem
};
$command
.=
"
--nice=
$res_opts
{nice}
"
if
$res_opts
{
nice
};
$command
.=
"
--gres=gpu:
$res_opts
{naccelerators}
"
if
$res_opts
{
naccelerators
};
# Cray-specific options
$command
.=
"
-n
$res_opts
{mppwidth}
"
if
$res_opts
{
mppwidth
};
$command
.=
"
-w
$res_opts
{mppnodes}
"
if
$res_opts
{
mppnodes
};
$command
.=
"
--cpus-per-task=
$res_opts
{mppdepth}
"
if
$res_opts
{
mppdepth
};
$command
.=
"
--begin=
$start_time
"
if
$start_time
;
$command
.=
"
--account=
$account
"
if
$account
;
$command
.=
"
-H
"
if
$hold
;
if
(
$mail_options
)
{
$command
.=
"
--mail-type=FAIL
"
if
$mail_options
=~
/a/
;
$command
.=
"
--mail-type=BEGIN
"
if
$mail_options
=~
/b/
;
$command
.=
"
--mail-type=END
"
if
$mail_options
=~
/e/
;
}
$command
.=
"
--mail-user=
$mail_user_list
"
if
$mail_user_list
;
$command
.=
"
-J
$job_name
"
if
$job_name
;
$command
.=
"
--nice=
$priority
"
if
$priority
;
$command
.=
"
-p
$partition
"
if
$partition
;
$command
.=
"
$script
"
if
$script
;
print
"
$command
\n
";
exit
;
# Execute the command and capture its stdout, stderr, and exit status. Note
# that if interactive mode was requested, the standard output and standard
# error are _not_ captured.
if
(
$interactive
)
{
my
$ret
=
system
(
$command
);
exit
(
$ret
>>
8
);
}
else
{
# Capture stderr from the command to the stdout stream.
$command
.=
'
2>&1
';
# Execute the command and capture the combined stdout and stderr.
my
@command_output
=
`
$command
2>&1
`;
# Save the command exit status.
my
$command_exit_status
=
$CHILD_ERROR
;
# If available, extract the job ID from the command output and print
# it to stdout, as done in the PBS version of qsub.
if
(
$command_exit_status
==
0
)
{
my
@spcommand_output
=
split
("
",
$command_output
[
$#command_output
]);
$job_id
=
$spcommand_output
[
$#spcommand_output
];
print
"
$job_id
\n
";
}
else
{
print
("
There was an error running the SLURM sbatch command.
\n
"
.
"
The command was:
\n
"
.
"
'
$command
'
\n
"
.
"
and the output was:
\n
"
.
"
'
@command_output
'
\n
");
}
# If block is true wait for the job to finish
my
(
$resp
,
$count
);
my
$slurm
=
Slurm::
new
();
if
(
(
lc
(
$block
)
eq
"
true
"
)
and
(
$command_exit_status
==
0
)
)
{
sleep
2
;
my
(
$job
)
=
$slurm
->
load_job
(
$job_id
);
$resp
=
$$job
{'
job_array
'}[
0
]
->
{
job_state
};
while
(
$resp
<
JOB_COMPLETE
)
{
$job
=
$slurm
->
load_job
(
$job_id
);
$resp
=
$$job
{'
job_array
'}[
0
]
->
{
job_state
};
sleep
1
;
}
}
# Exit with the command return code.
exit
(
$command_exit_status
>>
8
);
}
sub
_check_script
{
my
(
$script
)
=
@_
;
open
my
$file
,
'
<
',
$script
;
my
$first_line
=
<
$file
>
;
close
$file
;
return
(
$first
=~
/\#!/
);
}
sub
parse_resource_list
{
my
(
$rl
)
=
@_
;
my
%opt
=
('
accelerator
'
=>
"",
'
arch
'
=>
"",
'
block
'
=>
"",
'
cput
'
=>
"",
'
file
'
=>
"",
'
host
'
=>
"",
'
mem
'
=>
"",
'
mpiprocs
'
=>
"",
'
ncpus
'
=>
"",
'
nice
'
=>
"",
'
nodes
'
=>
"",
'
naccelerators
'
=>
"",
'
opsys
'
=>
"",
'
other
'
=>
"",
'
pcput
'
=>
"",
'
pmem
'
=>
"",
'
proc
'
=>
'',
'
pvmem
'
=>
"",
'
select
'
=>
"",
'
software
'
=>
"",
'
vmem
'
=>
"",
'
walltime
'
=>
"",
# Cray-specific resources
'
mppwidth
'
=>
"",
'
mppdepth
'
=>
"",
'
mppnppn
'
=>
"",
'
mppmem
'
=>
"",
'
mppnodes
'
=>
""
);
my
@keys
=
keys
(
%opt
);
# The select option uses a ":" separator rather than ","
# This wrapper currently does not support multiple select options
# Protect the colons used to separate elements in walltime=hh:mm:ss.
# Convert to NNhNNmNNs format.
$rl
=~
s/walltime=(\d{1,2}):(\d{2}):(\d{2})/walltime=$1h$2m$3s/
;
$rl
=~
s/:/,/g
;
foreach
my
$key
(
@keys
)
{
#print "$rl\n";
(
$opt
{
$key
})
=
$rl
=~
m/$key=([\w:\+=+]+)/
;
}
# If needed, un-protect the walltime string.
if
(
$opt
{
walltime
})
{
$opt
{
walltime
}
=~
s/(\d{1,2})h(\d{2})m(\d{2})s/$1:$2:$3/
;
# Convert to minutes for SLURM.
$opt
{
walltime
}
=
get_minutes
(
$opt
{
walltime
});
}
if
(
$opt
{
accelerator
}
&&
$opt
{
accelerator
}
=~
/^[Tt]/
&&
!
$opt
{
naccelerators
})
{
$opt
{
naccelerators
}
=
1
;
}
if
(
$opt
{
cput
})
{
$opt
{
cput
}
=
get_minutes
(
$opt
{
cput
});
}
if
(
$opt
{
mpiprocs
}
&&
(
!
$opt
{
mppnppn
}
||
(
$opt
{
mpiprocs
}
>
$opt
{
mppnppn
})))
{
$opt
{
mppnppn
}
=
$opt
{
mpiprocs
};
}
if
(
$opt
{
mppmem
})
{
$opt
{
mem
}
=
convert_mb_format
(
$opt
{
mppmem
});
}
elsif
(
$opt
{
mem
})
{
$opt
{
mem
}
=
convert_mb_format
(
$opt
{
mem
});
}
if
(
$opt
{
file
})
{
$opt
{
file
}
=
convert_mb_format
(
$opt
{
file
});
}
return
\
%opt
;
}
sub
parse_node_opts
{
my
(
$node_string
)
=
@_
;
my
%opt
=
('
node_cnt
'
=>
0
,
'
hostlist
'
=>
"",
'
task_cnt
'
=>
0
);
while
(
$node_string
=~
/ppn=(\d+)/g
)
{
$opt
{
task_cnt
}
+=
$
1
;
}
my
$hl
=
Slurm::Hostlist::
create
("");
my
@parts
=
split
(
/\+/
,
$node_string
);
foreach
my
$part
(
@parts
)
{
my
@sub_parts
=
split
(
/:/
,
$part
);
foreach
my
$sub_part
(
@sub_parts
)
{
if
(
$sub_part
=~
/ppn=(\d+)/
)
{
next
;
}
elsif
(
$sub_part
=~
/^(\d+)/
)
{
$opt
{
node_cnt
}
+=
$
1
;
}
else
{
if
(
!
Slurm::Hostlist::
push
(
$hl
,
$sub_part
))
{
print
"
problem pushing host
$sub_part
onto hostlist
\n
";
}
}
}
}
$opt
{
hostlist
}
=
Slurm::Hostlist::
ranged_string
(
$hl
);
my
$hl_cnt
=
Slurm::Hostlist::
count
(
$hl
);
$opt
{
node_cnt
}
=
$hl_cnt
if
$hl_cnt
>
$opt
{
node_cnt
};
return
\
%opt
;
}
sub
get_minutes
{
my
(
$duration
)
=
@_
;
$duration
=
0
unless
$duration
;
my
$minutes
=
0
;
# Convert [[HH:]MM:]SS to duration in minutes
if
(
$duration
=~
/^(?:(\d+):)?(\d*):(\d+)$/
)
{
my
(
$hh
,
$mm
,
$ss
)
=
(
$
1
||
0
,
$
2
||
0
,
$
3
);
$minutes
+=
1
if
$ss
>
0
;
$minutes
+=
$mm
;
$minutes
+=
$hh
*
60
;
}
elsif
(
$duration
=~
/^(\d+)$/
)
{
# Convert number in minutes to seconds
my
$mod
=
$duration
%
60
;
$minutes
=
int
(
$duration
/
60
);
$minutes
++
if
$mod
;
}
else
{
# Unsupported format
die
("
Invalid time limit specified (
$duration
)
\n
");
}
return
$minutes
;
}
sub
convert_mb_format
{
my
(
$value
)
=
@_
;
my
(
$amount
,
$suffix
)
=
$value
=~
/(\d+)($|[KMGT])/i
;
return
if
!
$amount
;
$suffix
=
lc
(
$suffix
);
if
(
!
$suffix
)
{
$amount
/=
1048576
;
}
elsif
(
$suffix
eq
"
k
")
{
$amount
/=
1024
;
}
elsif
(
$suffix
eq
"
m
")
{
#do nothing this is what we want.
}
elsif
(
$suffix
eq
"
g
")
{
$amount
*=
1024
;
}
elsif
(
$suffix
eq
"
t
")
{
$amount
*=
1048576
;
}
else
{
print
"
don't know what to do with suffix
$suffix
\n
";
return
;
}
$amount
.=
"
M
";
return
$amount
;
}
##############################################################################
__END__
=head1 NAME
B<bsub> - submit a batch job in a familiar OpenLava format
=head1 SYNOPSIS
bsub [-a start_time]
[-A account]
[-e err_path]
[-I]
[-l resource_list]
[-m mail_options] [-M user_list]
[-N job_name]
[-o out_path]
[-p priority]
[-q Queue name]
[-v variable_list]
[-V]
[-W additional_attributes]
[-h]
[script]
=head1 DESCRIPTION
The B<bsub> submits batch jobs. It is aimed to be feature-compatible with OpenLavas' bsub.
=head1 OPTIONS
=over 4
=item B<-a>
Earliest start time of job. Format: [HH:MM][MM/DD/YY]
=item B<-A account>
Specify the account to which the job should be charged.
=item B<-e err_path>
Specify a new path to receive the standard error output for the job.
=item B<-I>
Interactive execution.
=item B<-J job_array>
Job array index values. The -J and -t options are equivalent.
=item B<-l resource_list>
Specify an additional list of resources to request for the job.
=item B<-m mail_options>
Specify a list of events on which email is to be generated.
=item B<-M user_list>
Specify a list of email addresses to receive messages on specified events.
=item B<-N job_name>
Specify a name for the job.
=item B<-o out_path>
Specify the path to a file to hold the standard output from the job.
=item B<-p priority>
Specify the priority under which the job should run.
=item B<-p priority>
Specify the priority under which the job should run.
=item B<-t job_array>
Job array index values. The -J and -t options are equivalent.
=item B<-v> [variable_list]
Export only the specified environment variables. This option can also be used
with the -V option to add newly defined environment variables to the existing
environment. The variable_list is a comma delimited list of existing environment
variable names and/or newly defined environment variables using a name=value
format.
=item B<-V>
The -V option to exports the current environment, which is the default mode of
options unless the -v option is used.
=item B<-?> | B<--help>
brief help message
=item B<--man>
full documentation
=back
=cut
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment