NAME

Slurm::Sacctmgr - Perl wrapper to sacctmgr command

SYNOPSIS

  use Slurm::Sacctmgr;

  my $sacctmgr = Slurm::Sacctmgr->new( sacctmgr=>'path to sacctmgr command');

  my $sacctmgr->dryrun(1);
  my $sacctmgr->verbose(1);

  my $results;

  #This one won't run in dryrun mode
  $results = $sacctmgr->run_generic_sacctmgr_cmd('create', 
                'cluster', 'mycluster');
  if ( $results && ref($results) eq 'ARRAY' )
  {     print "Results of create cluster are: ",
                (join "\n", @$results), "\n\n";
  } else
  {     print STDERR "Error running create cluster: $results\n";
  }

  #This one will run in dryrun mode.  --readonly is silently appended, so
  #is "safe" to run in dryrun mode
  $sacctmgr->run_generic_safe_sacctmgr_cmd('list', 'cluster');
  if ( $results && ref($results) eq 'ARRAY' )
  {     print "Results of list cluster (human readable) are: ",
                (join "\n", @$results), "\n\n";
  } else
  {     print STDERR "Error running list cluster: $results\n";
  }

  #This also runs in dryrun mode.  --readonly, --parsable2, and --noheader
  #are added to the command silently
  $sacctmgr->run_generic_sacctmgr_list_command('list','cluster');
  if ( $results && ref($results) eq 'ARRAY' )
  {     print "Results of list cluster (machine readable) are: ",
                (join "\n", @$results), "\n\n";
  } else
  {     print STDERR "Error running list cluster: $results\n";
  }

  ...

DESCRIPTION

These provide wrappers to the Slurm sacctmgr command. Basically, it allows access to the Slurm sacctmgr command from within Perl. Forks and pipes are used so no new shell is spawned (and shell expansion is not handled) for increased safety. Although there might be advantages to using Slurmdb and accessing the database directly, this wrapper approach has some advantages as well, one of which is that provides greater correlation with existing manual procedures using these commands, thereby easing the automation of existing processes.

The interface to this package is object orientated, mainly to reduce namespace pollution.

CONSTRUCTOR and DATA members

The constructor new takes key => value pairs to set the data members, which are:

sacctmgr:

The path to the Slurm sacctmgr command. Can only be set at time of construction. Normally defaults to just "sacctmgr", i.e. will look for it in your path. Systems staff can set a different default by changing the value of the constant $DEFAULT_SACCTMGR_CMD at the top of this file. It is recommended that they also set $DEFAULT_SACCTMGR_VERSION at the same time if specifying the sacctmgr command of a specific Slurm version.

dryrun:

If this is set, the module works in dryrun mode. See below for details. Default is false.

verbose:

If this is set, the module works in verbose mode. Basically, the various sacctmgr commands will be printed out just before they are executed. Commands which do not actually run due to dryrun mode will not be printed out due to verbose mode, but will get printed out due to being dryrun mode (i.e. they will get printed once, and only once). Default is false.

Accessors exist for all of the above. The sacctmgr field is read-only, and can only be set at time of construction. dryrun and verbose are read-write, and can be set at any time by providing a defined boolean value as an explicit argument to the accessor. Usual perl boolean semantics apply, except that you cannot provide an undef value to the accessor to unset the fields (as that would be interpretted as a read accessor, not a mutator).

The main methods are the methods to actually run sacctmgr commands. These use forking and pipes to avoid invoking an Unix shell for additional safety (i.e., shell expansions will not work). The intent is to be able to programatically issue sacctmgr commands and get the results. The functions take the sacctmgr command, with each word as a separate argument to the function. The actual sacctmgr command should NOT be given, as we will use the one provided to the constructor.

Default value for sacctmgr path and Slurm version

If the user does not set the path to sacctmgr (and perhaps the version of Slurm) when constructing an instance, these will be defaulted. It is recommended that system administrators modify Sacctmgr.pm after installation to set the default path to the appropriate value for the cluster, and to also set the Slurm version. However, if the system administrator did not modify the file, the default default is to use whatever sacctmgr command is found in the caller's path, and the Slurm version will be determined, if needed, by probing the sacctmgr command (which involves an extra fork and exec).

For system administrators looking to default these values, there are several ways to proceed. The method _set_defaults handles setting all default values for the instance (although currently only sacctmgr is defaulted). If sacctmgr is in need of being defaulted, it calls the method default_sacctmgr_path_version which returns the path and possibly version as a list. The default version of default_sacctmgr_path_version simply returns the lexical variables $DEFAULT_SACCTMGR_CMD and $DEFAULT_SACCTMGR_VERSION which are defined at the top of the Sacctmgr.pm file. If not modified, these should be just 'sacctmgr' and undef, respectively, which results in whatever sacctmgr in the invoker's path being executing, and the package not knowing what version of Slurm is being used (which means if the version is needed, the package will attempt to query sacctmgr to discover the version).

In most cases, it is recommended that the system administrator just change the values of the lexical $DEFAULT_SACCTMGR_CMD and $DEFAULT_SACCTMGR_VERSION at the top of the file to the full path to the sacctmgr command and the version of Slurm being used on the cluster. This will avoid issues if there are issues with the caller's path, and prevent extra invocations of sacctmgr to determine the Slurm version.

If the situation is too complicated for the above, the default_sacctmgr_path_version provides a hook wherein the system administrator can use whatever algorithm desired to default these values. E.g., if you have two clusters sharing the same perl library but running different versions of Slurm.

RUN-type commands

The "run" commands are:

$sacctmgr-run_generic_sacctmgr_cmd(@sacctmgr_args)>

This runs sacctmgr with the arguments given in @sacctmgr_args, UNLESS we are in dryrun mode. In dryrun mode, the command is only printed out (with a [DRYRUN] prefix).

$sacctmgr-run_generic_safe_sacctmgr_cmd(@sacctmgr_args)>

This behaves much like run_generic_sacctmgr_cmd, except that it will always run, even in dryrun mode. Also, we prepend the --readonly argument to the argument list. It is intended for commands which do NOT update the database (and we use the --readonly flag to enforce that). Because the command does not update the database, it can safely run in dryrun mode. This is useful for sacctmgr commands that your script runs to gather information.

$sacctmgr-run_generic_sacctmgr_list_command(@sacctmgr_args)>

This behaves much like run_generic_safe_sacctmgr_cmd, except that it also adds the flags -parseable2 and -noheader to the argument list. This is intended to wrap commands to collect information using sacctmgr and present to your script in a machine-usable fashion. Note that you still need to give the full argument list to sacctmgr, i.e. the 'list' or 'show' command is not assumed.

RETURN VALUES AND ERROR HANDLING

For serious (fatal) errors, such as:

in the constructor, when required parameters are missing or illegal parameters given.
in the "run" commands, due to errors duplicating stderr onto stdout or errors forking the sacctmgr command.

For non-fatal errors, the return value will be a non-reference scalar string containing the error text. E.g., if the sacctmgr command returns a non-zero exit code, the "run" methods will return a string starting with "Error code: " followed by the error code and any error message received from sacctmgr.

On success, the return value for the "run" methods will be an array reference, containing the output of the sacctmgr command (each element of the array being one line of output).

DRYRUN MODE

For testing of scripts, it is nice to have a dryrun mode in which the user can see what commands would be executed, but without the commands actually executing. To do this, have a dryrun flag in your code, and set the dryrun data method of your Slurm::Sacctmgr instance. This can be done either at time of construction or afterwards with the dryrun mutator. NOTE: Although standard Perl boolean semantics are honored, you cannot use the dryrun mutator to unset the data method; as

  $sacctmgr->dryrun(undef);

will be considered a request to get the value of dryrun, not to set it to undef (false). Use instead something like:

  $sacctmgr->dryrun(0);

Actually, only commands which modify the database should not run; getting a list of all clusters, etc. is harmless and you normally want those to run (otherwise your code won't get far enough to reach the parts that really need debugging). So we provide a run_generic_sacctmgr_cmd method which honors the dryrun setting, and will only actually execute the command when dryrun is false, as well as run_generic_safe_sacctmgr_cmd, which does NOT honor the dryrun setting, and always runs.

The latter is intended for commands which do not modify the database, and so are safe to run even in a debugging session. To ensure the DB does not get modified, it adds the --readonly flag to sacctmgr.

The run_generic_sacctmgr_list_command is a variant of the run_generic_safe_sacctmgr_cmd, intended for the somewhat common operation of requesting information from sacctmgr. It adds flags to make the output more machine readable.

VERBOSE MODE

If the verbose data method is set, either at construction time or via the verbose mutator afterwards, the sacctmgr commands will be printed out to STDERR before being executed. This is again useful for debugging.

Note: If both verbose and dryrun modes are set, only the "safe" commands are printed out due to the instance being in verbose mode. The "unsafe" commands get intercepted by dryrun mode first, before verbose mode can print them out. But the dryrun mode prints them out anyway, so the result is the command gets printed out exactly once, which is what you probably want anyway.

EXPORT

None. OO interface only.

EXAMPLES

Generally, you will instantiate an instance of of this class and then pass it to one of the Slurm::Sacctmgr::* package class methods to do the actual work. The following little example script will print for each Slurm account the GrpCPUMin limits by cluster/partition, as well as list the users who can access the account:

  #!/usr/bin/perl
  use Slurm::Sacctmgr;
  use Slurm::Sacctmgr::Account;
  use Slurm::Sacctmgr::Association;
  
  #You can specify a full path to sacctmgr below if wanted, defaults to just 'sacctmgr'
  my $sa = Slurm::Sacctmgr->new;

  #Get a list of all accounts sacctmgr knows of
  my $accounts = Slurm::Sacctmgr::Account->sacctmgr_list($sa);

  foreach my $acct (@$accounts)
  {     my $account = $acct->account; #The name of the account
        my ($assoc, $cluster, $partition);
  
        # Get all associations in sacctmgr related to this account.
        # Arguments after the Slurm::Sacctmgr instance are passed to the sacctmgr list assoc command
        my $assocs = Slurm::Sacctmgr::Association->sacctmgr_list($sa, account=>$account);
  
        #Separate the associations with and without user members
        my @acctassocs = grep { ! defined $_->user } @$assocs;
        my @userassocs = grep { defined $_->user } @$assocs;
  
        print "--------------------------------------\n";
        print "Account $account:\n";
  
        #Print GrpCPUMin limits on any associations w/out users
        printf "\t%10s %10s %10s\n", 'Cluster', 'Partition', 'GrpCPUMins' if ( @acctassocs );
        foreach $assoc (@acctassocs)
        {       $cluster = $assoc->cluster || '<any>';
                $partition = $assoc->partition || '<any>';
                my $cpumin = $assoc->grpcpumins || '<unlimited>';
                printf "\t%10s %10s %10s\n", $cluster, $partition, $cpumin;
        }
  
        #List users with access to this Account
        printf "\t%10s %10s %10s\n", 'User', 'Cluster', 'Partition' if ( @userassocs );
        foreach $assoc (@userassocs)
        {       $cluster = $assoc->cluster || '<any>';
                $partition = $assoc->partition || '<any>';
                my $user = $assoc->user || '<any>';
                printf "\t%10s %10s %10s\n", $user, $cluster, $partition;
        }
  }

SEE ALSO

Slurmdb

Slurm::Sacctmgr::Account

Slurm::Sacctmgr::Associaton

Slurm::Sacctmgr::Cluster

Slurm::Sacctmgr::EntityBase

Slurm::Sacctmgr::Event

Slurm::Sacctmgr::Qos

Slurm::Sacctmgr::Transaction

Slurm::Sacctmgr::User

Slurm::Sacctmgr::WCKey

AUTHOR

Tom Payerle, payerle@umd.edu

COPYRIGHT AND LICENSE

Copyright (C) 2014-2016 by the University of Maryland.

This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0

Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.