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

ctbtodev
Last change on this file since 8028176 was 8028176, checked in by Anne Philipp <anne.philipp@…>, 4 years ago

updated unit tests

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