source: flex_extract.git/Source/Python/install.py @ 94d3227

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

switch back to using ecaccess-job-submit for installation script

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