source: flex_extract.git/Source/Python/install.py @ b6ea29e

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

Adaptations for Bologna servers in Python part

  • Property mode set to 100755
File size: 29.6 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
[b6ea29e]112    if c.install_target.lower() not in ['local', 'syslocal']:  # ecmwf servers e.g. ecgate (ecs) and hpc
[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,
[b6ea29e]139                        help="Valid targets: syslocal | local | ecgate | cca | \
140                        ccb | ecs | hpc , the latter 5 are at ECMWF servers")
[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
[b6ea29e]201    mk_compilejob(c.makefile, c.ecuid, 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
[b6ea29e]209    put_file_to_ecserver(_config.PATH_FLEXEXTRACT_DIR, tarball_name)
[8ce3be6]210
211    submit_job_to_ecserver(c.install_target,
212                           os.path.join(_config.PATH_REL_JOBSCRIPTS,
213                                        _config.FILE_INSTALL_COMPILEJOB))
214
215    silent_remove(tar_file)
216
217    print('Job compilation script has been submitted to ecgate for ' +
218          'installation in ' + c.installdir +
[0f89116]219          '/' + _config.FLEXEXTRACT_DIRNAME)
[8ce3be6]220    print('You should get an email with subject "flexcompile" within ' +
221          'the next few minutes!')
222
223    return
224
225def install_local(c):
226    '''Perform the actual installation on a local machine.
[54a8a01]227
[8ce3be6]228    Parameters
229    ----------
230    c : ControlFile
231        Contains all the parameters of CONTROL file and
232        command line.
233
234    Return
235    ------
236
237    '''
238
239    tar_file = os.path.join(_config.PATH_FLEXEXTRACT_DIR,
240                            _config.FLEXEXTRACT_DIRNAME + '.tar')
241
[47be2684]242    # this is standard installation into a single directory
243    if c.install_target == 'local':
[5adaf8a]244        c.installdir = os.path.abspath(os.path.expandvars(os.path.expanduser(
245            c.installdir)))
[47be2684]246
247        # installation into the current directory
248        if os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) == c.installdir:
249            print('WARNING: installdir has not been specified')
250            print('flex_extract will be installed in current dir by compiling the ' +
251                  'Fortran source in ' + _config.PATH_FORTRAN_SRC)
252            os.chdir(_config.PATH_FORTRAN_SRC)
253        # installation into a different path
254        elif os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) != c.installdir :
255
256            # creates the target working directory for flex_extract
[8ce3be6]257            mk_tarball(tar_file, c.install_target)
258            make_dir(os.path.join(c.installdir,
[0f89116]259                                  _config.FLEXEXTRACT_DIRNAME))
[8ce3be6]260            os.chdir(os.path.join(c.installdir,
[0f89116]261                                  _config.FLEXEXTRACT_DIRNAME))
[8ce3be6]262            un_tarball(tar_file)
263            os.chdir(os.path.join(c.installdir,
[0f89116]264                                  _config.FLEXEXTRACT_DIRNAME,
[8ce3be6]265                                  _config.PATH_REL_FORTRAN_SRC))
266
[47be2684]267        # Create Fortran executable
268        print('Install ' +  _config.FLEXEXTRACT_DIRNAME + ' software at ' +
269              c.install_target + ' in directory ' + c.installdir + '\n')
270
271        del_fortran_build('.')
272        mk_fortran_build('.', c.makefile)
273        os.chdir('../../')
274        # make sure that the correct calling of submit.py script is in run_local.sh
275        overwrite_lines_in_file('Run/run_local.sh',
276                                'pyscript=', 'pyscript=../Source/Python/submit.py\n')
277
278    # this is system installation were executables and user files are separated
279    elif c.install_target == 'syslocal':
[5adaf8a]280        c.sysinstalldir = os.path.abspath(os.path.expandvars(os.path.expanduser(
281            c.sysinstalldir)))
[47be2684]282        if os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) == c.sysinstalldir :
283            sys.exit('ERROR: System installation path is equal to user '
284                     'installation path.\n Please change either the system '
285                     'installation path or use installation target "local".')
286        if os.path.abspath(_config.PATH_FLEXEXTRACT_DIR) == c.installdir :
287            print('Flex_extract will be installed in current directory!')
288        else: # install user part in different dir
289            print('Flex_extract will be installed in ' + c.installdir )
290
291            c.installdir = os.path.join(c.installdir,_config.FLEXEXTRACT_DIRNAME)
292            if os.path.isdir(c.installdir):
293                shutil.rmtree(c.installdir)
294
295            # copy all files except Python and Fortranfiles to this dir
296            shutil.copytree(_config.PATH_FLEXEXTRACT_DIR,
297                            c.installdir, symlinks=True)
298            shutil.rmtree(os.path.join(c.installdir,'Source'))
299            shutil.rmtree(os.path.join(c.installdir,'.git'))
300            for x in UioFiles(c.installdir, '*~').files:
301                silent_remove(x)
302
303            os.remove(os.path.join(c.installdir,'setup.sh'))
304            os.remove(os.path.join(c.installdir,'setup_local.sh'))
305
306        # configure run_local script correctly
307        # check if source of system config file is already in run_local.sh,
308        # if not, add it
309        if not check_for_string_in_file(os.path.join(c.installdir,'Run/run_local.sh'),
310                                 'source .setup.rc'):
311            overwrite_lines_in_file(os.path.join(c.installdir,'Run/run_local.sh'),
312                                    '# PATH TO SUBMISSION SCRIPT',
313                                    '# PATH TO SUBMISSION SCRIPT\nsource '+_config.FILE_SYS_CONFIG+'\n')
314        # make sure that the correct calling of submit.py script is in run_local.sh
315        overwrite_lines_in_file(os.path.join(c.installdir,'Run/run_local.sh'),
316                                'pyscript=', 'pyscript=submit.py\n')
317
318        # change permission for file to executable
319        execute_subprocess(['chmod', '0775',
320                            os.path.join(os.path.abspath(c.installdir),'Run/run_local.sh')])
321
322
323        # create systemdir
324        c.sysinstalldir = os.path.join(c.sysinstalldir,_config.FLEXEXTRACT_DIRNAME)
325        if os.path.isdir(c.sysinstalldir):
326            shutil.rmtree(c.sysinstalldir)
327
328        # create setup file for running flex_extract with system installation
329        with open(os.path.join(os.path.abspath(c.installdir),'Run/.setup.rc'),'w') as fio:
330            fio.write('#!/bin/bash \n')
331            fio.write('export FLEXEXTRACT_USER_DIR='+os.path.abspath(c.installdir)+'\n')
332            fio.write('export PATH='+os.path.abspath(c.sysinstalldir)+'/Python:${PATH}\n')
333            fio.write('export PATH='+os.path.abspath(c.sysinstalldir)+':${PATH}\n')
334
335        # copy all Python and Fortranfiles to this dir
336        shutil.copytree(_config.PATH_SOURCES, c.sysinstalldir, symlinks=True)
337
338        os.chdir(os.path.join(c.sysinstalldir,'Fortran'))
339        # Create Fortran executable
340        print('Install ' +  _config.FLEXEXTRACT_DIRNAME + ' software as ' +
341              c.install_target + ' in directory ' +
342              os.path.abspath(c.sysinstalldir) + '\n')
343
344        del_fortran_build('.')
345        mk_fortran_build('.', c.makefile)
346
347        outfile = [x for x in UioFiles('.','*.out').files]
348        test=os.path.join(c.sysinstalldir,'calc_etadot')
349        if len(outfile) != 1:
350            print('WARNING: Multiple executables for Fortran code are available!')
351        # move executable one dir up and delete Fortran dir
352        os.chdir('..')
353        shutil.move(outfile[0], os.path.join(c.sysinstalldir,'calc_etadot'))
354        shutil.rmtree(os.path.join(os.path.abspath(c.sysinstalldir),'Fortran'))
[8ce3be6]355
356    os.chdir(_config.PATH_FLEXEXTRACT_DIR)
357    if os.path.isfile(tar_file):
358        os.remove(tar_file)
[54a8a01]359
360    return
361
[8ce3be6]362
[6cda7c1]363def check_install_conditions(c):
[8209738]364    '''Checks necessary attributes and conditions
365    for the installation, e.g. whether they exist and contain values.
[6cda7c1]366    Otherwise set default values.
367
368    Parameters
369    ----------
[6f951ca]370    c : ControlFile
[6cda7c1]371        Contains all the parameters of CONTROL file and
372        command line.
373
374
375    Return
376    ------
377
378    '''
379
380    if c.install_target and \
381       c.install_target not in _config.INSTALL_TARGETS:
382        print('ERROR: unknown or missing installation target ')
383        print('target: ', c.install_target)
384        print('please specify correct installation target ' +
[0f89116]385              str(_config.INSTALL_TARGETS))
[6cda7c1]386        print('use -h or --help for help')
387        sys.exit(1)
388
[47be2684]389    if c.install_target and c.install_target not in ['local', 'syslocal']:
[50f9ca6]390        if not c.ecgid or not c.ecuid:
391            print('Please enter your ECMWF user id and group id '
392                  ' with command line options --ecuid --ecgid')
[6cda7c1]393            print('Try "' + sys.argv[0].split('/')[-1] + \
394                  ' -h" to print usage information')
[50f9ca6]395            print('Please consult ecaccess documentation or ECMWF user '
396                  'support for further details.\n')
[6cda7c1]397            sys.exit(1)
[50f9ca6]398        if not c.gateway or not c.destination:
399            print('WARNING: Parameters GATEWAY and DESTINATION were '
400                  'not properly set for working on ECMWF server. \n'
401                  'There will be no transfer of output files to the '
402                  'local gateway server possible!')
[8ce3be6]403        if not c.installdir:
404            c.installdir = '${HOME}'
[47be2684]405    elif c.install_target == 'local':
[8ce3be6]406        if not c.installdir:
407            c.installdir = _config.PATH_FLEXEXTRACT_DIR
[47be2684]408    elif c.install_target == 'syslocal':
409        if not c.installdir:
410            c.installdir = _config.PATH_FLEXEXTRACT_DIR
411        if not c.sysinstalldir:
412            print('ERROR: System installation was selected but '
413                  'no system installation path was defined.')
414            sys.exit()
[6cda7c1]415
[5f67883]416    if not c.makefile:
417        print('WARNING: no makefile was specified.')
418        if c.install_target == 'local':
419            c.makefile = 'makefile_local_gfortran'
420            print('WARNING: default makefile selected: makefile_local_gfortan')
421        elif c.install_target == 'ecgate':
422            c.makefile = 'makefile_ecgate'
423            print('WARNING: default makefile selected: makefile_ecgate')
424        elif c.install_target == 'cca' or \
425             c.install_target == 'ccb':
426            c.makefile = 'makefile_cray'
427            print('WARNING: default makefile selected: makefile_cray')
428        else:
429            pass
[47be2684]430
[6cda7c1]431    return
432
433
[25b14be]434def mk_tarball(tarball_path, target):
[274f9ef]435    '''Creates a tarball with all necessary files which need to be sent to the
436    installation directory.
[8209738]437    It does not matter whether this is local or remote.
438    Collects all Python files, the Fortran source and makefiles,
[274f9ef]439    the ECMWF_ENV file, the CONTROL files as well as the
440    template files.
441
442    Parameters
443    ----------
[6f951ca]444    tarball_path : str
[274f9ef]445        The complete path to the tar file which will contain all
446        relevant data for flex_extract.
447
[6f951ca]448    target : str
[274f9ef]449        The queue where the job is submitted to.
450
451    Return
452    ------
453
[54a8a01]454    '''
[2fb99de]455
456    print('Create tarball ...')
457
458    # change to FLEXEXTRACT directory so that the tar can contain
459    # relative pathes to the files and directories
460    ecd = _config.PATH_FLEXEXTRACT_DIR + '/'
461    os.chdir(ecd)
462
463    # get lists of the files to be added to the tar file
[25b14be]464    if target == 'local':
[0f89116]465        ecmwf_env_file = []
[3946de5]466        runfile = [os.path.relpath(x, ecd)
467                   for x in UioFiles(_config.PATH_REL_RUN_DIR,
468                                     'run_local.sh').files]
[25b14be]469    else:
[0f89116]470        ecmwf_env_file = [_config.PATH_REL_ECMWF_ENV]
[3946de5]471        runfile = [os.path.relpath(x, ecd)
[0f89116]472                   for x in UioFiles(_config.PATH_REL_RUN_DIR,
473                                     'run.sh').files]
[25b14be]474
[2fb99de]475    pyfiles = [os.path.relpath(x, ecd)
[3946de5]476               for x in UioFiles(_config.PATH_REL_PYTHON_SRC, '*py').files]
477    pytestfiles = [os.path.relpath(x, ecd)
[0f89116]478                   for x in UioFiles(_config.PATH_REL_PYTHONTEST_SRC, '*py').files]
[2fb99de]479    controlfiles = [os.path.relpath(x, ecd)
[3946de5]480                    for x in UioFiles(_config.PATH_REL_CONTROLFILES,
[25b14be]481                                      'CONTROL*').files]
[1eca806]482    testfiles = [os.path.relpath(x, ecd)
[8028176]483                 for x in UioFiles(_config.PATH_REL_TEST+"/Installation", '*').files]
[2fb99de]484    tempfiles = [os.path.relpath(x, ecd)
[a916e8f]485                 for x in UioFiles(_config.PATH_REL_TEMPLATES, '*.template').files]
[3946de5]486    gribtable = [os.path.relpath(x, ecd)
[0f89116]487                 for x in UioFiles(_config.PATH_REL_TEMPLATES, '*grib*').files]
[2fb99de]488    ffiles = [os.path.relpath(x, ecd)
[0f89116]489              for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, '*.f90').files]
[2fb99de]490    hfiles = [os.path.relpath(x, ecd)
[3946de5]491              for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, '*.h').files]
[2fb99de]492    makefiles = [os.path.relpath(x, ecd)
[3a41083]493                 for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, 'makefile*').files]
[8028176]494    jobdir = [os.path.relpath(x, ecd)
495               for x in UioFiles(_config.PATH_REL_JOBSCRIPTS, '*.md').files]
[2fb99de]496
497    # concatenate single lists to one for a better looping
[a916e8f]498    filelist = pyfiles + pytestfiles + controlfiles + tempfiles + \
[0f89116]499               ffiles + gribtable + hfiles + makefiles + ecmwf_env_file + \
[1eca806]500               runfile + jobdir + testfiles +\
[3946de5]501               ['CODE_OF_CONDUCT.md', 'LICENSE.md', 'README.md']
[2fb99de]502
503    # create installation tar-file
[0f89116]504    exclude_files = [".ksh", ".tar"]
[54a8a01]505    try:
[2fb99de]506        with tarfile.open(tarball_path, "w:gz") as tar_handle:
[0f89116]507            for filename in filelist:
508                tar_handle.add(filename, recursive=False,
[3946de5]509                               filter=lambda tarinfo: None
[0f89116]510                               if os.path.splitext(tarinfo.name)[1]
511                               in exclude_files
512                               else tarinfo)
[79729d5]513    except tarfile.TarError as e:
[0f89116]514        print('... ERROR: ' + str(e))
515
[79729d5]516        sys.exit('\n... error occured while trying to create the tar-file ' +
[0f89116]517                 str(tarball_path))
[54a8a01]518
519    return
520
[2fb99de]521
522def un_tarball(tarball_path):
[274f9ef]523    '''Extracts the given tarball into current directory.
[2fb99de]524
[274f9ef]525    Parameters
526    ----------
[6f951ca]527    tarball_path : str
[274f9ef]528        The complete path to the tar file which will contain all
529        relevant data for flex_extract.
530
531    Return
532    ------
[2fb99de]533
534    '''
535
536    print('Untar ...')
537
[3946de5]538    try:
539        with tarfile.open(tarball_path) as tar_handle:
540            tar_handle.extractall()
541    except tarfile.TarError as e:
542        sys.exit('\n... error occured while trying to read tar-file ' +
[0f89116]543                 str(tarball_path))
[3946de5]544    except OSError as e:
545        print('... ERROR CODE: ' + str(e.errno))
546        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
547
548        sys.exit('\n... error occured while trying to read tar-file ' +
549                 str(tarball_path))
[2fb99de]550
551    return
552
553def mk_env_vars(ecuid, ecgid, gateway, destination):
[274f9ef]554    '''Creates a file named ECMWF_ENV which contains the
555    necessary environmental variables at ECMWF servers.
556    It is based on the template ECMWF_ENV.template.
557
558    Parameters
559    ----------
[6f951ca]560    ecuid : str
[274f9ef]561        The user id on ECMWF server.
[54a8a01]562
[6f951ca]563    ecgid : str
[274f9ef]564        The group id on ECMWF server.
[54a8a01]565
[6f951ca]566    gateway : str
[274f9ef]567        The gateway server the user is using.
[54a8a01]568
[6f951ca]569    destination : str
[274f9ef]570        The remote destination which is used to transfer files
571        from ECMWF server to local gateway server.
[54a8a01]572
[274f9ef]573    Return
574    ------
[54a8a01]575
576    '''
[0aaeb04]577    from genshi.template.text import NewTextTemplate
578    from genshi.template import  TemplateLoader
[3946de5]579    from genshi.template.eval import UndefinedError
[54a8a01]580
[3946de5]581    try:
582        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
583        ecmwfvars_template = loader.load(_config.TEMPFILE_USER_ENVVARS,
584                                         cls=NewTextTemplate)
585
[0f89116]586        stream = ecmwfvars_template.generate(user_name=ecuid,
587                                             user_group=ecgid,
588                                             gateway_name=gateway,
589                                             destination_name=destination
590                                            )
[3946de5]591    except UndefinedError as e:
592        print('... ERROR ' + str(e))
593
594        sys.exit('\n... error occured while trying to generate template ' +
595                 _config.PATH_ECMWF_ENV)
596    except OSError as e:
597        print('... ERROR CODE: ' + str(e.errno))
598        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
599
600        sys.exit('\n... error occured while trying to generate template ' +
601                 _config.PATH_ECMWF_ENV)
[0aaeb04]602
[3946de5]603    try:
604        with open(_config.PATH_ECMWF_ENV, 'w') as f:
605            f.write(stream.render('text'))
606    except OSError as e:
607        print('... ERROR CODE: ' + str(e.errno))
608        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
[0aaeb04]609
[3946de5]610        sys.exit('\n... error occured while trying to write ' +
611                 _config.PATH_ECMWF_ENV)
[54a8a01]612
613    return
614
[b6ea29e]615def mk_compilejob(makefile, ecuid, fp_root):
[274f9ef]616    '''Modifies the original job template file so that it is specified
617    for the user and the environment were it will be applied. Result
[b6ea29e]618    is stored in a new file "compilejob.ksh" in the Jobscript directory.
[274f9ef]619
620    Parameters
621    ----------
[6f951ca]622    makefile : str
[8209738]623        Name of the makefile which should be used to compile the Fortran
[5f67883]624        program.
[54a8a01]625
[6f951ca]626    ecuid : str
[274f9ef]627        The user id on ECMWF server.
[54a8a01]628
[6f951ca]629    fp_root : str
[274f9ef]630       Path to the root directory of FLEXPART environment or flex_extract
631       environment.
[54a8a01]632
[274f9ef]633    Return
634    ------
[a4b6cef]635
[991df6a]636    '''
[0aaeb04]637    from genshi.template.text import NewTextTemplate
638    from genshi.template import  TemplateLoader
[3946de5]639    from genshi.template.eval import  UndefinedError
[0aaeb04]640
641    if fp_root == '../':
642        fp_root = '$HOME'
643
[3946de5]644    try:
645        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
646        compile_template = loader.load(_config.TEMPFILE_INSTALL_COMPILEJOB,
647                                       cls=NewTextTemplate)
648
649        stream = compile_template.generate(
[0f89116]650            username=ecuid,
651            version_number=_config._VERSION_STR,
652            fp_root_scripts=fp_root,
653            makefile=makefile,
654            fortran_program=_config.FORTRAN_EXECUTABLE
[3946de5]655        )
656    except UndefinedError as e:
657        print('... ERROR ' + str(e))
658
659        sys.exit('\n... error occured while trying to generate template ' +
660                 _config.TEMPFILE_INSTALL_COMPILEJOB)
661    except OSError as e:
662        print('... ERROR CODE: ' + str(e.errno))
663        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
664
665        sys.exit('\n... error occured while trying to generate template ' +
666                 _config.TEMPFILE_INSTALL_COMPILEJOB)
[0aaeb04]667
[3946de5]668    try:
669        compilejob = os.path.join(_config.PATH_JOBSCRIPTS,
670                                  _config.FILE_INSTALL_COMPILEJOB)
[0aaeb04]671
[3946de5]672        with open(compilejob, 'w') as f:
673            f.write(stream.render('text'))
674    except OSError as e:
675        print('... ERROR CODE: ' + str(e.errno))
676        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
677
678        sys.exit('\n... error occured while trying to write ' +
679                 compilejob)
[0aaeb04]680
[54a8a01]681    return
682
[0f89116]683def mk_job_template(ecuid, ecgid, fp_root):
[274f9ef]684    '''Modifies the original job template file so that it is specified
685    for the user and the environment were it will be applied. Result
686    is stored in a new file.
[54a8a01]687
[274f9ef]688    Parameters
689    ----------
[6f951ca]690    ecuid : str
[274f9ef]691        The user id on ECMWF server.
[54a8a01]692
[6f951ca]693    ecgid : str
[274f9ef]694        The group id on ECMWF server.
[54a8a01]695
[6f951ca]696    fp_root : str
[274f9ef]697       Path to the root directory of FLEXPART environment or flex_extract
698       environment.
699
700    Return
701    ------
[54a8a01]702
703    '''
[c5074d2]704    from genshi.template.text import NewTextTemplate
705    from genshi.template import  TemplateLoader
[3946de5]706    from genshi.template.eval import  UndefinedError
[c5074d2]707
708    fp_root_path_to_python = os.path.join(fp_root,
709                                          _config.FLEXEXTRACT_DIRNAME,
[3946de5]710                                          _config.PATH_REL_PYTHON_SRC)
[ff2a11c]711    if '$' in fp_root_path_to_python:
712        ind = fp_root_path_to_python.index('$')
713        fp_root_path_to_python = fp_root_path_to_python[0:ind] + '$' + \
714                                 fp_root_path_to_python[ind:]
[3946de5]715
716    try:
717        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
718        compile_template = loader.load(_config.TEMPFILE_INSTALL_JOB,
719                                       cls=NewTextTemplate)
720
721        stream = compile_template.generate(
[0f89116]722            usergroup=ecgid,
723            username=ecuid,
724            version_number=_config._VERSION_STR,
725            fp_root_path=fp_root_path_to_python,
[3946de5]726        )
727    except UndefinedError as e:
728        print('... ERROR ' + str(e))
[c5074d2]729
[3946de5]730        sys.exit('\n... error occured while trying to generate template ' +
731                 _config.TEMPFILE_INSTALL_JOB)
732    except OSError as e:
733        print('... ERROR CODE: ' + str(e.errno))
734        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
735
736        sys.exit('\n... error occured while trying to generate template ' +
737                 _config.TEMPFILE_INSTALL_JOB)
738
739
740    try:
741        tempjobfile = os.path.join(_config.PATH_TEMPLATES,
742                                   _config.TEMPFILE_JOB)
[c5074d2]743
[3946de5]744        with open(tempjobfile, 'w') as f:
745            f.write(stream.render('text'))
746    except OSError as e:
747        print('... ERROR CODE: ' + str(e.errno))
748        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
[c5074d2]749
[3946de5]750        sys.exit('\n... error occured while trying to write ' +
751                 tempjobfile)
[c5074d2]752
[54a8a01]753    return
754
[5f67883]755def del_fortran_build(src_path):
[274f9ef]756    '''Clean up the Fortran source directory and remove all
[5f67883]757    build files (e.g. \*.o, \*.mod and FORTRAN EXECUTABLE)
[274f9ef]758
759    Parameters
760    ----------
[6f951ca]761    src_path : str
[274f9ef]762        Path to the fortran source directory.
[54a8a01]763
[274f9ef]764    Return
765    ------
[54a8a01]766
767    '''
768
[2fb99de]769    modfiles = UioFiles(src_path, '*.mod')
770    objfiles = UioFiles(src_path, '*.o')
771    exefile = UioFiles(src_path, _config.FORTRAN_EXECUTABLE)
[54a8a01]772
773    modfiles.delete_files()
774    objfiles.delete_files()
775    exefile.delete_files()
776
777    return
778
[5f67883]779def mk_fortran_build(src_path, makefile):
[274f9ef]780    '''Compiles the Fortran code and generates the executable.
781
782    Parameters
783    ----------
[6f951ca]784    src_path : str
[274f9ef]785        Path to the fortran source directory.
[54a8a01]786
[6f951ca]787    makefile : str
[274f9ef]788        The name of the makefile which should be used.
[54a8a01]789
[274f9ef]790    Return
791    ------
[54a8a01]792
793    '''
794
795    try:
[2fb99de]796        print('Using makefile: ' + makefile)
797        p = subprocess.Popen(['make', '-f',
798                              os.path.join(src_path, makefile)],
[54a8a01]799                             stdin=subprocess.PIPE,
800                             stdout=subprocess.PIPE,
801                             stderr=subprocess.PIPE,
802                             bufsize=1)
803        pout, perr = p.communicate()
[79729d5]804        print(pout.decode())
[54a8a01]805        if p.returncode != 0:
[79729d5]806            print(perr.decode())
[2fb99de]807            print('Please edit ' + makefile +
[5f67883]808                  ' or try another makefile in the src directory.')
809            print('Most likely ECCODES_INCLUDE_DIR, ECCODES_LIB '
[2fb99de]810                  'and EMOSLIB must be adapted.')
[5f67883]811            print('Available makefiles:')
812            print(UioFiles(src_path, 'makefile*'))
[54a8a01]813            sys.exit('Compilation failed!')
814    except ValueError as e:
[5f67883]815        print('ERROR: makefile call failed:')
[2fb99de]816        print(e)
[d69b677]817    else:
[47be2684]818        execute_subprocess(['ls', '-l',
[0f89116]819                            os.path.join(src_path, _config.FORTRAN_EXECUTABLE)],
820                           error_msg='FORTRAN EXECUTABLE COULD NOT BE FOUND!')
[a4b6cef]821
[d69b677]822    return
823
[a4b6cef]824
[d69b677]825if __name__ == "__main__":
826    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG