vortex-nwp 2.0.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. vortex/__init__.py +135 -0
  2. vortex/algo/__init__.py +12 -0
  3. vortex/algo/components.py +2136 -0
  4. vortex/algo/mpitools.py +1648 -0
  5. vortex/algo/mpitools_templates/envelope_wrapper_default.tpl +27 -0
  6. vortex/algo/mpitools_templates/envelope_wrapper_mpiauto.tpl +29 -0
  7. vortex/algo/mpitools_templates/wrapstd_wrapper_default.tpl +18 -0
  8. vortex/algo/serversynctools.py +170 -0
  9. vortex/config.py +115 -0
  10. vortex/data/__init__.py +13 -0
  11. vortex/data/abstractstores.py +1572 -0
  12. vortex/data/containers.py +780 -0
  13. vortex/data/contents.py +596 -0
  14. vortex/data/executables.py +284 -0
  15. vortex/data/flow.py +113 -0
  16. vortex/data/geometries.ini +2689 -0
  17. vortex/data/geometries.py +703 -0
  18. vortex/data/handlers.py +1021 -0
  19. vortex/data/outflow.py +67 -0
  20. vortex/data/providers.py +465 -0
  21. vortex/data/resources.py +201 -0
  22. vortex/data/stores.py +1271 -0
  23. vortex/gloves.py +282 -0
  24. vortex/layout/__init__.py +27 -0
  25. vortex/layout/appconf.py +109 -0
  26. vortex/layout/contexts.py +511 -0
  27. vortex/layout/dataflow.py +1069 -0
  28. vortex/layout/jobs.py +1276 -0
  29. vortex/layout/monitor.py +833 -0
  30. vortex/layout/nodes.py +1424 -0
  31. vortex/layout/subjobs.py +464 -0
  32. vortex/nwp/__init__.py +11 -0
  33. vortex/nwp/algo/__init__.py +12 -0
  34. vortex/nwp/algo/assim.py +483 -0
  35. vortex/nwp/algo/clim.py +920 -0
  36. vortex/nwp/algo/coupling.py +609 -0
  37. vortex/nwp/algo/eda.py +632 -0
  38. vortex/nwp/algo/eps.py +613 -0
  39. vortex/nwp/algo/forecasts.py +745 -0
  40. vortex/nwp/algo/fpserver.py +927 -0
  41. vortex/nwp/algo/ifsnaming.py +403 -0
  42. vortex/nwp/algo/ifsroot.py +311 -0
  43. vortex/nwp/algo/monitoring.py +202 -0
  44. vortex/nwp/algo/mpitools.py +554 -0
  45. vortex/nwp/algo/odbtools.py +974 -0
  46. vortex/nwp/algo/oopsroot.py +735 -0
  47. vortex/nwp/algo/oopstests.py +186 -0
  48. vortex/nwp/algo/request.py +579 -0
  49. vortex/nwp/algo/stdpost.py +1285 -0
  50. vortex/nwp/data/__init__.py +12 -0
  51. vortex/nwp/data/assim.py +392 -0
  52. vortex/nwp/data/boundaries.py +261 -0
  53. vortex/nwp/data/climfiles.py +539 -0
  54. vortex/nwp/data/configfiles.py +149 -0
  55. vortex/nwp/data/consts.py +929 -0
  56. vortex/nwp/data/ctpini.py +133 -0
  57. vortex/nwp/data/diagnostics.py +181 -0
  58. vortex/nwp/data/eda.py +148 -0
  59. vortex/nwp/data/eps.py +383 -0
  60. vortex/nwp/data/executables.py +1039 -0
  61. vortex/nwp/data/fields.py +96 -0
  62. vortex/nwp/data/gridfiles.py +308 -0
  63. vortex/nwp/data/logs.py +551 -0
  64. vortex/nwp/data/modelstates.py +334 -0
  65. vortex/nwp/data/monitoring.py +220 -0
  66. vortex/nwp/data/namelists.py +644 -0
  67. vortex/nwp/data/obs.py +748 -0
  68. vortex/nwp/data/oopsexec.py +72 -0
  69. vortex/nwp/data/providers.py +182 -0
  70. vortex/nwp/data/query.py +217 -0
  71. vortex/nwp/data/stores.py +147 -0
  72. vortex/nwp/data/surfex.py +338 -0
  73. vortex/nwp/syntax/__init__.py +9 -0
  74. vortex/nwp/syntax/stdattrs.py +375 -0
  75. vortex/nwp/tools/__init__.py +10 -0
  76. vortex/nwp/tools/addons.py +35 -0
  77. vortex/nwp/tools/agt.py +55 -0
  78. vortex/nwp/tools/bdap.py +48 -0
  79. vortex/nwp/tools/bdcp.py +38 -0
  80. vortex/nwp/tools/bdm.py +21 -0
  81. vortex/nwp/tools/bdmp.py +49 -0
  82. vortex/nwp/tools/conftools.py +1311 -0
  83. vortex/nwp/tools/drhook.py +62 -0
  84. vortex/nwp/tools/grib.py +268 -0
  85. vortex/nwp/tools/gribdiff.py +99 -0
  86. vortex/nwp/tools/ifstools.py +163 -0
  87. vortex/nwp/tools/igastuff.py +249 -0
  88. vortex/nwp/tools/mars.py +56 -0
  89. vortex/nwp/tools/odb.py +548 -0
  90. vortex/nwp/tools/partitioning.py +234 -0
  91. vortex/nwp/tools/satrad.py +56 -0
  92. vortex/nwp/util/__init__.py +6 -0
  93. vortex/nwp/util/async.py +184 -0
  94. vortex/nwp/util/beacon.py +40 -0
  95. vortex/nwp/util/diffpygram.py +359 -0
  96. vortex/nwp/util/ens.py +198 -0
  97. vortex/nwp/util/hooks.py +128 -0
  98. vortex/nwp/util/taskdeco.py +81 -0
  99. vortex/nwp/util/usepygram.py +591 -0
  100. vortex/nwp/util/usetnt.py +87 -0
  101. vortex/proxy.py +6 -0
  102. vortex/sessions.py +341 -0
  103. vortex/syntax/__init__.py +9 -0
  104. vortex/syntax/stdattrs.py +628 -0
  105. vortex/syntax/stddeco.py +176 -0
  106. vortex/toolbox.py +982 -0
  107. vortex/tools/__init__.py +11 -0
  108. vortex/tools/actions.py +457 -0
  109. vortex/tools/addons.py +297 -0
  110. vortex/tools/arm.py +76 -0
  111. vortex/tools/compression.py +322 -0
  112. vortex/tools/date.py +20 -0
  113. vortex/tools/ddhpack.py +10 -0
  114. vortex/tools/delayedactions.py +672 -0
  115. vortex/tools/env.py +513 -0
  116. vortex/tools/folder.py +663 -0
  117. vortex/tools/grib.py +559 -0
  118. vortex/tools/lfi.py +746 -0
  119. vortex/tools/listings.py +354 -0
  120. vortex/tools/names.py +575 -0
  121. vortex/tools/net.py +1790 -0
  122. vortex/tools/odb.py +10 -0
  123. vortex/tools/parallelism.py +336 -0
  124. vortex/tools/prestaging.py +186 -0
  125. vortex/tools/rawfiles.py +10 -0
  126. vortex/tools/schedulers.py +413 -0
  127. vortex/tools/services.py +871 -0
  128. vortex/tools/storage.py +1061 -0
  129. vortex/tools/surfex.py +61 -0
  130. vortex/tools/systems.py +3396 -0
  131. vortex/tools/targets.py +384 -0
  132. vortex/util/__init__.py +9 -0
  133. vortex/util/config.py +1071 -0
  134. vortex/util/empty.py +24 -0
  135. vortex/util/helpers.py +184 -0
  136. vortex/util/introspection.py +63 -0
  137. vortex/util/iosponge.py +76 -0
  138. vortex/util/roles.py +51 -0
  139. vortex/util/storefunctions.py +103 -0
  140. vortex/util/structs.py +26 -0
  141. vortex/util/worker.py +150 -0
  142. vortex_nwp-2.0.0b1.dist-info/LICENSE +517 -0
  143. vortex_nwp-2.0.0b1.dist-info/METADATA +50 -0
  144. vortex_nwp-2.0.0b1.dist-info/RECORD +146 -0
  145. vortex_nwp-2.0.0b1.dist-info/WHEEL +5 -0
  146. vortex_nwp-2.0.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,579 @@
1
+ """
2
+ A set of AlgoComponents interrogating various databases.
3
+ """
4
+
5
+ import copy
6
+
7
+ from bronx.fancies import loggers
8
+ from bronx.stdtypes.date import Time
9
+ import footprints
10
+
11
+ from vortex.algo.components import AlgoComponent, AlgoComponentDecoMixin, Expresso, BlindRun
12
+ from vortex.algo.components import algo_component_deco_mixin_autodoc
13
+ from vortex.syntax.stdattrs import a_date
14
+ from vortex.tools.systems import ExecutionError
15
+ from ..tools.bdap import BDAPrequest_actual_command, BDAPGetError, BDAPRequestConfigurationError
16
+ from ..tools.bdmp import BDMPrequest_actual_command, BDMPGetError
17
+ from ..tools.bdcp import BDCPrequest_actual_command, BDCPGetError
18
+ from ..tools.bdm import BDMGetError, BDMRequestConfigurationError, BDMError
19
+ from ..tools.mars import MarsGetError, callMarsExtract, findMarsExtractCommand
20
+ from ..data.obs import ObsMapContent
21
+
22
+ #: No automatic export
23
+ __all__ = []
24
+
25
+ logger = loggers.getLogger(__name__)
26
+
27
+
28
+ class GetBDAPResource(AlgoComponent):
29
+ """Algo component to get BDAP resources considering a BDAP query file."""
30
+
31
+ _footprint = dict(
32
+ info = 'Algo component to get BDAP files.',
33
+ attr = dict(
34
+ kind = dict(
35
+ values = ['get_bdap'],
36
+ ),
37
+ date = a_date,
38
+ target_bdap = dict(
39
+ default = 'OPER',
40
+ optional = True,
41
+ values = ['OPER', 'INTE'],
42
+ ),
43
+ terms = dict(
44
+ info = "A forecast term or a list of terms (rangex will be used to expand the string)",
45
+ alias = ('term', )
46
+ ),
47
+ command = dict(
48
+ default = 'dap3',
49
+ optional =True,
50
+ values = ['dap3', 'dap3_dev'],
51
+ ),
52
+ )
53
+ )
54
+
55
+ def execute_single(self, rh, opts):
56
+ """
57
+ Launch the BDAP request(s).
58
+ The results of each request are stored in a directory local_directory to avoid
59
+ files to be overwritten.
60
+ """
61
+
62
+ # Determine the target BDAP
63
+ int_bdap = self.target_bdap == 'INTE'
64
+
65
+ # Look for the input queries
66
+ input_queries = self.context.sequence.effective_inputs(
67
+ role='Query',
68
+ kind='bdap_query',
69
+ )
70
+
71
+ rc_all = True
72
+
73
+ for input_query in input_queries:
74
+ for term in [Time(t) for t in footprints.util.rangex(self.terms)]:
75
+
76
+ # Launch each input queries in a dedicated file
77
+ # (to check that the files do not overwrite each other)
78
+ query_file = input_query.rh.container.abspath
79
+ local_directory = '_'.join([query_file, self.date.ymdhms, term.fmtraw])
80
+
81
+ with self.system.cdcontext(local_directory, create=True):
82
+ # Determine the command to be launched
83
+ actual_command = BDAPrequest_actual_command(command=self.command,
84
+ date=self.date,
85
+ term=term,
86
+ query=query_file,
87
+ int_extraenv=int_bdap)
88
+ logger.info(' '.join(['BDAP extract command:', actual_command]))
89
+ logger.info('The %s directive file contains:', query_file)
90
+ self.system.cat(query_file, output=False)
91
+ # Launch the BDAP request
92
+ rc = self.system.spawn([actual_command, ], shell=True, output=False, fatal=False)
93
+
94
+ if not rc:
95
+ logger.exception('Problem during the BDAP request of %s.', query_file)
96
+ if self.system.path.isfile('DIAG_BDAP'):
97
+ raise BDAPRequestConfigurationError
98
+ else:
99
+ raise BDAPGetError
100
+
101
+ rc_all = rc_all and rc
102
+
103
+ if not rc_all:
104
+ logger.exception('Problem during the BDAP request.')
105
+
106
+ return rc_all
107
+
108
+
109
+ class GetBDMPResource(AlgoComponent):
110
+ """Algo component to get BDMP resources considering a BDMP query file."""
111
+
112
+ _footprint = dict(
113
+ info = 'Algo component to get BDMP files.',
114
+ attr = dict(
115
+ kind = dict(
116
+ values = ['get_bdmp'],
117
+ ),
118
+ target_bdmp = dict(
119
+ default = 'OPER',
120
+ optional = True,
121
+ values = ['OPER', 'INTE', 'ARCH'],
122
+ ),
123
+ command = dict(
124
+ default = 'bdmp_lecture',
125
+ optional =True,
126
+ values = ['bdmp_lecture', 'bdmp_lecture_pg', 'bdmp_lecture_ora'],
127
+ ),
128
+ )
129
+ )
130
+
131
+ def execute_single(self, rh, opts):
132
+ """
133
+ Launch the BDMP request(s).
134
+ The results of each request are stored in a directory local_directory to avoid
135
+ files to be overwritten.
136
+ """
137
+
138
+ # Look for the input queries
139
+ input_queries = self.context.sequence.effective_inputs(
140
+ role='Query',
141
+ kind='bdmp_query',
142
+ )
143
+
144
+ rc_all = True
145
+
146
+ for input_query in input_queries:
147
+
148
+ # Get information on the query file
149
+ query_file = input_query.rh.container.abspath
150
+ logger.info('The %s directive file contains:', query_file)
151
+ self.system.cat(query_file, output=False)
152
+
153
+ # Construct the name of the temporary directory
154
+ local_directory = '_'.join([query_file, 'extract'])
155
+
156
+ # Determine the command to be launched
157
+ actual_command = BDMPrequest_actual_command(command=self.command,
158
+ query=query_file,
159
+ target_bdmp=self.target_bdmp)
160
+ logger.info(' '.join(['BDMP extract command:', actual_command]))
161
+
162
+ # Launch the BDMP request
163
+ with self.system.cdcontext(local_directory, create=True):
164
+ rc = self.system.spawn([actual_command, ], shell=True, output=False, fatal=False)
165
+
166
+ if not rc:
167
+ logger.exception('Problem during the BDMP request of %s.', query_file)
168
+ raise BDMPGetError
169
+
170
+ rc_all = rc_all and rc
171
+
172
+ if not rc_all:
173
+ logger.exception('Problem during the BDMP request.')
174
+
175
+ return rc_all
176
+
177
+
178
+ class GetBDCPResource(AlgoComponent):
179
+ """Algo component to get BDCP resources considering a BDCP query file."""
180
+
181
+ _footprint = dict(
182
+ info = 'Algo component to get BDCP files.',
183
+ attr = dict(
184
+ kind = dict(
185
+ values = ['get_bdcp'],
186
+ ),
187
+ target_bdcp = dict(
188
+ default = 'OPER',
189
+ optional = True,
190
+ values = ['OPER'],
191
+ ),
192
+ command = dict(
193
+ default = 'extraction_directives',
194
+ optional =True,
195
+ values = ['extraction_directives'],
196
+ ),
197
+ )
198
+ )
199
+
200
+ def execute_single(self, rh, opts):
201
+ """
202
+ Launch the BDCP request(s).
203
+ The name of the output and log files are fixed by the AlgoComponent
204
+ according to the attributes of each request.
205
+ """
206
+
207
+ # Look for the input queries
208
+ input_queries = self.context.sequence.effective_inputs(
209
+ role='Query',
210
+ kind='bdcp_query',
211
+ )
212
+
213
+ rc_all = True
214
+
215
+ for input_query in input_queries:
216
+
217
+ # Get information on the query file
218
+ query_file = input_query.rh.container.abspath
219
+ logger.info('The %s directive file contains:', query_file)
220
+ self.system.cat(query_file, output=False)
221
+
222
+ # Construct the name of the output and log files
223
+ local_directory = '_'.join([query_file, 'extract'])
224
+ output_file = 'extract.out'
225
+ output_log = 'extract.out.diag'
226
+
227
+ # Determine the command to be launched
228
+ actual_command = BDCPrequest_actual_command(command=self.command,
229
+ query_file=query_file,
230
+ output_file=output_file)
231
+ logger.info(' '.join(['BDMP extract command:', actual_command]))
232
+
233
+ # Launch the BDCP request
234
+ with self.system.cdcontext(local_directory, create=True):
235
+ rc = self.system.spawn([actual_command, ], shell=True, output=False, fatal=False)
236
+ # Cat the log file
237
+ logger.info('Content of the log file:')
238
+ self.system.cat(output_log, output=False)
239
+
240
+ if not rc:
241
+ logger.exception('Problem during the BDCP request of %s.', query_file)
242
+ raise BDCPGetError
243
+
244
+ rc_all = rc_all and rc
245
+
246
+ if not rc_all:
247
+ logger.exception('Problem during the BDCP request.')
248
+
249
+ return rc_all
250
+
251
+
252
+ @algo_component_deco_mixin_autodoc
253
+ class _GetBDMDecoMixin(AlgoComponentDecoMixin):
254
+ """Class variables and methods usefull for BDM extractions."""
255
+
256
+ _MIXIN_EXTRA_FOOTPRINTS = [footprints.Footprint(
257
+ attr=dict(
258
+ date=a_date,
259
+ pwd_file=dict(
260
+ default='/usr/local/sopra/neons_pwd',
261
+ values=['/usr/local/sopra/neons_pwd'],
262
+ optional=True,
263
+ ),
264
+ fatal=dict(
265
+ type=bool,
266
+ default=False,
267
+ values=[True, False],
268
+ optional=True,
269
+ ),
270
+ defaut_queryname=dict(
271
+ default='vortexdefault_query_name',
272
+ doc_visibility=footprints.doc.visibility.GURU,
273
+ optional=True,
274
+ )
275
+ )
276
+ )]
277
+
278
+ def _verbose_env_export(self, varname, value):
279
+ self.env.setvar(varname, value)
280
+ logger.info('Setting environment variable %s = %s', varname, str(value))
281
+
282
+ def _prepare_commons(self, rh, opts):
283
+ """
284
+ Prepare the launch of the script
285
+ """
286
+ # Some exports to be done
287
+ self._verbose_env_export('PWD_FILE', self.pwd_file)
288
+ self._verbose_env_export('DMT_DATE_PIVOT', self.date.ymdhms)
289
+
290
+ _MIXIN_PREPARE_HOOKS = (_prepare_commons, )
291
+
292
+ def _spawn_command_options_extend(self, prev):
293
+ prev['query'] = self.defaut_queryname
294
+ return prev
295
+
296
+ _MIXIN_CLI_OPTS_EXTEND = (_spawn_command_options_extend, )
297
+
298
+ def _execute_commons(self, rh, opts):
299
+ """Launch the BDM request(s).
300
+
301
+ The results of each request are stored in a directory local_directory
302
+ to avoid files overwritten by others
303
+ """
304
+
305
+ # Look for the input queries
306
+ input_queries = self._get_input_queries()
307
+ # Initialize some variables
308
+ rc_all = True
309
+
310
+ # Loop over the query files
311
+ for input_query in input_queries:
312
+ # Find out the temporary directory name
313
+ query_filename = input_query.rh.container.filename
314
+ query_abspath = input_query.rh.container.abspath
315
+ loc_dir = self._local_directory(query_filename)
316
+ # Launch an execution for each input queries in a dedicated directory
317
+ # (to check that the files do not overwrite one another)
318
+ with self.system.cdcontext(loc_dir, create=True):
319
+ # Make the links needed
320
+ self.system.symlink(query_abspath,
321
+ self.defaut_queryname)
322
+ # Cat the query content
323
+ logger.info('The %s directive file contains:', query_filename)
324
+ self.system.cat(self.defaut_queryname, output=False)
325
+ # Launch the BDM request and catch
326
+ try:
327
+ super(self.mixin_execute_companion(), self).execute(rh, opts)
328
+ except ExecutionError:
329
+ rc_all = False
330
+ logger.error('Problem during the BDM request of %s.', query_filename)
331
+ if self.fatal:
332
+ raise BDMGetError('Problem during the BDM request of {}.'.format(query_filename))
333
+ # Delete the links
334
+ self.system.rm(self.defaut_queryname)
335
+ self.system.dir(output=False, fatal=False)
336
+
337
+ if not rc_all:
338
+ logger.error('At least one of the BDM request failed. Please check the logs above.')
339
+
340
+ _MIXIN_EXECUTE_OVERWRITE = _execute_commons
341
+
342
+ def _postfix_commons(self, rh, opts):
343
+ """Concatenate the batormap from the different tasks and check if there is no duplicated entries."""
344
+
345
+ # BATORMAP concatenation
346
+ # Determine the name of the batormap produced by the execution in the different directories
347
+ input_queries = self._get_input_queries()
348
+ local_dir = [self._local_directory(input_query.rh.container.filename)
349
+ for input_query in input_queries]
350
+ temp_files = []
351
+ for directory in local_dir:
352
+ glob_files = self.system.glob('/'.join([directory, '*batormap*']))
353
+ for element in glob_files:
354
+ temp_files.append(element)
355
+ # Initialize the resulting batormap file
356
+ obsmap_filename = '_'.join(['OBSMAP', self.date.ymdhms])
357
+ content = []
358
+ # Check if a batormap is already present in the directory (from previous extract)
359
+ if self.system.path.isfile(obsmap_filename):
360
+ temp_files.append(obsmap_filename)
361
+ # Loop over the directories to concatenate the batormap
362
+ for a_file in temp_files:
363
+ file_container = footprints.proxy.container(local=a_file)
364
+ content_tmp = ObsMapContent()
365
+ content_tmp.slurp(file_container)
366
+ content.append(content_tmp)
367
+ out_content = ObsMapContent()
368
+ out_content.merge(unique=True, *content)
369
+ out_content.sort()
370
+ out_container = footprints.proxy.container(local=obsmap_filename)
371
+ out_content.rewrite(out_container)
372
+ out_container.close()
373
+ logger.info('Content of the global batormap:')
374
+ self.system.cat(out_container.filename, output=False)
375
+
376
+ # Listing concatenation
377
+ # Initialize the resulting file
378
+ listing_filename = 'OULOUTPUT'
379
+ # Determine the name of the listing files produced by the execution
380
+ listing_files = []
381
+ for directory in local_dir:
382
+ glob_files = self.system.glob('/'.join([directory, listing_filename]))
383
+ for element in glob_files:
384
+ listing_files.append(element)
385
+ # Check if a listing is already present and has to be merged with the other
386
+ if self.system.path.isfile(listing_filename):
387
+ temp_listing = '.'.join([listing_filename, 'tmp'])
388
+ self.system.mv(listing_filename, temp_listing)
389
+ listing_files.append(temp_listing)
390
+ # Concatenate the listings
391
+ self.system.cat(*listing_files, output=listing_filename)
392
+
393
+ _MIXIN_POSTFIX_HOOKS = (_postfix_commons, )
394
+
395
+
396
+ class GetBDMBufr(Expresso, _GetBDMDecoMixin):
397
+ """Algo component to get BDM resources considering a BDM query file."""
398
+
399
+ _footprint = dict(
400
+ info = 'Algo component to get BDM BUFR.',
401
+ attr = dict(
402
+ kind = dict(
403
+ values = ['get_bdm_bufr'],
404
+ ),
405
+ db_file_bdm = dict(
406
+ default = '/usr/local/sopra/neons_db_bdm',
407
+ values = ['/usr/local/sopra/neons_db_bdm',
408
+ '/usr/local/sopra/neons_db_bdm.archi',
409
+ '/usr/local/sopra/neons_db_bdm.intgr'],
410
+ optional = True,
411
+ ),
412
+ extra_env_opt = dict(
413
+ values = ['RECHERCHE', 'OPERATIONNEL', 'OPER'],
414
+ default = 'OPER',
415
+ optional = True,
416
+ ),
417
+ shlib_path = dict(
418
+ default = '/usr/local/lib',
419
+ optional = True,
420
+ ),
421
+ interpreter = dict(
422
+ default = 'awk',
423
+ values = ['awk'],
424
+ optional = True,
425
+ ),
426
+ )
427
+ )
428
+
429
+ def _local_directory(self, query_filename):
430
+ return '_'.join(['BUFR', query_filename, self.date.ymdhms])
431
+
432
+ def _get_input_queries(self):
433
+ """Returns the list of queries to process."""
434
+ return self.context.sequence.effective_inputs(
435
+ role='Query',
436
+ kind='bdm_query',
437
+ )
438
+
439
+ def prepare(self, rh, opts):
440
+ """
441
+ Prepare the launch of the script
442
+ """
443
+ # Do the standard pre-treatment
444
+ super().prepare(rh, opts)
445
+
446
+ # Some exports to be done
447
+ self._verbose_env_export('EXTR_ENV', self.extra_env_opt)
448
+ self._verbose_env_export('DB_FILE_BDM', self.db_file_bdm)
449
+ self._verbose_env_export('SHLIB_PATH', ':'.join(['$SHLIB_PATH', self.shlib_path]))
450
+
451
+ # Check if query files are present
452
+ input_queries = self._get_input_queries()
453
+ if len(input_queries) < 1:
454
+ logger.exception('No query file found for the BDM extraction. Stop.')
455
+ raise BDMRequestConfigurationError('No query file found for the BDM extraction')
456
+
457
+
458
+ class GetBDMOulan(BlindRun, _GetBDMDecoMixin):
459
+ """Algo component to get BDM files using Oulan."""
460
+
461
+ _footprint = dict(
462
+ info = "Algo component to get BDM files using Oulan.",
463
+ attr = dict(
464
+ kind = dict(
465
+ values = ['get_bdm_oulan'],
466
+ ),
467
+ db_file = dict(
468
+ default = '/usr/local/sopra/neons_db',
469
+ values = ['/usr/local/sopra/neons_db'],
470
+ optional = True,
471
+ ),
472
+ defaut_queryname = dict(
473
+ default = 'NAMELIST',
474
+ ),
475
+ )
476
+ )
477
+
478
+ def _local_directory(self, query_filename):
479
+ return '_'.join(['Oulan', query_filename, self.date.ymdhms])
480
+
481
+ def _get_input_queries(self):
482
+ """Returns the list of namelists to process."""
483
+ return self.context.sequence.effective_inputs(
484
+ role='NamelistOulan',
485
+ kind='namutil',
486
+ )
487
+
488
+ def prepare(self, rh, opts):
489
+ """Prepare the execution of the Oulan extraction binary."""
490
+ # Do the standard pre-treatment
491
+ super().prepare(rh, opts)
492
+
493
+ # Export additional variables
494
+ self._verbose_env_export('DB_FILE', self.db_file)
495
+
496
+ # Check if namelists are present
497
+ input_namelists = self._get_input_queries()
498
+ if len(input_namelists) < 1:
499
+ logger.error('No Oulan namelist found. Stop.')
500
+ raise BDMError('No Oulan namelist found.')
501
+
502
+
503
+ class GetMarsResource(AlgoComponent):
504
+ """AlgoComponent to get Mars resources using a Mars query file"""
505
+
506
+ _footprint = dict(
507
+ info = 'AlgoComponent to get a Mars resource',
508
+ attr = dict(
509
+ kind = dict(
510
+ values = ['get_mars', ]
511
+ ),
512
+ date = a_date,
513
+ substitutions = dict(
514
+ info = "A dictionary of values to be substituted",
515
+ type = footprints.stdtypes.FPDict,
516
+ default = footprints.stdtypes.FPDict(),
517
+ optional = True
518
+ ),
519
+ command = dict(
520
+ optional = True
521
+ ),
522
+ fatal = dict(
523
+ type = bool,
524
+ default = True,
525
+ optional = True
526
+ )
527
+ )
528
+ )
529
+
530
+ def execute(self, rh, opts):
531
+ """
532
+ Launch the Mars request(s).
533
+ The results of each requests are stored in a directory to avoid
534
+ files to be overwritten.
535
+ """
536
+ # Look for input queries
537
+ input_queries = self.context.sequence.effective_inputs(
538
+ role='Query',
539
+ kind='mars_query',
540
+ )
541
+ if len(input_queries) < 1:
542
+ logger.exception('No query file found for the Mars extraction. Stop.')
543
+ raise MarsGetError('No query file found for the Mars extraction')
544
+
545
+ rc_all = True
546
+
547
+ # Find the command to be launched
548
+ actual_command = findMarsExtractCommand(sh=self.system, command=self.command)
549
+
550
+ # Prepare the substitutions' dictionnary
551
+ dictkeyvalue = copy.deepcopy(self.substitutions)
552
+ if self.date is not None:
553
+ dictkeyvalue["YYYYMMDDHH"] = self.date.ymdh
554
+ dictkeyvalue["YYYYMMDD"] = self.date.ymd
555
+ dictkeyvalue["HH"] = self.date.hh
556
+
557
+ # For each input query, extract the files
558
+ for input_query in input_queries:
559
+ # Prepare the query file used
560
+ query_content = input_query.rh.contents
561
+ query_content.setitems(dictkeyvalue)
562
+ input_query.rh.save()
563
+ # Launch each input queries in a dedicated file
564
+ # (to check that the files do not overwrite each other)
565
+ query_file_path = input_query.rh.container.abspath
566
+ local_directory = '_'.join([query_file_path, self.date.ymdhms])
567
+ logger.info("Here is the content of the query file %s (after substitution):", query_file_path)
568
+ self.system.cat(query_file_path, output=False)
569
+ with self.system.cdcontext(local_directory, create=True):
570
+ # Launch the command
571
+ rc = callMarsExtract(sh=self.system, query_file=query_file_path, fatal=self.fatal,
572
+ command=actual_command)
573
+ if not rc:
574
+ if self.fatal:
575
+ logger.error("Problem during the Mars request of %s", query_file_path)
576
+ raise MarsGetError
577
+ else:
578
+ logger.warning("Problem during the Mars request of %s", query_file_path)
579
+ rc_all = rc_all and rc