source: flex_extract.git/source/python/submit.py @ 0629ba8

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

removed print line

  • Property mode set to 100755
File size: 8.1 KB
RevLine 
[d69b677]1#!/usr/bin/env python
[64cf353]2# -*- coding: utf-8 -*-
[991df6a]3#*******************************************************************************
4# @Author: Anne Fouilloux (University of Oslo)
5#
6# @Date: October 2014
7#
8# @Change History:
9#
10#    November 2015 - Leopold Haimberger (University of Vienna):
11#        - job submission on ecgate and cca
12#        - job templates suitable for twice daily operational dissemination
13#
14#    February 2018 - Anne Philipp (University of Vienna):
15#        - applied PEP8 style guide
16#        - added documentation
17#        - minor changes in programming style (for consistence)
[2fb99de]18#        - changed path names to variables from config file
19#        - added option for writing mars requests to extra file
20#          additionally,as option without submitting the mars jobs
[991df6a]21#
22# @License:
23#    (C) Copyright 2014-2018.
24#
25#    This software is licensed under the terms of the Apache Licence Version 2.0
26#    which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
27#
28# @Program Functionality:
29#    This program is the main program of flex_extract and controls the
30#    program flow.
31#    If it is supposed to work locally then it works through the necessary
[ff99eae]32#    functions get_mars_data and prepareFlexpart. Otherwise it prepares
[991df6a]33#    a shell job script which will do the necessary work on the
34#    ECMWF server and is submitted via ecaccess-job-submit.
35#
36# @Program Content:
37#    - main
38#    - submit
39#
40#*******************************************************************************
[efdb01a]41
[64cf353]42# ------------------------------------------------------------------------------
43# MODULES
44# ------------------------------------------------------------------------------
[efdb01a]45import os
46import sys
[d69b677]47import subprocess
48import inspect
[54a8a01]49import collections
[f2616a3]50from datetime import datetime, timedelta
[efdb01a]51
52# software specific classes and modules from flex_extract
[54a8a01]53import _config
[9aefaad]54from mods.tools import (normal_exit, get_cmdline_args,
[25b14be]55                        submit_job_to_ecserver, read_ecenv)
56from mods.get_mars_data import get_mars_data
57from mods.prepare_flexpart import prepare_flexpart
58from classes.ControlFile import ControlFile
[991df6a]59
[64cf353]60# ------------------------------------------------------------------------------
61# FUNCTIONS
62# ------------------------------------------------------------------------------
[991df6a]63
[d69b677]64def main():
[274f9ef]65    '''Get the arguments from script call and from CONTROL file.
66    Decides from the argument "queue" if the local version
67    is done "queue=None" or the gateway version with "queue=ecgate"
68    or "queue=cca".
69
70    Parameters
71    ----------
[d69b677]72
[274f9ef]73    Return
74    ------
[64cf353]75
76    '''
[ff99eae]77
[9aefaad]78    args = get_cmdline_args()
[4971f63]79    c = ControlFile(args.controlfile)
[2fb99de]80
81    env_parameter = read_ecenv(_config.PATH_ECMWF_ENV)
[54a8a01]82    c.assign_args_to_control(args)
83    c.assign_envs_to_control(env_parameter)
[2fb99de]84    c.check_conditions(args.queue)
[ff99eae]85
[efdb01a]86    # on local side
[2fb99de]87    # on ECMWF server this would also be the local side
88    called_from_dir = os.getcwd()
[295ff45]89    if args.queue is None:
[64cf353]90        if c.inputdir[0] != '/':
[ff99eae]91            c.inputdir = os.path.join(called_from_dir, c.inputdir)
[64cf353]92        if c.outputdir[0] != '/':
[ff99eae]93            c.outputdir = os.path.join(called_from_dir, c.outputdir)
[54a8a01]94        get_mars_data(c)
[2fb99de]95        if c.request == 0 or c.request == 2:
96            prepare_flexpart(args.ppid, c)
[96e1533]97            exit_message = 'FLEX_EXTRACT IS DONE!'
[2fb99de]98        else:
[96e1533]99            exit_message = 'PRINTING MARS_REQUESTS DONE!'
100    # send files to ECMWF server
[d69b677]101    else:
[64cf353]102        submit(args.job_template, c, args.queue)
[e0e99a5]103        exit_message = 'FLEX_EXTRACT JOB SCRIPT IS SUBMITED!'
[64cf353]104
[403cbf1]105    normal_exit(exit_message)
[96e1533]106
[64cf353]107    return
108
109def submit(jtemplate, c, queue):
[ff2a11c]110    '''Prepares the job script and submits it to the specified queue.
[274f9ef]111
112    Parameters
113    ----------
114    jtemplate : :obj:`string`
115        Job template file from sub-directory "_templates" for
116        submission to ECMWF. It contains all necessary
117        module and variable settings for the ECMWF environment as well as
118        the job call and mail report instructions.
119        Default is "job.temp".
120
121    c : :obj:`ControlFile`
122        Contains all the parameters of CONTROL file and
123        command line.
124
125    queue : :obj:`string`
126        Name of queue for submission to ECMWF (e.g. ecgate or cca )
127
128    Return
129    ------
130
[64cf353]131    '''
132
[54a8a01]133    if not c.basetime:
134    # --------- create on demand job script ------------------------------------
[a4531f1]135        if c.purefc:
[2fb99de]136            print('---- Pure forecast mode! ----')
[54a8a01]137        else:
[2fb99de]138            print('---- On-demand mode! ----')
[54a8a01]139
[ff2a11c]140        job_file = os.path.join(_config.PATH_JOBSCRIPTS,
141                                jtemplate[:-5] + '.ksh')
[54a8a01]142
[f2616a3]143        # divide time periode into specified number of job chunks
144        # to have multiple job scripts
145        if c.job_chunk:
146            start = datetime.strptime(c.start_date, '%Y%m%d')
147            end = datetime.strptime(c.end_date, '%Y%m%d')
148            chunk = timedelta(days=c.job_chunk)
[54a8a01]149
[f2616a3]150            while start <= end:
151                if (start + chunk) <= end:
152                    c.end_date = (start + chunk).strftime("%Y%m%d")
153                else:
154                    c.end_date = end.strftime("%Y%m%d")
155
156                clist = c.to_list()
157
158                mk_jobscript(jtemplate, job_file, clist)
159
160                job_id = submit_job_to_ecserver(queue, job_file)
161                print('The job id is: ' + str(job_id.strip()))
162
163                start = start + chunk
164                c.start_date = start.strftime("%Y%m%d")
165        # submit a single job script
166        else:
167            clist = c.to_list()
168
169            mk_jobscript(jtemplate, job_file, clist)
170
171            job_id = submit_job_to_ecserver(queue, job_file)
172            print('The job id is: ' + str(job_id.strip()))
[54a8a01]173
174    else:
175    # --------- create operational job script ----------------------------------
[2fb99de]176        print('---- Operational mode! ----')
[ff2a11c]177
[2fb99de]178        job_file = os.path.join(_config.PATH_JOBSCRIPTS,
179                                jtemplate[:-5] + 'oper.ksh')
[54a8a01]180
181        c.start_date = '${MSJ_YEAR}${MSJ_MONTH}${MSJ_DAY}'
182        c.end_date = '${MSJ_YEAR}${MSJ_MONTH}${MSJ_DAY}'
183        c.base_time = '${MSJ_BASETIME}'
[ff2a11c]184        if c.maxstep > 24:
[54a8a01]185            c.time = '${MSJ_BASETIME} {MSJ_BASETIME}'
186
[ff2a11c]187        clist = c.to_list()
[54a8a01]188
[ff2a11c]189        mk_jobscript(jtemplate, job_file, clist)
[d69b677]190
[f2616a3]191        job_id = submit_job_to_ecserver(queue, job_file)
192        print('The job id is: ' + str(job_id.strip()))
193
194    print('You should get an email per job with subject flex.hostname.pid')
[d69b677]195
[64cf353]196    return
[d69b677]197
[ff2a11c]198def mk_jobscript(jtemplate, job_file, clist):
199    '''Creates the job script from template.
200
201    Parameters
202    ----------
203    jtemplate : :obj:`string`
204        Job template file from sub-directory "_templates" for
205        submission to ECMWF. It contains all necessary
206        module and variable settings for the ECMWF environment as well as
207        the job call and mail report instructions.
208        Default is "job.temp".
209
210    job_file : :obj:`string`
211        Path to the job script file.
212
213    clist : :obj:`list` of :obj:`string`
214        Contains all necessary parameters for ECMWF CONTROL file.
215
216    Return
217    ------
218
219    '''
220    from genshi.template.text import NewTextTemplate
221    from genshi.template import  TemplateLoader
222    from genshi.template.eval import UndefinedError
223
224    # load template and insert control content as list
225    try:
226        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
227        control_template = loader.load(jtemplate,
228                                       cls=NewTextTemplate)
229
230        stream = control_template.generate(control_content=clist)
231    except UndefinedError as e:
232        print('... ERROR ' + str(e))
233
234        sys.exit('\n... error occured while trying to generate jobscript')
235    except OSError as e:
236        print('... ERROR CODE: ' + str(e.errno))
237        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
238
239        sys.exit('\n... error occured while trying to generate jobscript')
240
241    # create jobscript file
242    try:
243        with open(job_file, 'w') as f:
244            f.write(stream.render('text'))
245    except OSError as e:
246        print('... ERROR CODE: ' + str(e.errno))
247        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
248
249        sys.exit('\n... error occured while trying to write ' + job_file)
250
251    return
252
[f2616a3]253
[d69b677]254if __name__ == "__main__":
255    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG