source: flex_extract.git/python/install.py @ 991df6a

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

finished documentation (except plot_retrieved)

  • Property mode set to 100755
File size: 16.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#************************************************************************
4# TODO AP
5# - localpythonpath should not be set in module load section!
6# - create a class Installation and divide installation in 3 subdefs for
7#   ecgate, local and cca seperatly
8# - Change History ist nicht angepasst ans File! Original geben lassen
9#************************************************************************
10#*******************************************************************************
11# @Author: Leopold Haimberger (University of Vienna)
12#
13# @Date: November 2015
14#
15# @Change History:
16#
17#    February 2018 - Anne Philipp (University of Vienna):
18#        - applied PEP8 style guide
19#        - added documentation
20#
21# @License:
22#    (C) Copyright 2015-2018.
23#
24#    This software is licensed under the terms of the Apache Licence Version 2.0
25#    which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
26#
27# @Program Functionality:
28#    Depending on the selected installation environment (locally or on the
29#    ECMWF server ecgate or cca) the program extracts the commandline
30#    arguments and the CONTROL file parameter and prepares the corresponding
31#    environment. The necessary files are collected in a tar-ball and placed
32#    at the target location. There its untared, the environment variables will
33#    be set and the Fortran code will be compiled. If the ECMWF environment is
34#    selected a job script is prepared and submitted for the remaining
35#    configurations after putting the tar-ball to the target ECMWF server.
36#
37# @Program Content:
38#    - main
39#    - install_args_and_control
40#    - install_via_gateway
41#
42#*******************************************************************************
43
44# ------------------------------------------------------------------------------
45# MODULES
46# ------------------------------------------------------------------------------
47import datetime
48import os
49import sys
50import glob
51import subprocess
52import inspect
53from argparse import ArgumentParser,ArgumentDefaultsHelpFormatter
54
55# add path to pythonpath so that python finds its buddies
56localpythonpath = os.path.dirname(os.path.abspath(
57    inspect.getfile(inspect.currentframe())))
58if localpythonpath not in sys.path:
59    sys.path.append(localpythonpath)
60
61# software specific classes and modules from flex_extract
62from ControlFile import ControlFile
63
64# ------------------------------------------------------------------------------
65# FUNCTIONS
66# ------------------------------------------------------------------------------
67def main():
68    '''
69    @Description:
70        Controls the installation process. Calls the installation function
71        if target is specified.
72
73    @Intput:
74        <nothing>
75
76    @Return:
77        <nothing>
78    '''
79
80    os.chdir(localpythonpath)
81    args, c = install_args_and_control()
82
83    if args.install_target is not None:
84        install_via_gateway(c, args.install_target)
85    else:
86        print('Please specify installation target (local|ecgate|cca)')
87        print('use -h or --help for help')
88
89    sys.exit()
90
91    return
92
93
94def install_args_and_control():
95    '''
96    @Description:
97        Assigns the command line arguments for installation and reads
98        CONTROL file content. Apply default values for non mentioned arguments.
99
100    @Input:
101        <nothing>
102
103    @Return:
104        args: instance of ArgumentParser
105            Contains the commandline arguments from script/program call.
106
107        c: instance of class ControlFile
108            Contains all necessary information of a CONTROL file. The parameters
109            are: DAY1, DAY2, DTIME, MAXSTEP, TYPE, TIME, STEP, CLASS, STREAM,
110            NUMBER, EXPVER, GRID, LEFT, LOWER, UPPER, RIGHT, LEVEL, LEVELIST,
111            RESOL, GAUSS, ACCURACY, OMEGA, OMEGADIFF, ETA, ETADIFF, DPDETA,
112            SMOOTH, FORMAT, ADDPAR, WRF, CWC, PREFIX, ECSTORAGE, ECTRANS,
113            ECFSDIR, MAILOPS, MAILFAIL, GRIB2FLEXPART, FLEXPARTDIR
114            For more information about format and content of the parameter see
115            documentation.
116    '''
117    parser = ArgumentParser(description='Install ECMWFDATA software locally or \
118                            on ECMWF machines',
119                            formatter_class=ArgumentDefaultsHelpFormatter)
120
121    parser.add_argument('--target', dest='install_target',
122                        help="Valid targets: local | ecgate | cca , \
123                        the latter two are at ECMWF")
124    parser.add_argument("--makefile", dest="makefile",
125                        help='Name of Makefile to use for compiling CONVERT2')
126    parser.add_argument("--ecuid", dest="ecuid",
127                        help='user id at ECMWF')
128    parser.add_argument("--ecgid", dest="ecgid",
129                        help='group id at ECMWF')
130    parser.add_argument("--gateway", dest="gateway",
131                        help='name of local gateway server')
132    parser.add_argument("--destination", dest="destination",
133                        help='ecaccess destination, e.g. leo@genericSftp')
134
135    parser.add_argument("--flexpart_root_scripts", dest="flexpart_root_scripts",
136                        help="FLEXPART root directory on ECMWF servers \
137                        (to find grib2flexpart and COMMAND file)\n\
138                        Normally ECMWFDATA resides in the scripts directory \
139                        of the FLEXPART distribution, thus the:")
140
141# arguments for job submission to ECMWF, only needed by submit.py
142    parser.add_argument("--job_template", dest='job_template',
143                        default="job.temp.o",
144                        help="job template file for submission to ECMWF")
145
146    parser.add_argument("--controlfile", dest="controlfile",
147                        default='CONTROL.temp',
148                        help="file with CONTROL parameters")
149
150    args = parser.parse_args()
151
152    try:
153        c = ControlFile(args.controlfile)
154    except:
155        print('Could not read CONTROL file "' + args.controlfile + '"')
156        print('Either it does not exist or its syntax is wrong.')
157        print('Try "' + sys.argv[0].split('/')[-1] +
158              ' -h" to print usage information')
159        exit(1)
160
161    if args.install_target != 'local':
162        if (args.ecgid is None or args.ecuid is None or args.gateway is None
163            or args.destination is None):
164            print('Please enter your ECMWF user id and group id as well as \
165                   the \nname of the local gateway and the ectrans \
166                   destination ')
167            print('with command line options --ecuid --ecgid \
168                   --gateway --destination')
169            print('Try "' + sys.argv[0].split('/')[-1] +
170                  ' -h" to print usage information')
171            print('Please consult ecaccess documentation or ECMWF user support \
172                   for further details')
173            sys.exit(1)
174        else:
175            c.ecuid = args.ecuid
176            c.ecgid = args.ecgid
177            c.gateway = args.gateway
178            c.destination = args.destination
179
180    try:
181        c.makefile = args.makefile
182    except:
183        pass
184
185    if args.install_target == 'local':
186        if args.flexpart_root_scripts is None:
187            c.flexpart_root_scripts = '../'
188        else:
189            c.flexpart_root_scripts = args.flexpart_root_scripts
190
191    if args.install_target != 'local':
192        if args.flexpart_root_scripts is None:
193            c.ec_flexpart_root_scripts = '${HOME}'
194        else:
195            c.ec_flexpart_root_scripts = args.flexpart_root_scripts
196
197    return args, c
198
199
200def install_via_gateway(c, target):
201    '''
202    @Description:
203        Perform the actual installation on local machine or prepare data
204        transfer to remote gate and submit a job script which will
205        install everything on the remote gate.
206
207    @Input:
208        c: instance of class ControlFile
209            Contains all necessary information of a CONTROL file. The parameters
210            are: DAY1, DAY2, DTIME, MAXSTEP, TYPE, TIME, STEP, CLASS, STREAM,
211            NUMBER, EXPVER, GRID, LEFT, LOWER, UPPER, RIGHT, LEVEL, LEVELIST,
212            RESOL, GAUSS, ACCURACY, OMEGA, OMEGADIFF, ETA, ETADIFF, DPDETA,
213            SMOOTH, FORMAT, ADDPAR, WRF, CWC, PREFIX, ECSTORAGE, ECTRANS,
214            ECFSDIR, MAILOPS, MAILFAIL, GRIB2FLEXPART, FLEXPARTDIR
215            For more information about format and content of the parameter see
216            documentation.
217
218        target: string
219            The target where the installation should be processed.
220            E.g. "local", "ecgate" or "cca"
221
222    @Return:
223        <nothing>
224    '''
225    ecd = c.ecmwfdatadir
226    template = ecd + 'python/compilejob.temp'
227    job = ecd + 'python/compilejob.ksh'
228    fo = open(job, 'w')
229#AP could do with open(template) as f, open(job, 'w') as fo:
230#AP or nested with statements
231    with open(template) as f:
232        fdata = f.read().split('\n')
233        for data in fdata:
234            if 'MAKEFILE=' in data:
235                if c.makefile is not None:
236                    data = 'export MAKEFILE=' + c.makefile
237            if 'FLEXPART_ROOT_SCRIPTS=' in data:
238                if c.flexpart_root_scripts != '../':
239                    data = 'export FLEXPART_ROOT_SCRIPTS=' + \
240                            c.flexpart_root_scripts
241                else:
242                    data='export FLEXPART_ROOT_SCRIPTS=$HOME'
243            if target.lower() != 'local':
244                if '--workdir' in data:
245                    data = '#SBATCH --workdir=/scratch/ms/' + c.ecgid + \
246                            '/' + c.ecuid
247                if '##PBS -o' in data:
248                    data = '##PBS -o /scratch/ms/' + c.ecgid + '/' + c.ecuid + \
249                            'flex_ecmwf.$Jobname.$Job_ID.out'
250                if 'FLEXPART_ROOT_SCRIPTS=' in data:
251                    if c.ec_flexpart_root_scripts != '../':
252                        data = 'export FLEXPART_ROOT_SCRIPTS=' + \
253                                c.ec_flexpart_root_scripts
254                    else:
255                        data = 'export FLEXPART_ROOT_SCRIPTS=$HOME'
256            fo.write(data + '\n')
257    f.close()
258    fo.close()
259
260    if target.lower() != 'local':
261        template = ecd + 'python/job.temp.o'
262#AP hier eventuell Zeile für Zeile lesen und dann if Entscheidung
263        with open(template) as f:
264            fdata = f.read().split('\n')
265        f.close()
266        fo = open(template[:-2], 'w')
267        for data in fdata:
268            if '--workdir' in data:
269                data = '#SBATCH --workdir=/scratch/ms/' + c.ecgid + \
270                        '/' + c.ecuid
271            if '##PBS -o' in data:
272                data = '##PBS -o /scratch/ms/' + c.ecgid + '/' + \
273                        c.ecuid + 'flex_ecmwf.$Jobname.$Job_ID.out'
274            if  'export PATH=${PATH}:' in data:
275                data += c.ec_flexpart_root_scripts + '/ECMWFDATA7.1/python'
276            if 'cat>>' in data or 'cat >>' in data:
277                i = data.index('>')
278                fo.write(data[:i] + data[i+1:] + '\n')
279                fo.write('GATEWAY ' + c.gateway + '\n')
280                fo.write('DESTINATION ' + c.destination + '\n')
281                fo.write('EOF\n')
282
283            fo.write(data + '\n')
284        fo.close()
285
286        job = ecd + 'python/ECMWF_ENV'
287        with open(job, 'w') as fo:
288            fo.write('ECUID ' + c.ecuid + '\n')
289            fo.write('ECGID ' + c.ecgid + '\n')
290            fo.write('GATEWAY ' + c.gateway + '\n')
291            fo.write('DESTINATION ' + c.destination + '\n')
292        fo.close()
293
294
295
296    if target.lower() == 'local':
297        # compile CONVERT2
298        if c.flexpart_root_scripts is None or c.flexpart_root_scripts == '../':
299            print('Warning: FLEXPART_ROOT_SCRIPTS has not been specified')
300            print('Only CONVERT2 will be compiled in ' + ecd + '/../src')
301        else:
302            c.flexpart_root_scripts = os.path.expandvars(os.path.expanduser(
303                                        c.flexpart_root_scripts))
304            if os.path.abspath(ecd) != os.path.abspath(c.flexpart_root_scripts):
305                os.chdir('/')
306                p = subprocess.check_call(['tar', '-cvf',
307                                           ecd + '../ECMWFDATA7.1.tar',
308                                           ecd + 'python',
309                                           ecd + 'grib_templates',
310                                           ecd + 'src'])
311                try:
312                    os.makedirs(c.flexpart_root_scripts + '/ECMWFDATA7.1')
313                except:
314                    pass
315                os.chdir(c.flexpart_root_scripts + '/ECMWFDATA7.1')
316                p = subprocess.check_call(['tar', '-xvf',
317                                           ecd + '../ECMWFDATA7.1.tar'])
318                os.chdir(c.flexpart_root_scripts + '/ECMWFDATA7.1/src')
319
320        os.chdir('../src')
321        print(('install ECMWFDATA7.1 software on ' + target + ' in directory '
322               + os.getcwd()))
323        if c.makefile is None:
324            makefile = 'Makefile.local.ifort'
325        else:
326            makefile = c.makefile
327        flist = glob.glob('*.mod') + glob.glob('*.o')
328        if flist:
329            p = subprocess.check_call(['rm'] + flist)
330        try:
331            print(('Using makefile: ' + makefile))
332            p = subprocess.check_call(['make', '-f', makefile])
333            p = subprocess.check_call(['ls', '-l','CONVERT2'])
334        except:
335            print('compile failed - please edit ' + makefile +
336                  ' or try another Makefile in the src directory.')
337            print('most likely GRIB_API_INCLUDE_DIR, GRIB_API_LIB '
338                    'and EMOSLIB must be adapted.')
339            print('Available Makefiles:')
340            print(glob.glob('Makefile*'))
341
342    elif target.lower() == 'ecgate':
343        os.chdir('/')
344        p = subprocess.check_call(['tar', '-cvf',
345                                   ecd + '../ECMWFDATA7.1.tar',
346                                   ecd + 'python',
347                                   ecd + 'grib_templates',
348                                   ecd + 'src'])
349        try:
350            p = subprocess.check_call(['ecaccess-file-put',
351                                       ecd + '../ECMWFDATA7.1.tar',
352                                       'ecgate:/home/ms/' + c.ecgid + '/' +
353                                       c.ecuid + '/ECMWFDATA7.1.tar'])
354        except:
355            print('ecaccess-file-put failed! Probably the eccert key has expired.')
356            exit(1)
357        p = subprocess.check_call(['ecaccess-job-submit',
358                                   '-queueName',
359                                   target,
360                                   ecd + 'python/compilejob.ksh'])
361        print('compilejob.ksh has been submitted to ecgate for '
362                'installation in ' + c.ec_flexpart_root_scripts +
363                '/ECMWFDATA7.1')
364        print('You should get an email with subject flexcompile within '
365                'the next few minutes')
366
367    elif target.lower() == 'cca':
368        os.chdir('/')
369        p = subprocess.check_call(['tar', '-cvf',
370                                   ecd + '../ECMWFDATA7.1.tar',
371                                   ecd + 'python',
372                                   ecd + 'grib_templates',
373                                   ecd + 'src'])
374        try:
375            p = subprocess.check_call(['ecaccess-file-put',
376                                       ecd + '../ECMWFDATA7.1.tar',
377                                       'cca:/home/ms/' + c.ecgid + '/' +
378                                       c.ecuid + '/ECMWFDATA7.1.tar'])
379        except:
380            print('ecaccess-file-put failed! '
381                    'Probably the eccert key has expired.')
382            exit(1)
383
384        p=subprocess.check_call(['ecaccess-job-submit',
385                                '-queueName',
386                                target,
387                                ecd + 'python/compilejob.ksh'])
388        print('compilejob.ksh has been submitted to cca for installation in ' +
389              c.ec_flexpart_root_scripts + '/ECMWFDATA7.1')
390        print('You should get an email with subject flexcompile '
391                'within the next few minutes')
392
393    else:
394        print('ERROR: unknown installation target ', target)
395        print('Valid targets: ecgate, cca, local')
396
397    return
398
399
400if __name__ == "__main__":
401    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG