source: flex_extract.git/Source/Python/submit.py @ ea754d1

dev
Last change on this file since ea754d1 was ea754d1, checked in by Anne Tipka <anne.tipka@…>, 19 months ago

accidentally wrote 'ls' into first line of file. removed

  • Property mode set to 100755
File size: 9.0 KB
RevLine 
[8463d78]1#!/usr/bin/env python3
[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
[6f951ca]20#          additionally, as option without submitting the mars jobs
21#        - splitted submit function to use genshi templates for the
22#          job script and avoid code duplication
[a916e8f]23#    June 2020 - Anne Philipp
24#        - changed finale job_file to filename from config file
25#          instead of generating from the template filename
[991df6a]26#
27# @License:
[026b359]28#    (C) Copyright 2014-2020.
[6f951ca]29#    Anne Philipp, Leopold Haimberger
[991df6a]30#
[44174de]31#    SPDX-License-Identifier: CC-BY-4.0
32#
[6f951ca]33#    This work is licensed under the Creative Commons Attribution 4.0
34#    International License. To view a copy of this license, visit
35#    http://creativecommons.org/licenses/by/4.0/ or send a letter to
36#    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
[991df6a]37#*******************************************************************************
[6f951ca]38'''This script allows the user to extract meteorological fields from the ECMWF.
39
40It prepares the settings for retrieving the data from ECMWF servers and
41process the resulting files to prepare them for the use with FLEXPART or
42FLEXTRA.
43
44If it is supposed to work locally then it works through the necessary
45functions get_mars_data and prepare_flexpart. Otherwise it prepares
46a job script (korn shell) which will do the necessary work on the
47ECMWF server. This script will de submitted via the ecaccess command
48ecaccess-job-submit.
49
50This file can also be imported as a module which then contains the following
51functions:
52
53    * main - the main function of the script
54    * submit - calls mk_jobscript depending on operation mode and submits its
55    * mk_jobscript - creates the job script from a template
56
57Type: submit.py --help
58to get information about command line parameters.
59Read the documentation for usage instructions.
60'''
[efdb01a]61
[64cf353]62# ------------------------------------------------------------------------------
63# MODULES
64# ------------------------------------------------------------------------------
[a1011e7]65from __future__ import print_function
66
[efdb01a]67import os
68import sys
[f2616a3]69from datetime import datetime, timedelta
[efdb01a]70
71# software specific classes and modules from flex_extract
[54a8a01]72import _config
[0f89116]73from Mods.tools import (setup_controldata, normal_exit,
[6e16c9d]74                        submit_job_to_ecserver,
75                        submit_eventjob_to_ecserver)
[ba99230]76from Mods.get_mars_data import get_mars_data
77from Mods.prepare_flexpart import prepare_flexpart
[d727af2]78
[64cf353]79# ------------------------------------------------------------------------------
[6f951ca]80# METHODS
[64cf353]81# ------------------------------------------------------------------------------
[991df6a]82
[d69b677]83def main():
[274f9ef]84    '''Get the arguments from script call and from CONTROL file.
85    Decides from the argument "queue" if the local version
86    is done "queue=None" or the gateway version with "queue=ecgate"
87    or "queue=cca".
88
89    Parameters
90    ----------
[d69b677]91
[d727af2]92
[274f9ef]93    Return
94    ------
[64cf353]95
96    '''
[ff99eae]97
[f20af73]98    c, ppid, queue, job_template = setup_controldata()
[ff99eae]99
[efdb01a]100    # on local side
[f20af73]101    # starting from an ECMWF server this would also be the local side
[2fb99de]102    called_from_dir = os.getcwd()
[f20af73]103    if queue is None:
[64cf353]104        if c.inputdir[0] != '/':
[ff99eae]105            c.inputdir = os.path.join(called_from_dir, c.inputdir)
[64cf353]106        if c.outputdir[0] != '/':
[ff99eae]107            c.outputdir = os.path.join(called_from_dir, c.outputdir)
[54a8a01]108        get_mars_data(c)
[2fb99de]109        if c.request == 0 or c.request == 2:
[f20af73]110            prepare_flexpart(ppid, c)
[96e1533]111            exit_message = 'FLEX_EXTRACT IS DONE!'
[2fb99de]112        else:
[96e1533]113            exit_message = 'PRINTING MARS_REQUESTS DONE!'
114    # send files to ECMWF server
[d69b677]115    else:
[f20af73]116        submit(job_template, c, queue)
[47be2684]117        exit_message = 'FLEX_EXTRACT JOB SCRIPT IS SUBMITTED!'
[64cf353]118
[403cbf1]119    normal_exit(exit_message)
[96e1533]120
[64cf353]121    return
122
123def submit(jtemplate, c, queue):
[ff2a11c]124    '''Prepares the job script and submits it to the specified queue.
[274f9ef]125
126    Parameters
127    ----------
[6f951ca]128    jtemplate : str
[274f9ef]129        Job template file from sub-directory "_templates" for
130        submission to ECMWF. It contains all necessary
131        module and variable settings for the ECMWF environment as well as
132        the job call and mail report instructions.
[5f67883]133        Default is _config.TEMPFILE_JOB.
[274f9ef]134
[6f951ca]135    c : ControlFile
[274f9ef]136        Contains all the parameters of CONTROL file and
137        command line.
138
[6f951ca]139    queue : str
[274f9ef]140        Name of queue for submission to ECMWF (e.g. ecgate or cca )
141
142    Return
143    ------
144
[64cf353]145    '''
146
[d4696e0]147    if not c.oper:
[54a8a01]148    # --------- create on demand job script ------------------------------------
[a4531f1]149        if c.purefc:
[2fb99de]150            print('---- Pure forecast mode! ----')
[54a8a01]151        else:
[2fb99de]152            print('---- On-demand mode! ----')
[54a8a01]153
[ff2a11c]154        job_file = os.path.join(_config.PATH_JOBSCRIPTS,
[a916e8f]155                                _config.FILE_JOB_OD)
[54a8a01]156
[f2616a3]157        # divide time periode into specified number of job chunks
158        # to have multiple job scripts
159        if c.job_chunk:
160            start = datetime.strptime(c.start_date, '%Y%m%d')
161            end = datetime.strptime(c.end_date, '%Y%m%d')
162            chunk = timedelta(days=c.job_chunk)
[fc05fbd]163            oneday = timedelta(days=1)
[54a8a01]164
[f2616a3]165            while start <= end:
166                if (start + chunk) <= end:
[fc05fbd]167                    c.end_date = (start + chunk - oneday).strftime("%Y%m%d")
[f2616a3]168                else:
169                    c.end_date = end.strftime("%Y%m%d")
170
171                clist = c.to_list()
172                mk_jobscript(jtemplate, job_file, clist)
173
174                job_id = submit_job_to_ecserver(queue, job_file)
175                print('The job id is: ' + str(job_id.strip()))
176
177                start = start + chunk
178                c.start_date = start.strftime("%Y%m%d")
179        # submit a single job script
180        else:
181            clist = c.to_list()
182
183            mk_jobscript(jtemplate, job_file, clist)
184
185            job_id = submit_job_to_ecserver(queue, job_file)
186            print('The job id is: ' + str(job_id.strip()))
[54a8a01]187
188    else:
189    # --------- create operational job script ----------------------------------
[2fb99de]190        print('---- Operational mode! ----')
[ff2a11c]191
[2fb99de]192        job_file = os.path.join(_config.PATH_JOBSCRIPTS,
[a916e8f]193                                _config.FILE_JOB_OP)
[54a8a01]194
195        c.start_date = '${MSJ_YEAR}${MSJ_MONTH}${MSJ_DAY}'
196        c.end_date = '${MSJ_YEAR}${MSJ_MONTH}${MSJ_DAY}'
[d4696e0]197        c.basetime = '${MSJ_BASETIME}'
[54a8a01]198
[ff2a11c]199        clist = c.to_list()
[54a8a01]200
[ff2a11c]201        mk_jobscript(jtemplate, job_file, clist)
[d69b677]202
[b8037ed]203        if not c.eventid:
204            job_id = submit_job_to_ecserver(queue, job_file)
205        else:
206            job_id = submit_eventjob_to_ecserver(queue, job_file, c.eventid,
207                                                 c.eventjobname, c.ecuid)
[0540bd0]208
[f2616a3]209        print('The job id is: ' + str(job_id.strip()))
210
211    print('You should get an email per job with subject flex.hostname.pid')
[d69b677]212
[64cf353]213    return
[d69b677]214
[ff2a11c]215def mk_jobscript(jtemplate, job_file, clist):
216    '''Creates the job script from template.
217
218    Parameters
219    ----------
[6f951ca]220    jtemplate : str
[a916e8f]221        Job template file from sub-directory "Templates" for
[ff2a11c]222        submission to ECMWF. It contains all necessary
223        module and variable settings for the ECMWF environment as well as
224        the job call and mail report instructions.
[5f67883]225        Default is _config.TEMPFILE_JOB.
[ff2a11c]226
[6f951ca]227    job_file : str
[ff2a11c]228        Path to the job script file.
229
[6f951ca]230    clist : list of str
[ff2a11c]231        Contains all necessary parameters for ECMWF CONTROL file.
232
233    Return
234    ------
235
236    '''
237    from genshi.template.text import NewTextTemplate
238    from genshi.template import  TemplateLoader
239    from genshi.template.eval import UndefinedError
240
241    # load template and insert control content as list
242    try:
243        loader = TemplateLoader(_config.PATH_TEMPLATES, auto_reload=False)
244        control_template = loader.load(jtemplate,
245                                       cls=NewTextTemplate)
246
247        stream = control_template.generate(control_content=clist)
248    except UndefinedError as e:
249        print('... ERROR ' + str(e))
250
251        sys.exit('\n... error occured while trying to generate jobscript')
252    except OSError as e:
253        print('... ERROR CODE: ' + str(e.errno))
254        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
255
256        sys.exit('\n... error occured while trying to generate jobscript')
257
258    # create jobscript file
259    try:
260        with open(job_file, 'w') as f:
261            f.write(stream.render('text'))
262    except OSError as e:
263        print('... ERROR CODE: ' + str(e.errno))
264        print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
265
266        sys.exit('\n... error occured while trying to write ' + job_file)
267
268    return
269
[f2616a3]270
[d69b677]271if __name__ == "__main__":
272    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG