add flex-grid folder for flexlm license manager accounting
This commit is contained in:
parent
d26631afd2
commit
81897cf285
1
flex-grid/cache
Symbolic link
1
flex-grid/cache
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/rscratch/minos19/flex_grid_cache
|
33
flex-grid/config/abaqus_licenses.conf
Normal file
33
flex-grid/config/abaqus_licenses.conf
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<qlicserverConfig>
|
||||||
|
<parameters type="overwrite">
|
||||||
|
<param name="lmutil">/opt/SGE/flex-grid/scripts/abaqus_lmutil</param>
|
||||||
|
<!-- <param name="LM_LICENSE_FILE">27000@abaqus-lizenz.rz.ruhr-uni-bochum.de</param> -->
|
||||||
|
<param name="LM_LICENSE_FILE">27000@vmrz0300.vm.ruhr-uni-bochum.de</param>
|
||||||
|
<param name="dir">/opt/SGE/flex-grid/cache</param>
|
||||||
|
<param name="output">qlicserver_abaqus.xml</param>
|
||||||
|
</parameters>
|
||||||
|
<!--
|
||||||
|
| Map resource names (complexes) to values (features)
|
||||||
|
| served by the license manager(s).
|
||||||
|
| Resources without a "served" attribute are considered internal
|
||||||
|
| Resources with type "track" are reported but not managed
|
||||||
|
| The urgency is how much extra weight to give to particular resources.
|
||||||
|
| If a 'slot' is weighted with 1000, we can give an extra 10% to
|
||||||
|
| a few resources. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| The resource 'limit' specifies an upper limit to prevent applications
|
||||||
|
| from flooding the cluster and/or prevent jobs from consuming all the
|
||||||
|
| available licenses. A negative limit is subtracted from the total
|
||||||
|
| to obtain the limit. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| Derived resources are combined from sub-elements and inherit the
|
||||||
|
| limits from their sub-elements.
|
||||||
|
|
|
||||||
|
| Resources that are not served and not derived are internal resources
|
||||||
|
+ -->
|
||||||
|
<resources type="overwrite">
|
||||||
|
<resource name="abaqus" served="abaqus" limit="30" type="job"/>
|
||||||
|
<resource name="cae" served="cae" limit="2" type="job"/>
|
||||||
|
</resources>
|
||||||
|
</qlicserverConfig>
|
31
flex-grid/config/comsol_licenses.conf
Normal file
31
flex-grid/config/comsol_licenses.conf
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<qlicserverConfig>
|
||||||
|
<parameters type="overwrite">
|
||||||
|
<param name="lmutil">/opt/matlab/etc/glnxa64/lmutil</param>
|
||||||
|
<param name="LM_LICENSE_FILE">/opt/SGE/flex-grid/licenses/comsol.lic</param>
|
||||||
|
<param name="dir">/opt/SGE/flex-grid/cache</param>
|
||||||
|
<param name="output">qlicserver_comsol.xml</param>
|
||||||
|
</parameters>
|
||||||
|
<!--
|
||||||
|
| Map resource names (complexes) to values (features)
|
||||||
|
| served by the license manager(s).
|
||||||
|
| Resources without a "served" attribute are considered internal
|
||||||
|
| Resources with type "track" are reported but not managed
|
||||||
|
| The urgency is how much extra weight to give to particular resources.
|
||||||
|
| If a 'slot' is weighted with 1000, we can give an extra 10% to
|
||||||
|
| a few resources. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| The resource 'limit' specifies an upper limit to prevent applications
|
||||||
|
| from flooding the cluster and/or prevent jobs from consuming all the
|
||||||
|
| available licenses. A negative limit is subtracted from the total
|
||||||
|
| to obtain the limit. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| Derived resources are combined from sub-elements and inherit the
|
||||||
|
| limits from their sub-elements.
|
||||||
|
|
|
||||||
|
| Resources that are not served and not derived are internal resources
|
||||||
|
+ -->
|
||||||
|
<resources type="overwrite">
|
||||||
|
<resource name="comsol" served="COMSOL" type="job"/>
|
||||||
|
</resources>
|
||||||
|
</qlicserverConfig>
|
36
flex-grid/config/local_licenses.conf
Normal file
36
flex-grid/config/local_licenses.conf
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<qlicserverConfig>
|
||||||
|
<parameters type="overwrite">
|
||||||
|
<param name="lmutil">/opt/matlab/etc/glnxa64/lmutil</param>
|
||||||
|
<param name="LM_LICENSE_FILE">/opt/SGE/flex-grid/licenses/multiphysics.lic</param>
|
||||||
|
<param name="dir">/opt/SGE/flex-grid/cache</param>
|
||||||
|
<param name="output">qlicserver_local.xml</param>
|
||||||
|
<param name="qhost">qhost.xml</param>
|
||||||
|
<param name="qstat">qstat.xml</param>
|
||||||
|
</parameters>
|
||||||
|
<!--
|
||||||
|
| Map resource names (complexes) to values (features)
|
||||||
|
| served by the license manager(s).
|
||||||
|
| Resources without a "served" attribute are considered internal
|
||||||
|
| Resources with type "track" are reported but not managed
|
||||||
|
| The urgency is how much extra weight to give to particular resources.
|
||||||
|
| If a 'slot' is weighted with 1000, we can give an extra 10% to
|
||||||
|
| a few resources. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| The resource 'limit' specifies an upper limit to prevent applications
|
||||||
|
| from flooding the cluster and/or prevent jobs from consuming all the
|
||||||
|
| available licenses. A negative limit is subtracted from the total
|
||||||
|
| to obtain the limit. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| Derived resources are combined from sub-elements and inherit the
|
||||||
|
| limits from their sub-elements.
|
||||||
|
|
|
||||||
|
| Resources that are not served and not derived are internal resources
|
||||||
|
resource name="hyper" served="GridWorks" type="job"
|
||||||
|
<resource name="matlab" served="MATLAB" type="job" limit="-2"/>
|
||||||
|
<resource name="signal_toolbox" served="Signal_Toolbox" type="job" limit="-2"/>
|
||||||
|
+ -->
|
||||||
|
<resources type="overwrite">
|
||||||
|
<resource name="femlab" served="COMSOL" type="track"/>
|
||||||
|
</resources>
|
||||||
|
</qlicserverConfig>
|
32
flex-grid/config/matlab_licenses.conf
Normal file
32
flex-grid/config/matlab_licenses.conf
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<qlicserverConfig>
|
||||||
|
<parameters type="overwrite">
|
||||||
|
<param name="lmutil">/opt/matlab/etc/glnxa64/lmutil</param>
|
||||||
|
<param name="LM_LICENSE_FILE">/opt/SGE/flex-grid/licenses/matlab.lic</param>
|
||||||
|
<param name="dir">/opt/SGE/flex-grid/cache</param>
|
||||||
|
<param name="output">qlicserver_matlab.xml</param>
|
||||||
|
</parameters>
|
||||||
|
<!--
|
||||||
|
| Map resource names (complexes) to values (features)
|
||||||
|
| served by the license manager(s).
|
||||||
|
| Resources without a "served" attribute are considered internal
|
||||||
|
| Resources with type "track" are reported but not managed
|
||||||
|
| The urgency is how much extra weight to give to particular resources.
|
||||||
|
| If a 'slot' is weighted with 1000, we can give an extra 10% to
|
||||||
|
| a few resources. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| The resource 'limit' specifies an upper limit to prevent applications
|
||||||
|
| from flooding the cluster and/or prevent jobs from consuming all the
|
||||||
|
| available licenses. A negative limit is subtracted from the total
|
||||||
|
| to obtain the limit. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| Derived resources are combined from sub-elements and inherit the
|
||||||
|
| limits from their sub-elements.
|
||||||
|
|
|
||||||
|
| Resources that are not served and not derived are internal resources
|
||||||
|
+ -->
|
||||||
|
<resources type="overwrite">
|
||||||
|
<resource name="matlab" served="MATLAB" type="job" limit="100"/>
|
||||||
|
<resource name="mcc" served="Compiler" type="job" limit="100"/>
|
||||||
|
</resources>
|
||||||
|
</qlicserverConfig>
|
31
flex-grid/config/trelis_licenses.conf
Normal file
31
flex-grid/config/trelis_licenses.conf
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<qlicserverConfig>
|
||||||
|
<parameters type="overwrite">
|
||||||
|
<param name="lmutil">/opt/matlab/etc/glnxa64/lmutil</param>
|
||||||
|
<param name="LM_LICENSE_FILE">/opt/SGE/flex-grid/licenses/matlab.lic</param>
|
||||||
|
<param name="dir">/opt/SGE/flex-grid/cache</param>
|
||||||
|
<param name="output">qlicserver_trelis.xml</param>
|
||||||
|
</parameters>
|
||||||
|
<!--
|
||||||
|
| Map resource names (complexes) to values (features)
|
||||||
|
| served by the license manager(s).
|
||||||
|
| Resources without a "served" attribute are considered internal
|
||||||
|
| Resources with type "track" are reported but not managed
|
||||||
|
| The urgency is how much extra weight to give to particular resources.
|
||||||
|
| If a 'slot' is weighted with 1000, we can give an extra 10% to
|
||||||
|
| a few resources. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| The resource 'limit' specifies an upper limit to prevent applications
|
||||||
|
| from flooding the cluster and/or prevent jobs from consuming all the
|
||||||
|
| available licenses. A negative limit is subtracted from the total
|
||||||
|
| to obtain the limit. [Format: INTEGER]
|
||||||
|
|
|
||||||
|
| Derived resources are combined from sub-elements and inherit the
|
||||||
|
| limits from their sub-elements.
|
||||||
|
|
|
||||||
|
| Resources that are not served and not derived are internal resources
|
||||||
|
+ -->
|
||||||
|
<resources type="overwrite">
|
||||||
|
<resource name="trelis" served="TRELIS" type="job"/>
|
||||||
|
</resources>
|
||||||
|
</qlicserverConfig>
|
1
flex-grid/licenses/comsol.lic
Symbolic link
1
flex-grid/licenses/comsol.lic
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/opt/comsol53a/multiphysics/license/license.dat
|
2
flex-grid/licenses/hyperworks.lic
Executable file
2
flex-grid/licenses/hyperworks.lic
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
SERVER kamikaze 80b660b0 7788
|
||||||
|
USE_SERVER
|
2
flex-grid/licenses/ifort.lic
Executable file
2
flex-grid/licenses/ifort.lic
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
SERVER kamikaze 80b660b0 28518
|
||||||
|
USE_SERVER
|
1
flex-grid/licenses/matlab.lic
Symbolic link
1
flex-grid/licenses/matlab.lic
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/opt/matlab/licenses/01network.lic
|
2
flex-grid/licenses/multiphysics.lic
Executable file
2
flex-grid/licenses/multiphysics.lic
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
SERVER phaidra.geophysik.ruhr-uni-bochum.de 00163ef90680 1718
|
||||||
|
USE_SERVER
|
221
flex-grid/scripts/GridEngine-git-config
Executable file
221
flex-grid/scripts/GridEngine-git-config
Executable file
@ -0,0 +1,221 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Snapshot of the current GridEngine configuration using git for the
|
||||||
|
# backend storage and tracking mechanism.
|
||||||
|
#
|
||||||
|
# Should normally be called via a cronjob.
|
||||||
|
#
|
||||||
|
# Following Edward Dale's idea:
|
||||||
|
# http://scompt.com/blog/archives/2009/10/13/versioned-grid-engine-configuration
|
||||||
|
# but using git for the backend
|
||||||
|
#
|
||||||
|
# initialize:
|
||||||
|
#
|
||||||
|
# git --git-dir=$GIT_DIR init --bare --shared=world
|
||||||
|
#
|
||||||
|
# Note: we use Perl for inplace editing since some versions of sed have
|
||||||
|
# problems with this task.
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
# CUSTOMIZE THESE SETTINGS TO MATCH YOUR REQUIREMENTS:
|
||||||
|
|
||||||
|
SGE_ROOT=/opt/grid
|
||||||
|
SGE_CELL=default
|
||||||
|
GIT_DIR=/data/cfd/share/git-repo/gridengine-config.git
|
||||||
|
|
||||||
|
#
|
||||||
|
# END OF CUSTOMIZE SETTINGS
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
Script=${0##.*/}
|
||||||
|
saveScript="$SGE_ROOT/util/upgrade_modules/save_sge_config.sh"
|
||||||
|
export SGE_ROOT SGE_CELL GIT_DIR
|
||||||
|
|
||||||
|
for i in git perl
|
||||||
|
do
|
||||||
|
type $i >/dev/null 2>&1 || {
|
||||||
|
echo "Error: $Script - no '$i' found"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
usage() {
|
||||||
|
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
|
||||||
|
cat<<USAGE
|
||||||
|
|
||||||
|
usage: ${0##*/} [OPTION | GIT_COMMAND]
|
||||||
|
options:
|
||||||
|
-help display this usage
|
||||||
|
init initialize git repo in $GIT_DIR
|
||||||
|
|
||||||
|
pass-through git commands:
|
||||||
|
log ls-files
|
||||||
|
show whatchanged
|
||||||
|
|
||||||
|
Snapshot of the current GridEngine configuration using git for the
|
||||||
|
backend storage and tracking mechanism.
|
||||||
|
|
||||||
|
* git repository stored here:
|
||||||
|
$GIT_DIR
|
||||||
|
|
||||||
|
copyright (c) 2009-10 <Mark.Olesen@faurecia.com>
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# parse options
|
||||||
|
while [ "$#" -gt 0 ]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
( help | -h | -help )
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
( init )
|
||||||
|
shift
|
||||||
|
if [ -d "$GIT_DIR" ]
|
||||||
|
then
|
||||||
|
echo "Error: $Script - $GIT_DIR already exists"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
git --git-dir=$GIT_DIR init --bare --shared=world $@
|
||||||
|
rc=$?
|
||||||
|
|
||||||
|
# add a description for gitweb
|
||||||
|
i="$GIT_DIR/description"
|
||||||
|
if [ -f "$i" -a -w "$i" ]
|
||||||
|
then
|
||||||
|
echo "snapshot of the current GridEngine configuration" > $i
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
exit $rc
|
||||||
|
;;
|
||||||
|
( log | ls-files | show | whatchanged )
|
||||||
|
git --git-dir=$GIT_DIR $@
|
||||||
|
exit $?
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
usage "unknown option/argument: '$*'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[ -d "$GIT_DIR" ] || {
|
||||||
|
echo "git repo: $GIT_DIR does not exist"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i="$SGE_ROOT/$SGE_CELL/common/settings.sh"
|
||||||
|
if [ -f "$i" -a -r "$i" ]
|
||||||
|
then
|
||||||
|
. "$i"
|
||||||
|
else
|
||||||
|
echo "cannot read $i"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -f "$saveScript" -a -r "$saveScript" ] || {
|
||||||
|
echo "cannot read $i"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a fresh empty directory
|
||||||
|
# cannot use --tmpdir on older systems
|
||||||
|
tmpDir=$(mktemp -d "/tmp/sgeSaveConfig.XXXXXXXXXX")
|
||||||
|
trap "rm -rf $tmpDir 2>/dev/null; exit 0" EXIT TERM INT
|
||||||
|
|
||||||
|
[ -d "$tmpDir" ] || {
|
||||||
|
echo "Error: temp dir '$tmpDir' does not exist"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$saveScript $tmpDir
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# cleanup
|
||||||
|
#
|
||||||
|
(
|
||||||
|
cd $tmpDir || exit 1
|
||||||
|
|
||||||
|
# all operations are now in the current directory
|
||||||
|
GIT_WORK_TREE=.
|
||||||
|
export GIT_WORK_TREE
|
||||||
|
|
||||||
|
# minor error checking that the save script worked
|
||||||
|
if [ -f backup_date -a -r backup_date ]
|
||||||
|
then
|
||||||
|
msg=$(cat backup_date)
|
||||||
|
else
|
||||||
|
echo "cannot read backup_date - $saveScript might have failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# ignore accounting (too big)
|
||||||
|
rm -f cell/accounting
|
||||||
|
|
||||||
|
# ignore current users
|
||||||
|
rm -f users/*
|
||||||
|
|
||||||
|
# ignore current load_values for exec hosts
|
||||||
|
perl -i -ne '/^load_values/ or print' execution/*
|
||||||
|
|
||||||
|
# assign (consumable) complex_values to zero - otherwise we indirectly
|
||||||
|
# track the external license usage when qlicserver is being used
|
||||||
|
# also sort the complexes to avoid spurious changes
|
||||||
|
perl -i -p -e 'if (/^complex_values/) { chomp; ' \
|
||||||
|
-e 's/=\d+/=0/g; s/^(complex\S+\s+)//; ' \
|
||||||
|
-e '$_ = $1 . join("," => sort split /,/) . "\n" }' \
|
||||||
|
execution/global
|
||||||
|
|
||||||
|
#
|
||||||
|
# determine if the configuration changed
|
||||||
|
#
|
||||||
|
# this is fairly roundabout until we find a better way
|
||||||
|
needsCommit=false
|
||||||
|
|
||||||
|
if [ -n "$(git ls-files -d)" ] # files deleted?
|
||||||
|
then
|
||||||
|
needsCommit=true
|
||||||
|
elif [ -n "$(git ls-files -o)" ] # files added?
|
||||||
|
then
|
||||||
|
needsCommit=true
|
||||||
|
else
|
||||||
|
# files modified?
|
||||||
|
# do it the long way to ensure we also get staged modifications
|
||||||
|
set -- $(git status | perl -ne 's/^#\s+modified:// and print')
|
||||||
|
|
||||||
|
# changes in backup_date, jobseqnum etc alone are not enough
|
||||||
|
# to warrant a commit
|
||||||
|
while [ "$#" -ge 1 ]
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
( arseqnum | backup_date | jobseqnum )
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
needsCommit=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$needsCommit" = true ]
|
||||||
|
then
|
||||||
|
# register all new files
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# commit everything
|
||||||
|
git commit -a -m "$msg"
|
||||||
|
else
|
||||||
|
echo "no changes to be committed $msg"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
#------------------------------------------------------------------------------
|
5
flex-grid/scripts/abaqus_lmutil
Executable file
5
flex-grid/scripts/abaqus_lmutil
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# $Id: abaqus_lmutil 180 2010-09-17 15:46:41Z kasper $
|
||||||
|
|
||||||
|
/opt/abaqus/Commands/abaqus licensing lmstat -a -f abaqus -S ABAQUSLM
|
||||||
|
/opt/abaqus/Commands/abaqus licensing lmstat -a -f cae -S ABAQUSLM
|
124
flex-grid/scripts/filter-accounting
Executable file
124
flex-grid/scripts/filter-accounting
Executable file
@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
use strict;
|
||||||
|
use Getopt::Std qw( getopts );
|
||||||
|
use Time::Local qw( timelocal );
|
||||||
|
|
||||||
|
my ($releaseDate) = qw( 2009-10-02 );
|
||||||
|
|
||||||
|
( my $Script = $0 ) =~ s{^.*/}{};
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
sub usage {
|
||||||
|
$! = 0; # clean exit
|
||||||
|
warn "@_\n" if @_;
|
||||||
|
die <<"USAGE";
|
||||||
|
usage:
|
||||||
|
$Script [OPTION] file1 [ .. fileN ]
|
||||||
|
|
||||||
|
with options:
|
||||||
|
-b YYYY[-MM[-DD]]
|
||||||
|
begin date for accounting (job end_time > DATE 2 A.M.)
|
||||||
|
-e YYYY[-MM[-DD]]
|
||||||
|
end date for accounting (job end_time <= DATE 2 A.M.)
|
||||||
|
-h usage
|
||||||
|
|
||||||
|
Extract portions of the GridEngine accounting(5) file according to the
|
||||||
|
job end_time. For example,
|
||||||
|
$Script -b 2008-01-01 -e 2009 ...
|
||||||
|
extracts the accounting for jobs that finished running in 2008.
|
||||||
|
|
||||||
|
The value of 2 A.M. avoids problems that daylight savings time might
|
||||||
|
otherwise cause.
|
||||||
|
|
||||||
|
version ($releaseDate)
|
||||||
|
copyright (c) 2009 <Mark.Olesen\@faurecia.com>
|
||||||
|
|
||||||
|
Licensed and distributed under the Creative Commons
|
||||||
|
Attribution-NonCommercial-ShareAlike 3.0 License.
|
||||||
|
http://creativecommons.org/licenses/by-nc-sa/3.0
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
my %opt;
|
||||||
|
getopts( "hb:e:", \%opt ) or usage();
|
||||||
|
usage() if $opt{h};
|
||||||
|
|
||||||
|
@ARGV or usage();
|
||||||
|
|
||||||
|
for (@ARGV) {
|
||||||
|
-f $_ or die "no file '$_'\n";
|
||||||
|
|
||||||
|
## handle compressed files transparently
|
||||||
|
if (/\.bz2$/) {
|
||||||
|
$_ = qq{bzip2 -dc "$_"|};
|
||||||
|
}
|
||||||
|
elsif (/\.gz$/) {
|
||||||
|
$_ = qq{gzip -dc "$_"|};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (qw( b e )) {
|
||||||
|
if ( $opt{$_} ||= 0 ) {
|
||||||
|
my ( $yy, $mm, $dd );
|
||||||
|
|
||||||
|
if ( $opt{$_} =~ /^(\d{2,4})-(\d{1,2})-(\d{1,2})$/ ) {
|
||||||
|
## YYYY-MM-DD
|
||||||
|
( $yy, $mm, $dd ) = ( $1, $2, $3 );
|
||||||
|
}
|
||||||
|
elsif ( $opt{$_} =~ /^(\d{2,4})-(\d{1,2})$/ ) {
|
||||||
|
## YYYY-MM
|
||||||
|
( $yy, $mm ) = ( $1, $2 );
|
||||||
|
}
|
||||||
|
elsif ( $opt{$_} =~ /^(\d{2,4})$/ ) {
|
||||||
|
## YYYY
|
||||||
|
($yy) = ($1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
usage("invalid date format: '$opt{$_}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
# treat missing month/day as '1'
|
||||||
|
$mm ||= 1;
|
||||||
|
$dd ||= 1;
|
||||||
|
|
||||||
|
# convert from YYYY-MM-DD to epoch,
|
||||||
|
# start at 2am - avoid problems with daylight savings time
|
||||||
|
$opt{$_} = timelocal( 0, 0, 2, $dd, $mm - 1, $yy ); # month (0..11)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$opt{b} or $opt{e} or usage("must specify at least one of -b or -e");
|
||||||
|
|
||||||
|
if ( $opt{e} and $opt{b} >= $opt{e} ) {
|
||||||
|
usage("-b DATE must less than -e DATE");
|
||||||
|
}
|
||||||
|
|
||||||
|
my $fileCount;
|
||||||
|
while (<>) {
|
||||||
|
if (/^\s*#/) {
|
||||||
|
## pass-thru comments, but only for the first file
|
||||||
|
print unless $fileCount;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my ($endtime) = ( split /:/ )[10];
|
||||||
|
|
||||||
|
# only allow things that ran (endtime non-zero)
|
||||||
|
# and that are within the filter limits
|
||||||
|
if ( $endtime
|
||||||
|
and ( $opt{b} ? ( $endtime > $opt{b} ) : 'okay' )
|
||||||
|
and ( $opt{e} ? ( $endtime <= $opt{e} ) : 'okay' ) )
|
||||||
|
{
|
||||||
|
print;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue {
|
||||||
|
$fileCount++ if eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
FORMAT - see accounting(5)
|
||||||
|
08 submission_time
|
||||||
|
09 start_time
|
||||||
|
10 end_time
|
517
flex-grid/scripts/qlic
Executable file
517
flex-grid/scripts/qlic
Executable file
@ -0,0 +1,517 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
use strict;
|
||||||
|
use Getopt::Std qw( getopts );
|
||||||
|
use POSIX qw( );
|
||||||
|
|
||||||
|
( my $Script = $0 ) =~ s{^.*/}{};
|
||||||
|
|
||||||
|
my $time = time;
|
||||||
|
my $date = POSIX::strftime( "%F %T", localtime $time );
|
||||||
|
|
||||||
|
$ENV{SGE_ROOT} or die "Error $Script: \$SGE_ROOT is not set\n";
|
||||||
|
$ENV{SGE_CELL} ||= "default"; # sge_cell
|
||||||
|
|
||||||
|
my ($siteLocation) = join "/" => ( $ENV{SGE_ROOT}, $ENV{SGE_CELL}, "site" );
|
||||||
|
|
||||||
|
my $config = {
|
||||||
|
-site => ( $siteLocation || '' ),
|
||||||
|
-cache => ( $siteLocation || '' ) . "/cache/" . "qlicserver.xml",
|
||||||
|
-limits => ( $siteLocation || '' ) . "/" . "qlicserver.limits",
|
||||||
|
};
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# utils
|
||||||
|
|
||||||
|
#
|
||||||
|
# calculate age from an epoch value
|
||||||
|
#
|
||||||
|
sub age {
|
||||||
|
my ( $a, $b ) = @_;
|
||||||
|
my $diff = ( $a - $b );
|
||||||
|
|
||||||
|
my $sign = '';
|
||||||
|
if ( $diff < 0 ) { # handle negatives
|
||||||
|
$sign = '-';
|
||||||
|
$diff = abs($diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf "$sign%d:%02d:%02d", # format into hh:mm:ss
|
||||||
|
( int $diff / 3_600 ), # hh
|
||||||
|
( ( int $diff / 60 ) % 60 ), # mm
|
||||||
|
( $diff % 60 ); # ss
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# change hash references to a comma-delimited string of key=value entries
|
||||||
|
#
|
||||||
|
sub hashRefToString {
|
||||||
|
map {
|
||||||
|
my $ref = $_;
|
||||||
|
ref $ref ? map { "$_=$ref->{$_}" } sort keys %$ref : ()
|
||||||
|
} @_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# extract attrib="value" ... attrib="value"
|
||||||
|
#
|
||||||
|
sub parseXMLattrib {
|
||||||
|
my $str = shift || '';
|
||||||
|
my %attr;
|
||||||
|
|
||||||
|
while ($str =~ s{^\s*(\w+)=\"([^\"]*)\"}{}s
|
||||||
|
or $str =~ s{^\s*(\w+)=\'([^\']*)\'}{}s )
|
||||||
|
{
|
||||||
|
$attr{$1} = $2;
|
||||||
|
}
|
||||||
|
|
||||||
|
%attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# processing of qlicserver.xml output
|
||||||
|
#
|
||||||
|
package qlicCache;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $caller = shift;
|
||||||
|
my $file = shift;
|
||||||
|
|
||||||
|
my $self = bless {
|
||||||
|
( map { $_ => {} } qw( -rc ) ),
|
||||||
|
( map { $_ => '' } qw( -date -host -age ) )
|
||||||
|
}, $caller;
|
||||||
|
|
||||||
|
-f $file or return $self;
|
||||||
|
|
||||||
|
local $_ = do { local ( @ARGV, $/ ) = $file; <>; };
|
||||||
|
|
||||||
|
# strip out all xml comments
|
||||||
|
s{<!--.*?-->\s*}{}sg;
|
||||||
|
|
||||||
|
# get the header section
|
||||||
|
s{^(.+?)</query>}{}s or return;
|
||||||
|
my $header = $1;
|
||||||
|
|
||||||
|
for ($header) {
|
||||||
|
if (m{<host (?:\s+([^<>]*))? > \s*(.+?)\s* </host>}sx) {
|
||||||
|
my ( $attr, $content ) = ( $1, $2 );
|
||||||
|
$self->{-host} = $content;
|
||||||
|
}
|
||||||
|
if (m{<time (?:\s+([^<>]*))? > \s*(.+?)\s* </time>}sx) {
|
||||||
|
my ( $attr, $content ) = ( $1, $2 );
|
||||||
|
my %attr = main::parseXMLattrib($attr);
|
||||||
|
|
||||||
|
$self->{-age} = main::age( $time, $attr{epoch} ) if $attr{epoch};
|
||||||
|
$self->{-date} = $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# only retain the <resources> contents
|
||||||
|
s{^.*?<resources>}{}s and s{</resources>.*$}{}s or return;
|
||||||
|
|
||||||
|
## process <resource .../>
|
||||||
|
while (s{<resource (?:\s+([^/<>]*))? />}{}sx) {
|
||||||
|
my ($attr) = ($1);
|
||||||
|
my %attr = main::parseXMLattrib($attr);
|
||||||
|
my $name = delete $attr{name};
|
||||||
|
|
||||||
|
if ( defined $name ) {
|
||||||
|
for ( keys %attr ) {
|
||||||
|
$self->{-rc}{$name}{$_} = $attr{$_} || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## process <resource ...> CONTENT </resource>
|
||||||
|
while (s{<resource (?:\s+([^<>]*))? > \s* (.*?) \s* </resource>}{}sx) {
|
||||||
|
my ( $attr, $content ) = ( $1, $2 );
|
||||||
|
my %attr = main::parseXMLattrib($attr);
|
||||||
|
my $name = delete $attr{name};
|
||||||
|
|
||||||
|
if ( defined $name ) {
|
||||||
|
for ( keys %attr ) {
|
||||||
|
$self->{-rc}{$name}{$_} = $attr{$_} || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## process <user ...> COUNT </user>
|
||||||
|
while ( $content =~ s{<user (?:\s+([^<>]*))? >\s*(\d+)\s*</user>}{}sx )
|
||||||
|
{
|
||||||
|
my ( $attr, $count ) = ( $1, $2 );
|
||||||
|
my %attr = main::parseXMLattrib($attr);
|
||||||
|
my $user = delete $attr{name};
|
||||||
|
my $host = delete $attr{host};
|
||||||
|
|
||||||
|
if ( defined $user ) {
|
||||||
|
if ( defined $host ) {
|
||||||
|
$self->{-rc}{$name}{-where}{"$user\@$host"} = $count;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
## tag waiting with '[]'
|
||||||
|
$self->{-rc}{$name}{-where}{$user} = "[$count]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub query {
|
||||||
|
my $self = shift;
|
||||||
|
%{ $self->{-rc} };
|
||||||
|
}
|
||||||
|
|
||||||
|
sub dump {
|
||||||
|
use Data::Dumper;
|
||||||
|
print Dumper( $_[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub available {
|
||||||
|
my $self = shift;
|
||||||
|
sort keys %{ $self->{-rc} };
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# processing of qlicserver.limits FILE or DIRECTORY
|
||||||
|
#
|
||||||
|
package qlicLimits;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $caller = shift;
|
||||||
|
my $diskValues = shift;
|
||||||
|
|
||||||
|
my $self = bless {}, $caller;
|
||||||
|
|
||||||
|
my $fileString;
|
||||||
|
if ( defined $diskValues and -f $diskValues ) {
|
||||||
|
$fileString = do {
|
||||||
|
local ( *FILE, $/ );
|
||||||
|
|
||||||
|
if ( open FILE, $diskValues ) {
|
||||||
|
<FILE>;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
undef;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
elsif ( defined $diskValues and -d $diskValues ) {
|
||||||
|
local *DIR;
|
||||||
|
my $dir = $diskValues;
|
||||||
|
if ( opendir DIR, $dir ) {
|
||||||
|
my @files = grep { -f "$dir/$_" and -r _ } readdir DIR;
|
||||||
|
for my $name (@files) {
|
||||||
|
my $limit;
|
||||||
|
|
||||||
|
# use the last value
|
||||||
|
if ( open FILE, "$dir/$name" ) {
|
||||||
|
$limit = ( map { /^\s*(-?\d+)\s*$/ } <FILE> )[-1];
|
||||||
|
}
|
||||||
|
defined $limit or $limit = "NONE";
|
||||||
|
$self->{$name} = $limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($fileString) {
|
||||||
|
defined or next;
|
||||||
|
|
||||||
|
# strip out all comments
|
||||||
|
s{<!--.*?-->\s*}{}sg;
|
||||||
|
|
||||||
|
## process <resource .../> and <resource ...></resource>
|
||||||
|
while (s{<resource (?:\s+([^/<>]*))? />}{}sx
|
||||||
|
or s{<resource (?:\s+([^/<>]*))? >\s*</resource>}{}sx )
|
||||||
|
{
|
||||||
|
my %attr = main::parseXMLattrib($1);
|
||||||
|
my $name = delete $attr{name};
|
||||||
|
my $limit = delete $attr{limit};
|
||||||
|
if ( defined $name and defined $limit ) {
|
||||||
|
$self->{$name} = $limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub change {
|
||||||
|
my $caller = shift;
|
||||||
|
my $diskValues = shift;
|
||||||
|
my @args = @_;
|
||||||
|
|
||||||
|
@args or return;
|
||||||
|
|
||||||
|
my ( %pending, %adjusted );
|
||||||
|
|
||||||
|
for (@args) {
|
||||||
|
s{,}{ }g; # comma -> space-delimited
|
||||||
|
|
||||||
|
my %h = map { /^(.+?)=(.*)$/ } split;
|
||||||
|
for ( keys %h ) {
|
||||||
|
defined $h{$_} and length $h{$_} or $h{$_} = "NONE";
|
||||||
|
$pending{$_} = $h{$_};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keys %pending or return;
|
||||||
|
|
||||||
|
my $user = getpwuid $<;
|
||||||
|
if ( defined $diskValues and -d $diskValues ) {
|
||||||
|
local *DIR;
|
||||||
|
my $dir = $diskValues;
|
||||||
|
if ( opendir DIR, $dir ) {
|
||||||
|
my @files = grep { -f "$dir/$_" and -w _ } readdir DIR;
|
||||||
|
|
||||||
|
for my $name (@files) {
|
||||||
|
if ( exists $pending{$name} ) {
|
||||||
|
local *FILE;
|
||||||
|
if ( open FILE, ">", "$dir/$name" ) {
|
||||||
|
print FILE "# adjusted by $user $date\n",
|
||||||
|
"$pending{$name}\n";
|
||||||
|
$adjusted{$name} = delete $pending{$name};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( [ "adjusted" => \%adjusted ], [ "not adjusted" => \%pending ], ) {
|
||||||
|
my ( $label, $href ) = @$_;
|
||||||
|
keys %$href or next;
|
||||||
|
print "$label: ",
|
||||||
|
join( "," => map { qq{$_=$href->{$_}} } sort keys %$href ), "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub output {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my @list = map { qq{$_=$self->{$_}} } sort keys %$self;
|
||||||
|
|
||||||
|
print "limits: ";
|
||||||
|
if (@list) {
|
||||||
|
print join( "," => @list ), "\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "NONE\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# main
|
||||||
|
#
|
||||||
|
|
||||||
|
package main;
|
||||||
|
import qlicCache;
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
sub usage {
|
||||||
|
$! = 0; # clean exit
|
||||||
|
warn "@_\n" if @_;
|
||||||
|
die <<"USAGE";
|
||||||
|
usage:
|
||||||
|
$Script [OPTION]
|
||||||
|
$Script [OPTION] resource=limit .. resource=limit
|
||||||
|
|
||||||
|
with options:
|
||||||
|
-c FILE alternative location for the license cache
|
||||||
|
-C FILE alternative location for the license limit
|
||||||
|
-d dump cache file as raw xml
|
||||||
|
-D dump license cache in perl format
|
||||||
|
-f display free licenses only
|
||||||
|
-l list license limit
|
||||||
|
-q display free licenses via qhost query
|
||||||
|
-u license usage via 'lacct'
|
||||||
|
-U license usage per user via 'lacct -u'
|
||||||
|
-w show who/where ('[]' indicates waiting jobs)
|
||||||
|
-h this help
|
||||||
|
|
||||||
|
* extract / display information for the GridEngine license cache
|
||||||
|
$config->{-cache}
|
||||||
|
|
||||||
|
* adjust / display information for the license limits
|
||||||
|
$config->{-limits}
|
||||||
|
|
||||||
|
copyright (c) 2003-10 <Mark.Olesen\@faurecia.com>
|
||||||
|
|
||||||
|
Licensed and distributed under the Creative Commons
|
||||||
|
Attribution-NonCommercial-ShareAlike 3.0 License.
|
||||||
|
http://creativecommons.org/licenses/by-nc-sa/3.0
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
my %opt;
|
||||||
|
getopts( 'hc:C:DdflqUuw', \%opt ) or usage();
|
||||||
|
$opt{h} and usage();
|
||||||
|
|
||||||
|
if ( $opt{U} ) {
|
||||||
|
## user-based usage from accounting
|
||||||
|
my @query = ( "lacct", "-u" );
|
||||||
|
exec @query;
|
||||||
|
exit 2;
|
||||||
|
}
|
||||||
|
elsif ( $opt{u} ) {
|
||||||
|
## usage from accounting
|
||||||
|
my @query = ( "lacct", $opt{w} ? "-w" : () );
|
||||||
|
exec @query;
|
||||||
|
exit 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $opt{d} ) {
|
||||||
|
my $file = $opt{c} || $config->{-cache};
|
||||||
|
|
||||||
|
if ( not -f $file and $file !~ m{/} ) {
|
||||||
|
$file = "$config->{-site}/$file";
|
||||||
|
}
|
||||||
|
|
||||||
|
-f $file or exit 1;
|
||||||
|
|
||||||
|
local $_ = do { local ( @ARGV, $/ ) = $file; <>; };
|
||||||
|
|
||||||
|
# do a basic check for well-formed xml
|
||||||
|
# this might not be the case if there is a race condition
|
||||||
|
# and the file has not been fully written
|
||||||
|
|
||||||
|
# check for '<?xml version="1.0"?><someTag ...' at the start
|
||||||
|
# and '</someTag>' at the end
|
||||||
|
my ($tag) = m{^<\?xml (?:\s+[^<>]*?)? \?>\s*\<(\w+)}sx;
|
||||||
|
unless ( $tag and m{</\Q$tag\E>\s*$} ) {
|
||||||
|
sleep 2; ## wait and try again
|
||||||
|
$_ = do { local ( @ARGV, $/ ) = $file; <>; };
|
||||||
|
}
|
||||||
|
|
||||||
|
$_ ||= ''; ## avoid uninitialized
|
||||||
|
|
||||||
|
print;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $opt{q} ) {
|
||||||
|
my %free =
|
||||||
|
map { /^\s+gc:(\S+?)=(\d\S*)\s*$/ }
|
||||||
|
grep { /^global/ ... /^\S/ } qx{qhost -F};
|
||||||
|
|
||||||
|
$_ += 0 for values %free;
|
||||||
|
|
||||||
|
for ( sort keys %free ) {
|
||||||
|
my $intval = $free{$_} + 0; # normalize as integers
|
||||||
|
print "$_=$intval\n";
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $opt{l} ) {
|
||||||
|
qlicLimits->new( $opt{C} || $config->{-limits} )->output();
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@ARGV) {
|
||||||
|
qlicLimits->change( $opt{C} || $config->{-limits}, @ARGV );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $info = qlicCache->new( $opt{c} || $config->{-cache} );
|
||||||
|
$info->dump() if $opt{D};
|
||||||
|
|
||||||
|
my %resources = $info->query();
|
||||||
|
|
||||||
|
#
|
||||||
|
# display free licenses
|
||||||
|
#
|
||||||
|
if ( $opt{f} ) {
|
||||||
|
for my $resource ( sort keys %resources ) {
|
||||||
|
my $count = $resources{$resource} || {};
|
||||||
|
my $free = $count->{free} || 0;
|
||||||
|
print "$resource=$free\n" if $free;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# display who/where
|
||||||
|
#
|
||||||
|
if ( $opt{w} ) {
|
||||||
|
my ($len) = sort { $b <=> $a } map { length } keys %resources;
|
||||||
|
$len += 2;
|
||||||
|
|
||||||
|
my $fmt = "%-${len}s";
|
||||||
|
my $indent = sprintf "\n$fmt", '';
|
||||||
|
|
||||||
|
for my $resource ( sort keys %resources ) {
|
||||||
|
my $count = $resources{$resource} || {};
|
||||||
|
my @list = hashRefToString( $count->{-where} );
|
||||||
|
if (@list) {
|
||||||
|
printf $fmt, $resource;
|
||||||
|
print join( $indent => @list ), "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# define table output format
|
||||||
|
#
|
||||||
|
my @outputList;
|
||||||
|
|
||||||
|
format =
|
||||||
|
# name total limit extern intern wait free
|
||||||
|
@<<<<<<<<<<< @>>>>> @>>>>> @>>>>> @>>>>> @>>>> @>>>>
|
||||||
|
@outputList
|
||||||
|
.
|
||||||
|
|
||||||
|
#
|
||||||
|
# display table header
|
||||||
|
# --------------------
|
||||||
|
{
|
||||||
|
my @info = qw( host age );
|
||||||
|
my ($len) = sort { $b <=> $a } map { length } @info;
|
||||||
|
|
||||||
|
print map {
|
||||||
|
my $k = sprintf "%-${len}s", $_;
|
||||||
|
my $v = $info->{"-$_"};
|
||||||
|
$v ? "$k = $v\n" : ();
|
||||||
|
} @info;
|
||||||
|
|
||||||
|
print "\n";
|
||||||
|
|
||||||
|
@outputList = qw( resource total limit extern intern wait free );
|
||||||
|
|
||||||
|
write;
|
||||||
|
s/./-/g for @outputList;
|
||||||
|
write;
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# display table body
|
||||||
|
# ------------------
|
||||||
|
for my $resource ( sort keys %resources ) {
|
||||||
|
my $count = $resources{$resource} || {};
|
||||||
|
@outputList =
|
||||||
|
( $resource, @{$count}{qw( total limit extern intern waiting free )} );
|
||||||
|
|
||||||
|
my $type = $resources{$resource}{type} || 0;
|
||||||
|
|
||||||
|
# no total?
|
||||||
|
$_ ||= "?" for $outputList[1];
|
||||||
|
|
||||||
|
if ( $type eq "intern" ) {
|
||||||
|
$_ = "*" for $outputList[3];
|
||||||
|
}
|
||||||
|
elsif ( $type eq "track" ) {
|
||||||
|
$_ = "*" for $outputList[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
# easy to read representation for zero
|
||||||
|
for (@outputList) {
|
||||||
|
defined $_ or $_ = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
write;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
2327
flex-grid/site/qlicserver
Executable file
2327
flex-grid/site/qlicserver
Executable file
File diff suppressed because it is too large
Load Diff
325
flex-grid/site/qloadsensor
Executable file
325
flex-grid/site/qloadsensor
Executable file
@ -0,0 +1,325 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# $Id: qloadsensor 180 2010-09-17 15:46:41Z kasper $
|
||||||
|
#
|
||||||
|
# qloadsensor:
|
||||||
|
# load sensor for particular file systems and floating licenses
|
||||||
|
#
|
||||||
|
# NB:
|
||||||
|
# 1) add the new complexes (via qconf -mc) for the following:
|
||||||
|
# * complex configurations managed in the shell script
|
||||||
|
# eg, 'perl -x qloadsensor'
|
||||||
|
# * complex consumables managed global
|
||||||
|
# eg, 'qlicserver -c'
|
||||||
|
# 2) initialize the global complex consumables to be managed
|
||||||
|
# eg, 'qlicserver -C'
|
||||||
|
#
|
||||||
|
# copyright (c) 2003-10 <Mark.Olesen@faurecia.com>
|
||||||
|
#
|
||||||
|
# Licensed and distributed under the Creative Commons
|
||||||
|
# Attribution-NonCommercial-ShareAlike 3.0 License.
|
||||||
|
# http://creativecommons.org/licenses/by-nc-sa/3.0
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# impose default GridEngine environment + ascertain the binary architecture
|
||||||
|
#
|
||||||
|
# you likely don't need to adjust these values, since the loadsensor is called
|
||||||
|
# from sge_execd, which in turn is started from /etc/init.d/n1ge and
|
||||||
|
# these variables should be correctly exported there
|
||||||
|
#
|
||||||
|
[ -d "$SGE_ROOT" ] || { echo "Error: SGE_ROOT=$SGE_ROOT not found"; exit 1; }
|
||||||
|
: ${SGE_CELL:=default}
|
||||||
|
: ${SGE_ARCH:=`$SGE_ROOT/util/arch`}
|
||||||
|
|
||||||
|
export SGE_ROOT SGE_CELL SGE_ARCH
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# this script should run as the 'admin_user' registered in 'bootstrap'
|
||||||
|
#
|
||||||
|
if [ "$UID" -eq 0 ]
|
||||||
|
then
|
||||||
|
admin_user=$(sed -ne 's/^admin_user *//p' $SGE_ROOT/$SGE_CELL/common/bootstrap)
|
||||||
|
: ${admin_user:=root}
|
||||||
|
if [ $admin_user != root -a $(echo $admin_user | tr "A-Z" "a-z") != none ]
|
||||||
|
then
|
||||||
|
exec $SGE_ROOT/utilbin/$SGE_ARCH/adminrun $admin_user $0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# <settings>
|
||||||
|
# ========================================================================
|
||||||
|
# now that we are the admin_user, we can source our standard settings
|
||||||
|
# - customize *all* settings there (eg, license server settings)
|
||||||
|
# - ENSURE THAT '$SGE_site' IS DEFINED !!!
|
||||||
|
#
|
||||||
|
for i in $SGE_ROOT/$SGE_CELL/site/environ; do [ -f $i ] && . $i; done
|
||||||
|
|
||||||
|
# define (unique) cluster name if not already defined
|
||||||
|
if [ -z "$SGE_CLUSTER_NAME" -a -r "$SGE_ROOT/$SGE_CELL/common/cluster_name" ]
|
||||||
|
then
|
||||||
|
SGE_CLUSTER_NAME=$(cat $SGE_ROOT/$SGE_CELL/common/cluster_name 2>/dev/null)
|
||||||
|
fi
|
||||||
|
: ${SGE_CLUSTER_NAME:=default}
|
||||||
|
export SGE_CLUSTER_NAME
|
||||||
|
|
||||||
|
SGE_site="$SGE_ROOT/flex-grid/site"
|
||||||
|
|
||||||
|
#
|
||||||
|
# ========================================================================
|
||||||
|
# </settings>
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
###############################################################################
|
||||||
|
# CUSTOMIZE THESE SETTINGS - iff. required
|
||||||
|
|
||||||
|
qlicserver="$SGE_site/qlicserver config=$SGE_site/../config/local_licenses.conf dir=$SGE_ROOT/flex-grid/cache output=$SGE_ROOT/flex-grid/cache/qlicserver.xml qhost=qhost.xml qstat=qstat.xml"
|
||||||
|
diskmon="$SGE_site/diskmon.pl"
|
||||||
|
|
||||||
|
# END OF CUSTOMIZE SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# the real (not compiled in) architecture
|
||||||
|
#
|
||||||
|
os_arch=`$SGE_ROOT/util/arch`
|
||||||
|
SGE_utilbin=$SGE_ROOT/utilbin/$os_arch
|
||||||
|
|
||||||
|
#
|
||||||
|
# set some constants
|
||||||
|
#
|
||||||
|
HOST=$($SGE_utilbin/gethostname -aname)
|
||||||
|
UQHOST=$(echo $HOST | cut -f1 -d.)
|
||||||
|
SGE_qmaster=unknown; export SGE_qmaster
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# act_qmaster
|
||||||
|
#
|
||||||
|
# extract the unqualified host name from the "act_qmaster" file
|
||||||
|
# return this value or 'unknown' on failure
|
||||||
|
#
|
||||||
|
act_qmaster()
|
||||||
|
{
|
||||||
|
tmp=$(cat $SGE_common/act_qmaster 2>/dev/null)
|
||||||
|
echo ${tmp:-unknown}
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# df_info
|
||||||
|
#
|
||||||
|
# echo the $1_{total,used,free} space on filesystem $2
|
||||||
|
#
|
||||||
|
# gridengine uses the suffixes
|
||||||
|
# 'k' => blocksize 1000
|
||||||
|
# 'K' => blocksize 1024
|
||||||
|
#
|
||||||
|
# return 0 if 'df' fails
|
||||||
|
df_info()
|
||||||
|
{
|
||||||
|
# 1:tag 2:mount 3:filesys 4:total 5:Used 6:Avail 7:Used% 8:Mount
|
||||||
|
[ -d "$2" ] && set -- $1 $2 $( df -k -P $2 2>/dev/null | tail -1 )
|
||||||
|
|
||||||
|
#!# we could add the following check:
|
||||||
|
#!# [ "$2" != "$8" ] && set -- $1 $2; # mount point mismatch?
|
||||||
|
|
||||||
|
[ "$#" -ge 6 ] || set -- $1 $2 filesystem 0 0 0
|
||||||
|
|
||||||
|
echo "$UQHOST:$1_total:$4K"
|
||||||
|
echo "$UQHOST:$1_used:$5K"
|
||||||
|
|
||||||
|
#if [ -w "$2" ]
|
||||||
|
#then
|
||||||
|
echo "$UQHOST:$1_free:$6K"
|
||||||
|
#else
|
||||||
|
# echo "$UQHOST:$1_free:0"
|
||||||
|
#fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# invariant values
|
||||||
|
if [ -e "/proc/cpuinfo" ]
|
||||||
|
then
|
||||||
|
# mips=$(awk '{if (/mips/) printf "%.0f\n", $NF}' /proc/cpuinfo | tail -1)
|
||||||
|
mips=$(awk 'BEGIN {mips=0} /mips/ {if ($NF > mips) mips=$NF }; END {print mips}' /proc/cpuinfo)
|
||||||
|
else
|
||||||
|
mips=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset os_name
|
||||||
|
# extract lsb_release
|
||||||
|
if [ -e "/usr/bin/lsb_release" ]
|
||||||
|
then
|
||||||
|
os_name=$(/usr/bin/lsb_release -ircs | xargs echo | sed 's/ /_/g')
|
||||||
|
else
|
||||||
|
os_name='unkown'
|
||||||
|
fi
|
||||||
|
: ${os_name:=NONE}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# host_info
|
||||||
|
#
|
||||||
|
# report host specific information about filesystems, logins,
|
||||||
|
# special hardware extensions, etc.
|
||||||
|
#
|
||||||
|
host_info()
|
||||||
|
{
|
||||||
|
echo "$UQHOST:arch:$os_arch"
|
||||||
|
echo "$UQHOST:os:$os_name"
|
||||||
|
# df_info tmp /tmp
|
||||||
|
df_info scratch /scratch
|
||||||
|
echo "$UQHOST:mips:$mips"
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# iidle_info()
|
||||||
|
# report a machine's idle time
|
||||||
|
#
|
||||||
|
# parse the contents from /proc/interrupts, which looks like the following:
|
||||||
|
#
|
||||||
|
# CPU0
|
||||||
|
# 0: 23024789 XT-PIC timer
|
||||||
|
# 1: 13 XT-PIC keyboard
|
||||||
|
# 2: 0 XT-PIC cascade
|
||||||
|
# 5: 0 XT-PIC usb-uhci
|
||||||
|
# 8: 2 XT-PIC rtc
|
||||||
|
# 9: 0 XT-PIC acpi
|
||||||
|
# 10: 0 XT-PIC ehci-hcd, usb-uhci
|
||||||
|
# 11: 16687253 XT-PIC eth0, usb-uhci, Intel 82801DB-ICH4, nvidia
|
||||||
|
# 12: 20 XT-PIC PS/2 Mouse
|
||||||
|
# 14: 77178 XT-PIC ide0
|
||||||
|
# 15: 2 XT-PIC ide1
|
||||||
|
# NMI: 0
|
||||||
|
# LOC: 0
|
||||||
|
# ERR: 0
|
||||||
|
# MIS: 0
|
||||||
|
#
|
||||||
|
# or,
|
||||||
|
#
|
||||||
|
# CPU0 CPU1
|
||||||
|
# 0: 12820049 12818168 IO-APIC-edge timer
|
||||||
|
# 1: 42889 43309 IO-APIC-edge keyboard
|
||||||
|
# 2: 0 0 XT-PIC cascade
|
||||||
|
# 8: 2 0 IO-APIC-edge rtc
|
||||||
|
# 9: 0 0 IO-APIC-edge acpi
|
||||||
|
# 12: 287235 296531 IO-APIC-edge PS/2 Mouse
|
||||||
|
# 14: 47423 40923 IO-APIC-edge ide0
|
||||||
|
# 15: 2 3 IO-APIC-edge ide1
|
||||||
|
# 16: 7733868 7737081 IO-APIC-level nvidia
|
||||||
|
# 17: 159 156 IO-APIC-level Intel ICH 82801AA
|
||||||
|
# 19: 2155710 2159943 IO-APIC-level e100, usb-uhci
|
||||||
|
# NMI: 0 0
|
||||||
|
# LOC: 25641034 25641033
|
||||||
|
# ERR: 0
|
||||||
|
# MIS: 0
|
||||||
|
#
|
||||||
|
# Thus, we need the [-1, 1..$ncpu] fields for the following sources:
|
||||||
|
# keyboard, Mouse, serial
|
||||||
|
#
|
||||||
|
# NB: adding 'usb-uhci' gives problems, since this is sometimes
|
||||||
|
# attached to the ethernet card
|
||||||
|
#
|
||||||
|
# set the variable 'iidle' to the idle time (seconds) since the last call
|
||||||
|
#
|
||||||
|
last="0 -1";
|
||||||
|
iidle_info()
|
||||||
|
{
|
||||||
|
set -- $(
|
||||||
|
perl -e '
|
||||||
|
my @last = @ARGV;
|
||||||
|
@ARGV = "/proc/interrupts";
|
||||||
|
$_ = <>;
|
||||||
|
|
||||||
|
my $ncpu = s/\s*CPU\d+//g || 0;
|
||||||
|
my ( $iidle, $int, $now ) = ( 0, 0, time );
|
||||||
|
|
||||||
|
$int += $_
|
||||||
|
for
|
||||||
|
map { /\s+(keyboard|Mouse|serial)$/ ? (split)[ 1 .. $ncpu ] : (); }
|
||||||
|
<>;
|
||||||
|
|
||||||
|
if ( $int == $last[-1] ) { # no interactivity since last round
|
||||||
|
$iidle = ( $now - $last[0] );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
@last = ( $now, $int );
|
||||||
|
}
|
||||||
|
|
||||||
|
print "$iidle @last\n";
|
||||||
|
' $last
|
||||||
|
);
|
||||||
|
|
||||||
|
echo "$UQHOST:iidle:$1";
|
||||||
|
|
||||||
|
shift; last="$@"; # save for later
|
||||||
|
}
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# The execd running on the qmaster queries the license server
|
||||||
|
# The contents of 'act_qmaster' should suffice to migrate the load sensor
|
||||||
|
# for a controlled migration.
|
||||||
|
#
|
||||||
|
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
read input || exit 1 # wait for input
|
||||||
|
[ "$input" = quit ] && exit 0
|
||||||
|
|
||||||
|
echo begin # begin load report
|
||||||
|
host_info # host information
|
||||||
|
iidle_info # machine's idle time
|
||||||
|
echo end # end load report
|
||||||
|
|
||||||
|
# let the license query run between load reports
|
||||||
|
# SGE_qmaster=`act_qmaster` # refresh the name of the qmaster
|
||||||
|
# if [ "$HOST" = "$SGE_qmaster" ]
|
||||||
|
if [ "$HOST" = "minos19" ]
|
||||||
|
then
|
||||||
|
# $qlicserver 2>> qloadsensor.err
|
||||||
|
$SGE_ROOT/flex-grid/site/qlicserver config=$SGE_ROOT/flex-grid/config/local_licenses.conf output=$SGE_ROOT/flex-grid/cache/qlicserver_local.xml
|
||||||
|
$SGE_ROOT/flex-grid/site/qlicserver config=$SGE_ROOT/flex-grid/config/abaqus_licenses.conf timeout=60 output=$SGE_ROOT/flex-grid/cache/qlicserver_abaqus.xml
|
||||||
|
# $SGE_ROOT/flex-grid/site/qlicserver config=/opt/SGE/flex-grid/config/trelis_licenses.conf timeout=60 output=$SGE_ROOT/flex-grid/cache/qlicserver_trelis.xml
|
||||||
|
$SGE_ROOT/flex-grid/site/qlicserver config=/opt/SGE/flex-grid/config/comsol_licenses.conf timeout=60 output=$SGE_ROOT/flex-grid/cache/qlicserver_comsol.xml
|
||||||
|
$SGE_ROOT/flex-grid/site/qlicserver config=$SGE_ROOT/flex-grid/config/matlab_licenses.conf timeout=60 output=$SGE_ROOT/flex-grid/cache/qlicserver_matlab.xml
|
||||||
|
lockfile $SGE_ROOT/flex-grid/cache/qlicserver.xml.lock
|
||||||
|
# (sed '/<\/resources>/,$ d' $SGE_ROOT/flex-grid/cache/qlicserver_abaqus.xml ; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_trelis.xml | grep -v qlicserver | grep -v resources ; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_local.xml | grep -v qlicserver | grep -v resources ; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_matlab.xml;) > $SGE_ROOT/flex-grid/cache/qlicserver.xml
|
||||||
|
# (sed '/<\/resources>/,$ d' $SGE_ROOT/flex-grid/cache/qlicserver_abaqus.xml ; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_local.xml | grep -v qlicserver | grep -v resources ; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_matlab.xml;) > $SGE_ROOT/flex-grid/cache/qlicserver.xml
|
||||||
|
(sed '/<\/resources>/,$ d' $SGE_ROOT/flex-grid/cache/qlicserver_abaqus.xml ; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_local.xml | grep -v qlicserver | grep -v resources; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_comsol.xml | grep -v qlicserver | grep -v resources ; sed '1,/<resources>/d' $SGE_ROOT/flex-grid/cache/qlicserver_matlab.xml;) > $SGE_ROOT/flex-grid/cache/qlicserver.xml
|
||||||
|
rm -f $SGE_ROOT/flex-grid/cache/qlicserver.xml.lock
|
||||||
|
# $diskmon -m 2>> qloadsensor.err
|
||||||
|
# force rescheduling of express jobs
|
||||||
|
# $SGE_site/qxprs >/dev/null 2>&1
|
||||||
|
# else
|
||||||
|
# $diskmon 2>> qloadsensor.err
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit 0 # we never get here, but just in case
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# feed via 'perl -x' to extract the 'host' complex configuration
|
||||||
|
|
||||||
|
#!/usr/bin/perl -w
|
||||||
|
print <DATA>
|
||||||
|
__DATA__
|
||||||
|
#
|
||||||
|
# host complex configuration
|
||||||
|
#
|
||||||
|
#name shortcut type relop requestable consumable default urgency
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
tmp_total tmpt MEMORY <= YES NO 0 0
|
||||||
|
tmp_used tmpu MEMORY >= NO NO 0 0
|
||||||
|
tmp_free tmpf MEMORY <= YES NO 0 0
|
||||||
|
iidle iidle INT <= YES NO 0 0
|
||||||
|
mips mips INT <= YES NO 0 0
|
||||||
|
os os RESTRING == YES NO NONE 0
|
||||||
|
abaqus abaqus DOUBLE <= YES YES 0 0
|
||||||
|
cae cae DOUBLE <= YES YES 0 0
|
||||||
|
comsol comsol DOUBLE <= YES YES 0 0
|
||||||
|
hyper hyper DOUBLE <= YES YES 0 0
|
||||||
|
ifort ifort DOUBLE <= YES YES 0 0
|
||||||
|
matlab matlab DOUBLE <= YES YES 0 0
|
||||||
|
mcc mcc DOUBLE <= YES YES 0 0
|
||||||
|
multiphysics multiphysics DOUBLE <= YES YES 0 0
|
||||||
|
trelis trelis DOUBLE <= YES YES 0 0
|
||||||
|
scratch_free scratch_free MEMORY <= YES YES 0 0
|
||||||
|
scratch_total scratch_total MEMORY <= YES NO 0 0
|
||||||
|
scratch_used scratch_used MEMORY >= NO NO 0 0
|
||||||
|
# -----------------------------------------------------------------------------
|
Loading…
Reference in New Issue
Block a user