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

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

merge of language editing branch into master

  • Property mode set to 100755
File size: 24.5 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)
[0f89116]378                 for x in UioFiles(_config.PATH_REL_TEST, '*').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]
[3946de5]389    jobdir = [_config.PATH_REL_JOBSCRIPTS]
[2fb99de]390
391    # concatenate single lists to one for a better looping
[a916e8f]392    filelist = pyfiles + pytestfiles + controlfiles + tempfiles + \
[0f89116]393               ffiles + gribtable + hfiles + makefiles + ecmwf_env_file + \
[1eca806]394               runfile + jobdir + testfiles +\
[3946de5]395               ['CODE_OF_CONDUCT.md', 'LICENSE.md', 'README.md']
[2fb99de]396
397    # create installation tar-file
[0f89116]398    exclude_files = [".ksh", ".tar"]
[54a8a01]399    try:
[2fb99de]400        with tarfile.open(tarball_path, "w:gz") as tar_handle:
[0f89116]401            for filename in filelist:
402                tar_handle.add(filename, recursive=False,
[3946de5]403                               filter=lambda tarinfo: None
[0f89116]404                               if os.path.splitext(tarinfo.name)[1]
405                               in exclude_files
406                               else tarinfo)
[79729d5]407    except tarfile.TarError as e:
[0f89116]408        print('... ERROR: ' + str(e))
409
[79729d5]410        sys.exit('\n... error occured while trying to create the tar-file ' +
[0f89116]411                 str(tarball_path))
[54a8a01]412
413    return
414
[2fb99de]415
416def un_tarball(tarball_path):
[274f9ef]417    '''Extracts the given tarball into current directory.
[2fb99de]418
[274f9ef]419    Parameters
420    ----------
[6f951ca]421    tarball_path : str
[274f9ef]422        The complete path to the tar file which will contain all
423        relevant data for flex_extract.
424
425    Return
426    ------
[2fb99de]427
428    '''
429
430    print('Untar ...')
431
[3946de5]432    try:
433        with tarfile.open(tarball_path) as tar_handle:
434            tar_handle.extractall()
435    except tarfile.TarError as e:
436        sys.exit('\n... error occured while trying to read tar-file ' +
[0f89116]437                 str(tarball_path))
[3946de5]438    except OSError as e:
439        print('... ERROR CODE: ' + str(e.errno))
440        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
441
442        sys.exit('\n... error occured while trying to read tar-file ' +
443                 str(tarball_path))
[2fb99de]444
445    return
446
447def mk_env_vars(ecuid, ecgid, gateway, destination):
[274f9ef]448    '''Creates a file named ECMWF_ENV which contains the
449    necessary environmental variables at ECMWF servers.
450    It is based on the template ECMWF_ENV.template.
451
452    Parameters
453    ----------
[6f951ca]454    ecuid : str
[274f9ef]455        The user id on ECMWF server.
[54a8a01]456
[6f951ca]457    ecgid : str
[274f9ef]458        The group id on ECMWF server.
[54a8a01]459
[6f951ca]460    gateway : str
[274f9ef]461        The gateway server the user is using.
[54a8a01]462
[6f951ca]463    destination : str
[274f9ef]464        The remote destination which is used to transfer files
465        from ECMWF server to local gateway server.
[54a8a01]466
[274f9ef]467    Return
468    ------
[54a8a01]469
470    '''
[0aaeb04]471    from genshi.template.text import NewTextTemplate
472    from genshi.template import  TemplateLoader
[3946de5]473    from genshi.template.eval import UndefinedError
[54a8a01]474
[3946de5]475    try:
476        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
477        ecmwfvars_template = loader.load(_config.TEMPFILE_USER_ENVVARS,
478                                         cls=NewTextTemplate)
479
[0f89116]480        stream = ecmwfvars_template.generate(user_name=ecuid,
481                                             user_group=ecgid,
482                                             gateway_name=gateway,
483                                             destination_name=destination
484                                            )
[3946de5]485    except UndefinedError as e:
486        print('... ERROR ' + str(e))
487
488        sys.exit('\n... error occured while trying to generate template ' +
489                 _config.PATH_ECMWF_ENV)
490    except OSError as e:
491        print('... ERROR CODE: ' + str(e.errno))
492        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
493
494        sys.exit('\n... error occured while trying to generate template ' +
495                 _config.PATH_ECMWF_ENV)
[0aaeb04]496
[3946de5]497    try:
498        with open(_config.PATH_ECMWF_ENV, 'w') as f:
499            f.write(stream.render('text'))
500    except OSError as e:
501        print('... ERROR CODE: ' + str(e.errno))
502        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
[0aaeb04]503
[3946de5]504        sys.exit('\n... error occured while trying to write ' +
505                 _config.PATH_ECMWF_ENV)
[54a8a01]506
507    return
508
[0f89116]509def mk_compilejob(makefile, ecuid, ecgid, fp_root):
[274f9ef]510    '''Modifies the original job template file so that it is specified
511    for the user and the environment were it will be applied. Result
512    is stored in a new file "job.temp" in the python directory.
513
514    Parameters
515    ----------
[6f951ca]516    makefile : str
[f61e1df]517<<<<<<< HEAD
[274f9ef]518        Name of the makefile which should be used to compile FORTRAN
[f61e1df]519=======
[8209738]520        Name of the makefile which should be used to compile the Fortran
[f61e1df]521>>>>>>> origin/task/language-editing
[5f67883]522        program.
[54a8a01]523
[6f951ca]524    ecuid : str
[274f9ef]525        The user id on ECMWF server.
[54a8a01]526
[6f951ca]527    ecgid : str
[274f9ef]528        The group id on ECMWF server.
[54a8a01]529
[6f951ca]530    fp_root : str
[274f9ef]531       Path to the root directory of FLEXPART environment or flex_extract
532       environment.
[54a8a01]533
[274f9ef]534    Return
535    ------
[a4b6cef]536
[991df6a]537    '''
[0aaeb04]538    from genshi.template.text import NewTextTemplate
539    from genshi.template import  TemplateLoader
[3946de5]540    from genshi.template.eval import  UndefinedError
[0aaeb04]541
542    if fp_root == '../':
543        fp_root = '$HOME'
544
[3946de5]545    try:
546        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
547        compile_template = loader.load(_config.TEMPFILE_INSTALL_COMPILEJOB,
548                                       cls=NewTextTemplate)
549
550        stream = compile_template.generate(
[0f89116]551            usergroup=ecgid,
552            username=ecuid,
553            version_number=_config._VERSION_STR,
554            fp_root_scripts=fp_root,
555            makefile=makefile,
556            fortran_program=_config.FORTRAN_EXECUTABLE
[3946de5]557        )
558    except UndefinedError as e:
559        print('... ERROR ' + str(e))
560
561        sys.exit('\n... error occured while trying to generate template ' +
562                 _config.TEMPFILE_INSTALL_COMPILEJOB)
563    except OSError as e:
564        print('... ERROR CODE: ' + str(e.errno))
565        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
566
567        sys.exit('\n... error occured while trying to generate template ' +
568                 _config.TEMPFILE_INSTALL_COMPILEJOB)
[0aaeb04]569
[3946de5]570    try:
571        compilejob = os.path.join(_config.PATH_JOBSCRIPTS,
572                                  _config.FILE_INSTALL_COMPILEJOB)
[0aaeb04]573
[3946de5]574        with open(compilejob, 'w') as f:
575            f.write(stream.render('text'))
576    except OSError as e:
577        print('... ERROR CODE: ' + str(e.errno))
578        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
579
580        sys.exit('\n... error occured while trying to write ' +
581                 compilejob)
[0aaeb04]582
[54a8a01]583    return
584
[0f89116]585def mk_job_template(ecuid, ecgid, fp_root):
[274f9ef]586    '''Modifies the original job template file so that it is specified
587    for the user and the environment were it will be applied. Result
588    is stored in a new file.
[54a8a01]589
[274f9ef]590    Parameters
591    ----------
[6f951ca]592    ecuid : str
[274f9ef]593        The user id on ECMWF server.
[54a8a01]594
[6f951ca]595    ecgid : str
[274f9ef]596        The group id on ECMWF server.
[54a8a01]597
[6f951ca]598    fp_root : str
[274f9ef]599       Path to the root directory of FLEXPART environment or flex_extract
600       environment.
601
602    Return
603    ------
[54a8a01]604
605    '''
[c5074d2]606    from genshi.template.text import NewTextTemplate
607    from genshi.template import  TemplateLoader
[3946de5]608    from genshi.template.eval import  UndefinedError
[c5074d2]609
610    fp_root_path_to_python = os.path.join(fp_root,
611                                          _config.FLEXEXTRACT_DIRNAME,
[3946de5]612                                          _config.PATH_REL_PYTHON_SRC)
[ff2a11c]613    if '$' in fp_root_path_to_python:
614        ind = fp_root_path_to_python.index('$')
615        fp_root_path_to_python = fp_root_path_to_python[0:ind] + '$' + \
616                                 fp_root_path_to_python[ind:]
[3946de5]617
618    try:
619        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
620        compile_template = loader.load(_config.TEMPFILE_INSTALL_JOB,
621                                       cls=NewTextTemplate)
622
623        stream = compile_template.generate(
[0f89116]624            usergroup=ecgid,
625            username=ecuid,
626            version_number=_config._VERSION_STR,
627            fp_root_path=fp_root_path_to_python,
[3946de5]628        )
629    except UndefinedError as e:
630        print('... ERROR ' + str(e))
[c5074d2]631
[3946de5]632        sys.exit('\n... error occured while trying to generate template ' +
633                 _config.TEMPFILE_INSTALL_JOB)
634    except OSError as e:
635        print('... ERROR CODE: ' + str(e.errno))
636        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
637
638        sys.exit('\n... error occured while trying to generate template ' +
639                 _config.TEMPFILE_INSTALL_JOB)
640
641
642    try:
643        tempjobfile = os.path.join(_config.PATH_TEMPLATES,
644                                   _config.TEMPFILE_JOB)
[c5074d2]645
[3946de5]646        with open(tempjobfile, 'w') as f:
647            f.write(stream.render('text'))
648    except OSError as e:
649        print('... ERROR CODE: ' + str(e.errno))
650        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
[c5074d2]651
[3946de5]652        sys.exit('\n... error occured while trying to write ' +
653                 tempjobfile)
[c5074d2]654
[54a8a01]655    return
656
[5f67883]657def del_fortran_build(src_path):
[274f9ef]658    '''Clean up the Fortran source directory and remove all
[5f67883]659    build files (e.g. \*.o, \*.mod and FORTRAN EXECUTABLE)
[274f9ef]660
661    Parameters
662    ----------
[6f951ca]663    src_path : str
[274f9ef]664        Path to the fortran source directory.
[54a8a01]665
[274f9ef]666    Return
667    ------
[54a8a01]668
669    '''
670
[2fb99de]671    modfiles = UioFiles(src_path, '*.mod')
672    objfiles = UioFiles(src_path, '*.o')
673    exefile = UioFiles(src_path, _config.FORTRAN_EXECUTABLE)
[54a8a01]674
675    modfiles.delete_files()
676    objfiles.delete_files()
677    exefile.delete_files()
678
679    return
680
[5f67883]681def mk_fortran_build(src_path, makefile):
[274f9ef]682    '''Compiles the Fortran code and generates the executable.
683
684    Parameters
685    ----------
[6f951ca]686    src_path : str
[274f9ef]687        Path to the fortran source directory.
[54a8a01]688
[6f951ca]689    makefile : str
[274f9ef]690        The name of the makefile which should be used.
[54a8a01]691
[274f9ef]692    Return
693    ------
[54a8a01]694
695    '''
696
697    try:
[2fb99de]698        print('Using makefile: ' + makefile)
699        p = subprocess.Popen(['make', '-f',
700                              os.path.join(src_path, makefile)],
[54a8a01]701                             stdin=subprocess.PIPE,
702                             stdout=subprocess.PIPE,
703                             stderr=subprocess.PIPE,
704                             bufsize=1)
705        pout, perr = p.communicate()
[79729d5]706        print(pout.decode())
[54a8a01]707        if p.returncode != 0:
[79729d5]708            print(perr.decode())
[2fb99de]709            print('Please edit ' + makefile +
[5f67883]710                  ' or try another makefile in the src directory.')
[f61e1df]711<<<<<<< HEAD
[5f67883]712            print('Most likely ECCODES_INCLUDE_DIR, ECCODES_LIB '
[f61e1df]713=======
[2fb99de]714            print('Most likely GRIB_API_INCLUDE_DIR, GRIB_API_LIB '
[f61e1df]715>>>>>>> origin/task/language-editing
[2fb99de]716                  'and EMOSLIB must be adapted.')
[5f67883]717            print('Available makefiles:')
718            print(UioFiles(src_path, 'makefile*'))
[54a8a01]719            sys.exit('Compilation failed!')
720    except ValueError as e:
[f61e1df]721<<<<<<< HEAD
[5f67883]722        print('ERROR: makefile call failed:')
[f61e1df]723=======
[8209738]724        print('ERROR: make of Fortran code failed:')
[f61e1df]725>>>>>>> origin/task/language-editing
[2fb99de]726        print(e)
[d69b677]727    else:
[8209738]728        execute_subprocess(['ls', '-l', 
[0f89116]729                            os.path.join(src_path, _config.FORTRAN_EXECUTABLE)],
730                           error_msg='FORTRAN EXECUTABLE COULD NOT BE FOUND!')
[a4b6cef]731
[d69b677]732    return
733
[a4b6cef]734
[d69b677]735if __name__ == "__main__":
736    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG