source: flex_extract.git/Source/Python/install.py @ 5adaf8a

dev
Last change on this file since 5adaf8a was 5adaf8a, checked in by Anne Tipka <anne.tipka@…>, 22 months ago

bug fix: sysinstalldir assignment

  • Property mode set to 100755
File size: 29.7 KB
RevLine 
[8463d78]1#!/usr/bin/env python3
[64cf353]2# -*- coding: utf-8 -*-
[991df6a]3#*******************************************************************************
4# @Author: Leopold Haimberger (University of Vienna)
5#
6# @Date: November 2015
7#
8# @Change History:
9#
10#    February 2018 - Anne Philipp (University of Vienna):
11#        - applied PEP8 style guide
12#        - added documentation
[ff99eae]13#        - moved install_args_and_control in here
[2fb99de]14#        - splitted code in smaller functions
[5f67883]15#        - delete fortran build files in here instead of compile job script
[6f951ca]16#        - changed static path names to variables from config file
17#        - splitted install function into several smaller pieces
18#        - use of tarfile package in python
[a916e8f]19#    June 2020 - Anne Philipp
20#        - renamed "convert" functions to "fortran" functions
[47be2684]21#        - reconfigured mk_tarball to select *.template files instead
[a916e8f]22#          of *.nl and *.temp
23#        - added check for makefile settings
[75db9b0]24#    August 2020 - Leopold Haimberger
25#        - added a new installation section for system installation (if-else block)
26#        - read new argument from command line
27#        - write .setup.rc for a system installation into Run directory
28#        - copy executables to system path and user files to user path
[991df6a]29#
30# @License:
[026b359]31#    (C) Copyright 2014-2020.
[6f951ca]32#    Anne Philipp, Leopold Haimberger
[991df6a]33#
[44174de]34#    SPDX-License-Identifier: CC-BY-4.0
35#
[6f951ca]36#    This work is licensed under the Creative Commons Attribution 4.0
37#    International License. To view a copy of this license, visit
38#    http://creativecommons.org/licenses/by/4.0/ or send a letter to
39#    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
[991df6a]40#
[6f951ca]41# @Methods:
42#    main
43#    get_install_cmdline_args
44#    install_via_gateway
45#    check_install_conditions
46#    mk_tarball
47#    un_tarball
48#    mk_env_vars
49#    mk_compilejob
50#    mk_job_template
[5f67883]51#    del_fortran_build
52#    mk_fortran_build
[991df6a]53#
54#*******************************************************************************
[6f951ca]55'''This script installs the flex_extract program.
56
57Depending on the selected installation environment (locally or on the
[8209738]58ECMWF server ecgate or cca) the program extracts the command line
[6f951ca]59arguments and the CONTROL file parameter and prepares the corresponding
60environment.
[8209738]61The necessary files are collected in a tar ball and placed
62at the target location. There, is is untared, the environment variables are
63set, and the Fortran code is compiled.
64If the ECMWF environment is selected, a job script is prepared and submitted
65for the remaining configurations after putting the tar ball on the
[6f951ca]66target ECMWF server.
67
68Type: install.py --help
69to get information about command line parameters.
70Read the documentation for usage instructions.
71'''
[991df6a]72
[64cf353]73# ------------------------------------------------------------------------------
74# MODULES
75# ------------------------------------------------------------------------------
[8ce3be6]76from __future__ import print_function
77
[991df6a]78import os
79import sys
[d69b677]80import subprocess
[3946de5]81import tarfile
[47be2684]82import shutil
[ff99eae]83from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
[991df6a]84
85# software specific classes and modules from flex_extract
[2fb99de]86import _config
[ba99230]87from Classes.ControlFile import ControlFile
88from Classes.UioFiles import UioFiles
89from Mods.tools import (make_dir, put_file_to_ecserver, submit_job_to_ecserver,
[47be2684]90                        silent_remove, execute_subprocess, none_or_str,
91                        overwrite_lines_in_file, check_for_string_in_file)
[d69b677]92
[64cf353]93# ------------------------------------------------------------------------------
94# FUNCTIONS
95# ------------------------------------------------------------------------------
[991df6a]96def main():
[274f9ef]97    '''Controls the installation process. Calls the installation function
98    if target is specified.
[991df6a]99
[274f9ef]100    Parameters
101    ----------
[991df6a]102
[274f9ef]103    Return
104    ------
[991df6a]105    '''
106
[8652e7e]107    args = get_install_cmdline_args()
[4971f63]108    c = ControlFile(args.controlfile)
[54a8a01]109    c.assign_args_to_control(args)
[6cda7c1]110    check_install_conditions(c)
[991df6a]111
[47be2684]112    if c.install_target.lower() not in ['local', 'syslocal']: # ecgate or cca
[8ce3be6]113        install_via_gateway(c)
114    else: # local
115        install_local(c)
[991df6a]116
[47be2684]117    print("SUCCESS: INSTALLATION FINISHED!")
118
[54a8a01]119    return
[991df6a]120
[8652e7e]121def get_install_cmdline_args():
[274f9ef]122    '''Decomposes the command line arguments and assigns them to variables.
[8209738]123    Apply default values for arguments not present.
[efdb01a]124
[274f9ef]125    Parameters
126    ----------
[efdb01a]127
[274f9ef]128    Return
129    ------
[6f951ca]130    args : Namespace
[274f9ef]131        Contains the commandline arguments from script/program call.
[efdb01a]132    '''
[8ce3be6]133    parser = ArgumentParser(description='Install flex_extract software '
134                                        'locally or on ECMWF machines',
[efdb01a]135                            formatter_class=ArgumentDefaultsHelpFormatter)
136
[8ce3be6]137    parser.add_argument('--target', dest='install_target',
138                        type=none_or_str, default=None,
[47be2684]139                        help="Valid targets: syslocal | local | ecgate | cca , \
[efdb01a]140                        the latter two are at ECMWF")
[8ce3be6]141    parser.add_argument("--makefile", dest="makefile",
142                        type=none_or_str, default=None,
[8209738]143                        help='Name of makefile for compiling the '
[8ce3be6]144                        'Fortran program')
145    parser.add_argument("--ecuid", dest="ecuid",
146                        type=none_or_str, default=None,
[8209738]147                        help='User id at ECMWF')
[8ce3be6]148    parser.add_argument("--ecgid", dest="ecgid",
149                        type=none_or_str, default=None,
[8209738]150                        help='Group id at ECMWF')
[8ce3be6]151    parser.add_argument("--gateway", dest="gateway",
152                        type=none_or_str, default=None,
[8209738]153                        help='Name of the local gateway server')
[8ce3be6]154    parser.add_argument("--destination", dest="destination",
155                        type=none_or_str, default=None,
[8209738]156                        help='ecaccess association, e.g. '
[8ce3be6]157                        'myUser@genericSftp')
158
159    parser.add_argument("--installdir", dest="installdir",
160                        type=none_or_str, default=None,
[47be2684]161                        help='Root (user) directory of the '
[8209738]162                        'flex_extract installation')
[47be2684]163    parser.add_argument("--sysinstalldir", dest="sysinstalldir",
164                        type=none_or_str, default=None,
165                        help='System installation path; where '
166                        'executables are stored.')
[efdb01a]167
[54a8a01]168    # arguments for job submission to ECMWF, only needed by submit.py
[efdb01a]169    parser.add_argument("--job_template", dest='job_template',
[8ce3be6]170                        type=none_or_str, default="job.template",
[8209738]171                        help='Rudimentary template file to create a batch '
172                        'job template for submission to ECMWF servers')
[efdb01a]173
174    parser.add_argument("--controlfile", dest="controlfile",
[8ce3be6]175                        type=none_or_str, default='CONTROL_EA5',
[8209738]176                        help="A file that contains all CONTROL parameters.")
[efdb01a]177
178    args = parser.parse_args()
179
[54a8a01]180    return args
181
[efdb01a]182
[54a8a01]183def install_via_gateway(c):
[8209738]184    '''Prepare data transfer to remote gateway and submit a job script which will
185    install everything on the remote gateway.
[274f9ef]186
187    Parameters
188    ----------
[6f951ca]189    c : ControlFile
[274f9ef]190        Contains all the parameters of CONTROL file and
191        command line.
192
193    Return
194    ------
195
[54a8a01]196    '''
[2fb99de]197
198    tarball_name = _config.FLEXEXTRACT_DIRNAME + '.tar'
[8ce3be6]199    tar_file = os.path.join(_config.PATH_FLEXEXTRACT_DIR, tarball_name)
[54a8a01]200
[0f89116]201    mk_compilejob(c.makefile, c.ecuid, c.ecgid, c.installdir)
[54a8a01]202
[0f89116]203    mk_job_template(c.ecuid, c.ecgid, c.installdir)
[8ce3be6]204
205    mk_env_vars(c.ecuid, c.ecgid, c.gateway, c.destination)
206
207    mk_tarball(tar_file, c.install_target)
208
209    put_file_to_ecserver(_config.PATH_FLEXEXTRACT_DIR, tarball_name,
210                         c.install_target, c.ecuid, c.ecgid)
211
212    submit_job_to_ecserver(c.install_target,
213                           os.path.join(_config.PATH_REL_JOBSCRIPTS,
214                                        _config.FILE_INSTALL_COMPILEJOB))
215
216    silent_remove(tar_file)
217
218    print('Job compilation script has been submitted to ecgate for ' +
219          'installation in ' + c.installdir +
[0f89116]220          '/' + _config.FLEXEXTRACT_DIRNAME)
[8ce3be6]221    print('You should get an email with subject "flexcompile" within ' +
222          'the next few minutes!')
223
224    return
225
226def install_local(c):
227    '''Perform the actual installation on a local machine.
[54a8a01]228
[8ce3be6]229    Parameters
230    ----------
231    c : ControlFile
232        Contains all the parameters of CONTROL file and
233        command line.
234
235    Return
236    ------
237
238    '''
239
240    tar_file = os.path.join(_config.PATH_FLEXEXTRACT_DIR,
241                            _config.FLEXEXTRACT_DIRNAME + '.tar')
242
[47be2684]243    # this is standard installation into a single directory
244    if c.install_target == 'local':
[5adaf8a]245        c.installdir = os.path.abspath(os.path.expandvars(os.path.expanduser(
246            c.installdir)))
[47be2684]247
248        # installation into the current directory
249        if os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) == c.installdir:
250            print('WARNING: installdir has not been specified')
251            print('flex_extract will be installed in current dir by compiling the ' +
252                  'Fortran source in ' + _config.PATH_FORTRAN_SRC)
253            os.chdir(_config.PATH_FORTRAN_SRC)
254        # installation into a different path
255        elif os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) != c.installdir :
256
257            # creates the target working directory for flex_extract
[8ce3be6]258            mk_tarball(tar_file, c.install_target)
259            make_dir(os.path.join(c.installdir,
[0f89116]260                                  _config.FLEXEXTRACT_DIRNAME))
[8ce3be6]261            os.chdir(os.path.join(c.installdir,
[0f89116]262                                  _config.FLEXEXTRACT_DIRNAME))
[8ce3be6]263            un_tarball(tar_file)
264            os.chdir(os.path.join(c.installdir,
[0f89116]265                                  _config.FLEXEXTRACT_DIRNAME,
[8ce3be6]266                                  _config.PATH_REL_FORTRAN_SRC))
267
[47be2684]268        # Create Fortran executable
269        print('Install ' +  _config.FLEXEXTRACT_DIRNAME + ' software at ' +
270              c.install_target + ' in directory ' + c.installdir + '\n')
271
272        del_fortran_build('.')
273        mk_fortran_build('.', c.makefile)
274        os.chdir('../../')
275        # make sure that the correct calling of submit.py script is in run_local.sh
276        overwrite_lines_in_file('Run/run_local.sh',
277                                'pyscript=', 'pyscript=../Source/Python/submit.py\n')
278
279    # this is system installation were executables and user files are separated
280    elif c.install_target == 'syslocal':
[5adaf8a]281        c.sysinstalldir = os.path.abspath(os.path.expandvars(os.path.expanduser(
282            c.sysinstalldir)))
[47be2684]283        if os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) == c.sysinstalldir :
284            sys.exit('ERROR: System installation path is equal to user '
285                     'installation path.\n Please change either the system '
286                     'installation path or use installation target "local".')
287        if os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) == c.installdir :
288            print('Flex_extract will be installed in current directory!')
289        else: # install user part in different dir
290            print('Flex_extract will be installed in ' + c.installdir )
291
292            c.installdir = os.path.join(c.installdir,_config.FLEXEXTRACT_DIRNAME)
293            if os.path.isdir(c.installdir):
294                shutil.rmtree(c.installdir)
295
296            # copy all files except Python and Fortranfiles to this dir
297            shutil.copytree(_config.PATH_FLEXEXTRACT_DIR,
298                            c.installdir, symlinks=True)
299            shutil.rmtree(os.path.join(c.installdir,'Source'))
300            shutil.rmtree(os.path.join(c.installdir,'.git'))
301            for x in UioFiles(c.installdir, '*~').files:
302                silent_remove(x)
303
304            os.remove(os.path.join(c.installdir,'setup.sh'))
305            os.remove(os.path.join(c.installdir,'setup_local.sh'))
306
307        # configure run_local script correctly
308        # check if source of system config file is already in run_local.sh,
309        # if not, add it
310        if not check_for_string_in_file(os.path.join(c.installdir,'Run/run_local.sh'),
311                                 'source .setup.rc'):
312            overwrite_lines_in_file(os.path.join(c.installdir,'Run/run_local.sh'),
313                                    '# PATH TO SUBMISSION SCRIPT',
314                                    '# PATH TO SUBMISSION SCRIPT\nsource '+_config.FILE_SYS_CONFIG+'\n')
315        # make sure that the correct calling of submit.py script is in run_local.sh
316        overwrite_lines_in_file(os.path.join(c.installdir,'Run/run_local.sh'),
317                                'pyscript=', 'pyscript=submit.py\n')
318
319        # change permission for file to executable
320        execute_subprocess(['chmod', '0775',
321                            os.path.join(os.path.abspath(c.installdir),'Run/run_local.sh')])
322
323
324        # create systemdir
325        c.sysinstalldir = os.path.join(c.sysinstalldir,_config.FLEXEXTRACT_DIRNAME)
326        if os.path.isdir(c.sysinstalldir):
327            shutil.rmtree(c.sysinstalldir)
328
329        # create setup file for running flex_extract with system installation
330        with open(os.path.join(os.path.abspath(c.installdir),'Run/.setup.rc'),'w') as fio:
331            fio.write('#!/bin/bash \n')
332            fio.write('export FLEXEXTRACT_USER_DIR='+os.path.abspath(c.installdir)+'\n')
333            fio.write('export PATH='+os.path.abspath(c.sysinstalldir)+'/Python:${PATH}\n')
334            fio.write('export PATH='+os.path.abspath(c.sysinstalldir)+':${PATH}\n')
335
336        # copy all Python and Fortranfiles to this dir
337        shutil.copytree(_config.PATH_SOURCES, c.sysinstalldir, symlinks=True)
338
339        os.chdir(os.path.join(c.sysinstalldir,'Fortran'))
340        # Create Fortran executable
341        print('Install ' +  _config.FLEXEXTRACT_DIRNAME + ' software as ' +
342              c.install_target + ' in directory ' +
343              os.path.abspath(c.sysinstalldir) + '\n')
344
345        del_fortran_build('.')
346        mk_fortran_build('.', c.makefile)
347
348        outfile = [x for x in UioFiles('.','*.out').files]
349        test=os.path.join(c.sysinstalldir,'calc_etadot')
350        if len(outfile) != 1:
351            print('WARNING: Multiple executables for Fortran code are available!')
352        # move executable one dir up and delete Fortran dir
353        os.chdir('..')
354        shutil.move(outfile[0], os.path.join(c.sysinstalldir,'calc_etadot'))
355        shutil.rmtree(os.path.join(os.path.abspath(c.sysinstalldir),'Fortran'))
[8ce3be6]356
357    os.chdir(_config.PATH_FLEXEXTRACT_DIR)
358    if os.path.isfile(tar_file):
359        os.remove(tar_file)
[54a8a01]360
361    return
362
[8ce3be6]363
[6cda7c1]364def check_install_conditions(c):
[8209738]365    '''Checks necessary attributes and conditions
366    for the installation, e.g. whether they exist and contain values.
[6cda7c1]367    Otherwise set default values.
368
369    Parameters
370    ----------
[6f951ca]371    c : ControlFile
[6cda7c1]372        Contains all the parameters of CONTROL file and
373        command line.
374
375
376    Return
377    ------
378
379    '''
380
381    if c.install_target and \
382       c.install_target not in _config.INSTALL_TARGETS:
383        print('ERROR: unknown or missing installation target ')
384        print('target: ', c.install_target)
385        print('please specify correct installation target ' +
[0f89116]386              str(_config.INSTALL_TARGETS))
[6cda7c1]387        print('use -h or --help for help')
388        sys.exit(1)
389
[47be2684]390    if c.install_target and c.install_target not in ['local', 'syslocal']:
[50f9ca6]391        if not c.ecgid or not c.ecuid:
392            print('Please enter your ECMWF user id and group id '
393                  ' with command line options --ecuid --ecgid')
[6cda7c1]394            print('Try "' + sys.argv[0].split('/')[-1] + \
395                  ' -h" to print usage information')
[50f9ca6]396            print('Please consult ecaccess documentation or ECMWF user '
397                  'support for further details.\n')
[6cda7c1]398            sys.exit(1)
[50f9ca6]399        if not c.gateway or not c.destination:
400            print('WARNING: Parameters GATEWAY and DESTINATION were '
401                  'not properly set for working on ECMWF server. \n'
402                  'There will be no transfer of output files to the '
403                  'local gateway server possible!')
[8ce3be6]404        if not c.installdir:
405            c.installdir = '${HOME}'
[47be2684]406    elif c.install_target == 'local':
[8ce3be6]407        if not c.installdir:
408            c.installdir = _config.PATH_FLEXEXTRACT_DIR
[47be2684]409    elif c.install_target == 'syslocal':
410        if not c.installdir:
411            c.installdir = _config.PATH_FLEXEXTRACT_DIR
412        if not c.sysinstalldir:
413            print('ERROR: System installation was selected but '
414                  'no system installation path was defined.')
415            sys.exit()
[6cda7c1]416
[5f67883]417    if not c.makefile:
418        print('WARNING: no makefile was specified.')
419        if c.install_target == 'local':
420            c.makefile = 'makefile_local_gfortran'
421            print('WARNING: default makefile selected: makefile_local_gfortan')
422        elif c.install_target == 'ecgate':
423            c.makefile = 'makefile_ecgate'
424            print('WARNING: default makefile selected: makefile_ecgate')
425        elif c.install_target == 'cca' or \
426             c.install_target == 'ccb':
427            c.makefile = 'makefile_cray'
428            print('WARNING: default makefile selected: makefile_cray')
429        else:
430            pass
[47be2684]431
[6cda7c1]432    return
433
434
[25b14be]435def mk_tarball(tarball_path, target):
[274f9ef]436    '''Creates a tarball with all necessary files which need to be sent to the
437    installation directory.
[8209738]438    It does not matter whether this is local or remote.
439    Collects all Python files, the Fortran source and makefiles,
[274f9ef]440    the ECMWF_ENV file, the CONTROL files as well as the
441    template files.
442
443    Parameters
444    ----------
[6f951ca]445    tarball_path : str
[274f9ef]446        The complete path to the tar file which will contain all
447        relevant data for flex_extract.
448
[6f951ca]449    target : str
[274f9ef]450        The queue where the job is submitted to.
451
452    Return
453    ------
454
[54a8a01]455    '''
[2fb99de]456
457    print('Create tarball ...')
458
459    # change to FLEXEXTRACT directory so that the tar can contain
460    # relative pathes to the files and directories
461    ecd = _config.PATH_FLEXEXTRACT_DIR + '/'
462    os.chdir(ecd)
463
464    # get lists of the files to be added to the tar file
[25b14be]465    if target == 'local':
[0f89116]466        ecmwf_env_file = []
[3946de5]467        runfile = [os.path.relpath(x, ecd)
468                   for x in UioFiles(_config.PATH_REL_RUN_DIR,
469                                     'run_local.sh').files]
[25b14be]470    else:
[0f89116]471        ecmwf_env_file = [_config.PATH_REL_ECMWF_ENV]
[3946de5]472        runfile = [os.path.relpath(x, ecd)
[0f89116]473                   for x in UioFiles(_config.PATH_REL_RUN_DIR,
474                                     'run.sh').files]
[25b14be]475
[2fb99de]476    pyfiles = [os.path.relpath(x, ecd)
[3946de5]477               for x in UioFiles(_config.PATH_REL_PYTHON_SRC, '*py').files]
478    pytestfiles = [os.path.relpath(x, ecd)
[0f89116]479                   for x in UioFiles(_config.PATH_REL_PYTHONTEST_SRC, '*py').files]
[2fb99de]480    controlfiles = [os.path.relpath(x, ecd)
[3946de5]481                    for x in UioFiles(_config.PATH_REL_CONTROLFILES,
[25b14be]482                                      'CONTROL*').files]
[1eca806]483    testfiles = [os.path.relpath(x, ecd)
[8028176]484                 for x in UioFiles(_config.PATH_REL_TEST+"/Installation", '*').files]
[2fb99de]485    tempfiles = [os.path.relpath(x, ecd)
[a916e8f]486                 for x in UioFiles(_config.PATH_REL_TEMPLATES, '*.template').files]
[3946de5]487    gribtable = [os.path.relpath(x, ecd)
[0f89116]488                 for x in UioFiles(_config.PATH_REL_TEMPLATES, '*grib*').files]
[2fb99de]489    ffiles = [os.path.relpath(x, ecd)
[0f89116]490              for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, '*.f90').files]
[2fb99de]491    hfiles = [os.path.relpath(x, ecd)
[3946de5]492              for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, '*.h').files]
[2fb99de]493    makefiles = [os.path.relpath(x, ecd)
[3a41083]494                 for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, 'makefile*').files]
[8028176]495    jobdir = [os.path.relpath(x, ecd)
496               for x in UioFiles(_config.PATH_REL_JOBSCRIPTS, '*.md').files]
[2fb99de]497
498    # concatenate single lists to one for a better looping
[a916e8f]499    filelist = pyfiles + pytestfiles + controlfiles + tempfiles + \
[0f89116]500               ffiles + gribtable + hfiles + makefiles + ecmwf_env_file + \
[1eca806]501               runfile + jobdir + testfiles +\
[3946de5]502               ['CODE_OF_CONDUCT.md', 'LICENSE.md', 'README.md']
[2fb99de]503
504    # create installation tar-file
[0f89116]505    exclude_files = [".ksh", ".tar"]
[54a8a01]506    try:
[2fb99de]507        with tarfile.open(tarball_path, "w:gz") as tar_handle:
[0f89116]508            for filename in filelist:
509                tar_handle.add(filename, recursive=False,
[3946de5]510                               filter=lambda tarinfo: None
[0f89116]511                               if os.path.splitext(tarinfo.name)[1]
512                               in exclude_files
513                               else tarinfo)
[79729d5]514    except tarfile.TarError as e:
[0f89116]515        print('... ERROR: ' + str(e))
516
[79729d5]517        sys.exit('\n... error occured while trying to create the tar-file ' +
[0f89116]518                 str(tarball_path))
[54a8a01]519
520    return
521
[2fb99de]522
523def un_tarball(tarball_path):
[274f9ef]524    '''Extracts the given tarball into current directory.
[2fb99de]525
[274f9ef]526    Parameters
527    ----------
[6f951ca]528    tarball_path : str
[274f9ef]529        The complete path to the tar file which will contain all
530        relevant data for flex_extract.
531
532    Return
533    ------
[2fb99de]534
535    '''
536
537    print('Untar ...')
538
[3946de5]539    try:
540        with tarfile.open(tarball_path) as tar_handle:
541            tar_handle.extractall()
542    except tarfile.TarError as e:
543        sys.exit('\n... error occured while trying to read tar-file ' +
[0f89116]544                 str(tarball_path))
[3946de5]545    except OSError as e:
546        print('... ERROR CODE: ' + str(e.errno))
547        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
548
549        sys.exit('\n... error occured while trying to read tar-file ' +
550                 str(tarball_path))
[2fb99de]551
552    return
553
554def mk_env_vars(ecuid, ecgid, gateway, destination):
[274f9ef]555    '''Creates a file named ECMWF_ENV which contains the
556    necessary environmental variables at ECMWF servers.
557    It is based on the template ECMWF_ENV.template.
558
559    Parameters
560    ----------
[6f951ca]561    ecuid : str
[274f9ef]562        The user id on ECMWF server.
[54a8a01]563
[6f951ca]564    ecgid : str
[274f9ef]565        The group id on ECMWF server.
[54a8a01]566
[6f951ca]567    gateway : str
[274f9ef]568        The gateway server the user is using.
[54a8a01]569
[6f951ca]570    destination : str
[274f9ef]571        The remote destination which is used to transfer files
572        from ECMWF server to local gateway server.
[54a8a01]573
[274f9ef]574    Return
575    ------
[54a8a01]576
577    '''
[0aaeb04]578    from genshi.template.text import NewTextTemplate
579    from genshi.template import  TemplateLoader
[3946de5]580    from genshi.template.eval import UndefinedError
[54a8a01]581
[3946de5]582    try:
583        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
584        ecmwfvars_template = loader.load(_config.TEMPFILE_USER_ENVVARS,
585                                         cls=NewTextTemplate)
586
[0f89116]587        stream = ecmwfvars_template.generate(user_name=ecuid,
588                                             user_group=ecgid,
589                                             gateway_name=gateway,
590                                             destination_name=destination
591                                            )
[3946de5]592    except UndefinedError as e:
593        print('... ERROR ' + str(e))
594
595        sys.exit('\n... error occured while trying to generate template ' +
596                 _config.PATH_ECMWF_ENV)
597    except OSError as e:
598        print('... ERROR CODE: ' + str(e.errno))
599        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
600
601        sys.exit('\n... error occured while trying to generate template ' +
602                 _config.PATH_ECMWF_ENV)
[0aaeb04]603
[3946de5]604    try:
605        with open(_config.PATH_ECMWF_ENV, 'w') as f:
606            f.write(stream.render('text'))
607    except OSError as e:
608        print('... ERROR CODE: ' + str(e.errno))
609        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
[0aaeb04]610
[3946de5]611        sys.exit('\n... error occured while trying to write ' +
612                 _config.PATH_ECMWF_ENV)
[54a8a01]613
614    return
615
[0f89116]616def mk_compilejob(makefile, ecuid, ecgid, fp_root):
[274f9ef]617    '''Modifies the original job template file so that it is specified
618    for the user and the environment were it will be applied. Result
619    is stored in a new file "job.temp" in the python directory.
620
621    Parameters
622    ----------
[6f951ca]623    makefile : str
[8209738]624        Name of the makefile which should be used to compile the Fortran
[5f67883]625        program.
[54a8a01]626
[6f951ca]627    ecuid : str
[274f9ef]628        The user id on ECMWF server.
[54a8a01]629
[6f951ca]630    ecgid : str
[274f9ef]631        The group id on ECMWF server.
[54a8a01]632
[6f951ca]633    fp_root : str
[274f9ef]634       Path to the root directory of FLEXPART environment or flex_extract
635       environment.
[54a8a01]636
[274f9ef]637    Return
638    ------
[a4b6cef]639
[991df6a]640    '''
[0aaeb04]641    from genshi.template.text import NewTextTemplate
642    from genshi.template import  TemplateLoader
[3946de5]643    from genshi.template.eval import  UndefinedError
[0aaeb04]644
645    if fp_root == '../':
646        fp_root = '$HOME'
647
[3946de5]648    try:
649        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
650        compile_template = loader.load(_config.TEMPFILE_INSTALL_COMPILEJOB,
651                                       cls=NewTextTemplate)
652
653        stream = compile_template.generate(
[0f89116]654            usergroup=ecgid,
655            username=ecuid,
656            version_number=_config._VERSION_STR,
657            fp_root_scripts=fp_root,
658            makefile=makefile,
659            fortran_program=_config.FORTRAN_EXECUTABLE
[3946de5]660        )
661    except UndefinedError as e:
662        print('... ERROR ' + str(e))
663
664        sys.exit('\n... error occured while trying to generate template ' +
665                 _config.TEMPFILE_INSTALL_COMPILEJOB)
666    except OSError as e:
667        print('... ERROR CODE: ' + str(e.errno))
668        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
669
670        sys.exit('\n... error occured while trying to generate template ' +
671                 _config.TEMPFILE_INSTALL_COMPILEJOB)
[0aaeb04]672
[3946de5]673    try:
674        compilejob = os.path.join(_config.PATH_JOBSCRIPTS,
675                                  _config.FILE_INSTALL_COMPILEJOB)
[0aaeb04]676
[3946de5]677        with open(compilejob, 'w') as f:
678            f.write(stream.render('text'))
679    except OSError as e:
680        print('... ERROR CODE: ' + str(e.errno))
681        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
682
683        sys.exit('\n... error occured while trying to write ' +
684                 compilejob)
[0aaeb04]685
[54a8a01]686    return
687
[0f89116]688def mk_job_template(ecuid, ecgid, fp_root):
[274f9ef]689    '''Modifies the original job template file so that it is specified
690    for the user and the environment were it will be applied. Result
691    is stored in a new file.
[54a8a01]692
[274f9ef]693    Parameters
694    ----------
[6f951ca]695    ecuid : str
[274f9ef]696        The user id on ECMWF server.
[54a8a01]697
[6f951ca]698    ecgid : str
[274f9ef]699        The group id on ECMWF server.
[54a8a01]700
[6f951ca]701    fp_root : str
[274f9ef]702       Path to the root directory of FLEXPART environment or flex_extract
703       environment.
704
705    Return
706    ------
[54a8a01]707
708    '''
[c5074d2]709    from genshi.template.text import NewTextTemplate
710    from genshi.template import  TemplateLoader
[3946de5]711    from genshi.template.eval import  UndefinedError
[c5074d2]712
713    fp_root_path_to_python = os.path.join(fp_root,
714                                          _config.FLEXEXTRACT_DIRNAME,
[3946de5]715                                          _config.PATH_REL_PYTHON_SRC)
[ff2a11c]716    if '$' in fp_root_path_to_python:
717        ind = fp_root_path_to_python.index('$')
718        fp_root_path_to_python = fp_root_path_to_python[0:ind] + '$' + \
719                                 fp_root_path_to_python[ind:]
[3946de5]720
721    try:
722        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
723        compile_template = loader.load(_config.TEMPFILE_INSTALL_JOB,
724                                       cls=NewTextTemplate)
725
726        stream = compile_template.generate(
[0f89116]727            usergroup=ecgid,
728            username=ecuid,
729            version_number=_config._VERSION_STR,
730            fp_root_path=fp_root_path_to_python,
[3946de5]731        )
732    except UndefinedError as e:
733        print('... ERROR ' + str(e))
[c5074d2]734
[3946de5]735        sys.exit('\n... error occured while trying to generate template ' +
736                 _config.TEMPFILE_INSTALL_JOB)
737    except OSError as e:
738        print('... ERROR CODE: ' + str(e.errno))
739        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
740
741        sys.exit('\n... error occured while trying to generate template ' +
742                 _config.TEMPFILE_INSTALL_JOB)
743
744
745    try:
746        tempjobfile = os.path.join(_config.PATH_TEMPLATES,
747                                   _config.TEMPFILE_JOB)
[c5074d2]748
[3946de5]749        with open(tempjobfile, 'w') as f:
750            f.write(stream.render('text'))
751    except OSError as e:
752        print('... ERROR CODE: ' + str(e.errno))
753        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
[c5074d2]754
[3946de5]755        sys.exit('\n... error occured while trying to write ' +
756                 tempjobfile)
[c5074d2]757
[54a8a01]758    return
759
[5f67883]760def del_fortran_build(src_path):
[274f9ef]761    '''Clean up the Fortran source directory and remove all
[5f67883]762    build files (e.g. \*.o, \*.mod and FORTRAN EXECUTABLE)
[274f9ef]763
764    Parameters
765    ----------
[6f951ca]766    src_path : str
[274f9ef]767        Path to the fortran source directory.
[54a8a01]768
[274f9ef]769    Return
770    ------
[54a8a01]771
772    '''
773
[2fb99de]774    modfiles = UioFiles(src_path, '*.mod')
775    objfiles = UioFiles(src_path, '*.o')
776    exefile = UioFiles(src_path, _config.FORTRAN_EXECUTABLE)
[54a8a01]777
778    modfiles.delete_files()
779    objfiles.delete_files()
780    exefile.delete_files()
781
782    return
783
[5f67883]784def mk_fortran_build(src_path, makefile):
[274f9ef]785    '''Compiles the Fortran code and generates the executable.
786
787    Parameters
788    ----------
[6f951ca]789    src_path : str
[274f9ef]790        Path to the fortran source directory.
[54a8a01]791
[6f951ca]792    makefile : str
[274f9ef]793        The name of the makefile which should be used.
[54a8a01]794
[274f9ef]795    Return
796    ------
[54a8a01]797
798    '''
799
800    try:
[2fb99de]801        print('Using makefile: ' + makefile)
802        p = subprocess.Popen(['make', '-f',
803                              os.path.join(src_path, makefile)],
[54a8a01]804                             stdin=subprocess.PIPE,
805                             stdout=subprocess.PIPE,
806                             stderr=subprocess.PIPE,
807                             bufsize=1)
808        pout, perr = p.communicate()
[79729d5]809        print(pout.decode())
[54a8a01]810        if p.returncode != 0:
[79729d5]811            print(perr.decode())
[2fb99de]812            print('Please edit ' + makefile +
[5f67883]813                  ' or try another makefile in the src directory.')
814            print('Most likely ECCODES_INCLUDE_DIR, ECCODES_LIB '
[2fb99de]815                  'and EMOSLIB must be adapted.')
[5f67883]816            print('Available makefiles:')
817            print(UioFiles(src_path, 'makefile*'))
[54a8a01]818            sys.exit('Compilation failed!')
819    except ValueError as e:
[5f67883]820        print('ERROR: makefile call failed:')
[2fb99de]821        print(e)
[d69b677]822    else:
[47be2684]823        execute_subprocess(['ls', '-l',
[0f89116]824                            os.path.join(src_path, _config.FORTRAN_EXECUTABLE)],
825                           error_msg='FORTRAN EXECUTABLE COULD NOT BE FOUND!')
[a4b6cef]826
[d69b677]827    return
828
[a4b6cef]829
[d69b677]830if __name__ == "__main__":
831    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG