source: flex_extract.git/Source/Python/install.py @ 75db9b0

dev
Last change on this file since 75db9b0 was 75db9b0, checked in by anphi <anne.philipp@…>, 4 years ago

added history information of changes to v7.1.2

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