Hi Loris,

Thank you.

Regards,
Miguel


On 12/05/16 08:03, Loris Bennett wrote:
Hi Miguel,

Miguel Couceiro <couce...@isec.pt> writes:

Hi Loris,

I am interested in the script you mentioned. Could you please post the code?

Best regards,
Miguel
[snip (23 lines)]

We have licenses, such as Intel compiler licenses, which can be used
both interactively outside the queuing system and within Slurm jobs.

We use a script which parses the output of the FlexLM manager and
modifies a reservation in which the licenses are defined.  This is run
as a cron job once a minute.  It's a bit of a kludge and obviously won't
work well if there is a lot of contention for licenses.

I can post the code if anyone is interested.

Cheers,

Loris
It is almost the first thing I wrote in Python, so beware.  Also the
usual caveats apply: use at your own risk, no warranty implied, I'm not
responsible if the script causes your license server to implode, etc.

The code relies on being able to parse the output of the FlexLM license
server.  If you are using something else, you'll have to adapt the
regular expression used appropriately.  The program has an option to
generate a 'Licenses' entry for slurm.conf.  Users then have to specify
both a license and the appropriate reservation, e.g.

#SBATCH --licenses=matlab_MATLAB
#SBATCH --reservation=licenses_matlab

The main things to be configured are the paths to the license manager
and to 'scontrol' as well as the paths to the license files.

One thing is missing:  The script should also update the reservation to
move the end time continuously into the future, such that it never
expires.

Here's the code.  Enjoy.  Improvements/suggestions welcome.

Cheers,

Loris

-------------------------------------------------------------------------------

#!/shared/apps/python/python3.4/bin/python
from subprocess import check_output
import re
import string
import os
import sys
import argparse

parser = argparse.ArgumentParser(description="update licence reservations")
parser.add_argument("-i","--initialise", help="generate line for slurm.conf",
                     action="store_true")
parser.add_argument("-d","--dryrun", help="print action without performing it",
                     action="store_true")
args = parser.parse_args()

total_or_available = 'available'
separator = ':'
if args.initialise:
     total_or_available = 'total'
     separator = '*'

lmstat   = '/local/licenses/matlab/etc/lmstat'
scontrol = '/usr/bin/scontrol'

matlab_license_file = '/local/licenses/matlab/etc/license.dat'
intel_license_file = '/shared/licenses/intel/license_2015-2016.lic'

vendors = {}
vendors['matlab'] = {'prefix':'matlab_',
                      'licence_file': matlab_license_file }
vendors['intel']  = {'prefix':'intel_',
                      'licence_file': intel_license_file}

# Note that licence names may contain hyphens (particularly for Intel products)
re_dict = re.compile(r"""Users\s+of\s+(?P<name>\w+(?:-\w+)*):\s+
                          \(Total\s+of\s+(?P<total>\d+)\s+licenses?\s+issued;\s+
                            
Total\s+of\s+(?P<in_use>\d+)\s+licenses?\s+in\s+use\)""",
                      re.VERBOSE)

re_product = re.compile('User.*', re.MULTILINE)
re_name    = re.compile('Users of (.*?):')
re_error   = re.compile('Error')

for vendor, params in vendors.items():

     cmd = [lmstat, "-a", "-c", params['licence_file']]
     out = check_output(cmd)
     string = str(out,'utf-8')

     licences = []

     for line in re_product.findall(string):

         # Something is wrong with the licence manager or license file
         if re_error.search(line):
             product['name'] = re_name.match(line).group(1)
             product['error'] = True
         # Extract licence data
         else:
             m = re_dict.match(line)
             product = m.groupdict()
             product['error'] = False
         licences.append(product)

     licence_strings_total = []
     licence_strings_available = []

     for licence in licences:

         if not licence['error']:
             slurm_licence_name = params['prefix']
             slurm_licence_name += licence['name']
             licence['available'] = int(licence['total']) - \
                                    int(licence['in_use'])
             licence_strings_total.append(slurm_licence_name + \
                                          separator + \
                                          str(licence['total']))
             if licence['available'] > 0: # Slurm doesn't like 0 licenses
                 licence_strings_available.append(slurm_licence_name + \
                                                  separator + \
                                                  str(licence['available']))

     slurm_licence_total_string = ",".join(licence_strings_total)
     slurm_licence_available_string = ",".join(licence_strings_available)
     scontrol_string = scontrol + \
                       ' update reservationname=licenses_' + vendor + \
                       ' licenses=' + slurm_licence_available_string

     if args.initialise:
         print(slurm_licence_total_string)
         continue

     if args.dryrun:
         print(scontrol_string)
         continue

     # Actually update the reservation
     os.system(scontrol_string)

# Strings used for testing
#
#string = 'Users of MATLAB_Distrib_Comp_Engine:  (Total of 16 licenses issued;  
Total of 0 licenses in use)'
#string = 'Users of Wavelet_Toolbox:  (Error: 2 licenses, unsupported by 
licensed server)'

-------------------------------------------------------------------------------


Reply via email to