sierra-research 1.3.6__py3-none-any.whl → 1.5.0__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.
- sierra/__init__.py +3 -3
- sierra/core/__init__.py +3 -3
- sierra/core/batchroot.py +223 -0
- sierra/core/cmdline.py +681 -1057
- sierra/core/compare.py +11 -0
- sierra/core/config.py +96 -88
- sierra/core/engine.py +306 -0
- sierra/core/execenv.py +380 -0
- sierra/core/expdef.py +11 -0
- sierra/core/experiment/__init__.py +1 -0
- sierra/core/experiment/bindings.py +150 -101
- sierra/core/experiment/definition.py +414 -245
- sierra/core/experiment/spec.py +83 -85
- sierra/core/exproot.py +44 -0
- sierra/core/generators/__init__.py +10 -0
- sierra/core/generators/experiment.py +528 -0
- sierra/core/generators/generator_factory.py +138 -137
- sierra/core/graphs/__init__.py +23 -0
- sierra/core/graphs/bcbridge.py +94 -0
- sierra/core/graphs/heatmap.py +245 -324
- sierra/core/graphs/pathset.py +27 -0
- sierra/core/graphs/schema.py +77 -0
- sierra/core/graphs/stacked_line.py +341 -0
- sierra/core/graphs/summary_line.py +506 -0
- sierra/core/logging.py +3 -2
- sierra/core/models/__init__.py +3 -1
- sierra/core/models/info.py +19 -0
- sierra/core/models/interface.py +52 -122
- sierra/core/pipeline/__init__.py +2 -5
- sierra/core/pipeline/pipeline.py +228 -126
- sierra/core/pipeline/stage1/__init__.py +10 -0
- sierra/core/pipeline/stage1/pipeline_stage1.py +45 -31
- sierra/core/pipeline/stage2/__init__.py +10 -0
- sierra/core/pipeline/stage2/pipeline_stage2.py +8 -11
- sierra/core/pipeline/stage2/runner.py +401 -0
- sierra/core/pipeline/stage3/__init__.py +12 -0
- sierra/core/pipeline/stage3/gather.py +321 -0
- sierra/core/pipeline/stage3/pipeline_stage3.py +37 -84
- sierra/core/pipeline/stage4/__init__.py +12 -2
- sierra/core/pipeline/stage4/pipeline_stage4.py +36 -354
- sierra/core/pipeline/stage5/__init__.py +12 -0
- sierra/core/pipeline/stage5/pipeline_stage5.py +33 -208
- sierra/core/pipeline/yaml.py +48 -0
- sierra/core/plugin.py +529 -62
- sierra/core/proc.py +11 -0
- sierra/core/prod.py +11 -0
- sierra/core/ros1/__init__.py +5 -1
- sierra/core/ros1/callbacks.py +22 -21
- sierra/core/ros1/cmdline.py +59 -88
- sierra/core/ros1/generators.py +159 -175
- sierra/core/ros1/variables/__init__.py +3 -0
- sierra/core/ros1/variables/exp_setup.py +122 -116
- sierra/core/startup.py +106 -76
- sierra/core/stat_kernels.py +4 -5
- sierra/core/storage.py +13 -32
- sierra/core/trampoline.py +30 -0
- sierra/core/types.py +116 -71
- sierra/core/utils.py +103 -106
- sierra/core/variables/__init__.py +1 -1
- sierra/core/variables/base_variable.py +12 -17
- sierra/core/variables/batch_criteria.py +387 -481
- sierra/core/variables/builtin.py +135 -0
- sierra/core/variables/exp_setup.py +19 -39
- sierra/core/variables/population_size.py +72 -76
- sierra/core/variables/variable_density.py +44 -68
- sierra/core/vector.py +1 -1
- sierra/main.py +256 -88
- sierra/plugins/__init__.py +119 -0
- sierra/plugins/compare/__init__.py +14 -0
- sierra/plugins/compare/graphs/__init__.py +19 -0
- sierra/plugins/compare/graphs/cmdline.py +120 -0
- sierra/plugins/compare/graphs/comparator.py +291 -0
- sierra/plugins/compare/graphs/inter_controller.py +531 -0
- sierra/plugins/compare/graphs/inter_scenario.py +297 -0
- sierra/plugins/compare/graphs/namecalc.py +53 -0
- sierra/plugins/compare/graphs/outputroot.py +73 -0
- sierra/plugins/compare/graphs/plugin.py +147 -0
- sierra/plugins/compare/graphs/preprocess.py +172 -0
- sierra/plugins/compare/graphs/schema.py +37 -0
- sierra/plugins/engine/__init__.py +14 -0
- sierra/plugins/engine/argos/__init__.py +18 -0
- sierra/plugins/{platform → engine}/argos/cmdline.py +144 -151
- sierra/plugins/{platform/argos/variables → engine/argos/generators}/__init__.py +5 -0
- sierra/plugins/engine/argos/generators/engine.py +394 -0
- sierra/plugins/engine/argos/plugin.py +393 -0
- sierra/plugins/{platform/argos/generators → engine/argos/variables}/__init__.py +5 -0
- sierra/plugins/engine/argos/variables/arena_shape.py +183 -0
- sierra/plugins/engine/argos/variables/cameras.py +240 -0
- sierra/plugins/engine/argos/variables/constant_density.py +112 -0
- sierra/plugins/engine/argos/variables/exp_setup.py +82 -0
- sierra/plugins/{platform → engine}/argos/variables/physics_engines.py +83 -87
- sierra/plugins/engine/argos/variables/population_constant_density.py +178 -0
- sierra/plugins/engine/argos/variables/population_size.py +115 -0
- sierra/plugins/engine/argos/variables/population_variable_density.py +123 -0
- sierra/plugins/engine/argos/variables/rendering.py +108 -0
- sierra/plugins/engine/ros1gazebo/__init__.py +18 -0
- sierra/plugins/engine/ros1gazebo/cmdline.py +175 -0
- sierra/plugins/{platform/ros1robot → engine/ros1gazebo}/generators/__init__.py +5 -0
- sierra/plugins/engine/ros1gazebo/generators/engine.py +125 -0
- sierra/plugins/engine/ros1gazebo/plugin.py +404 -0
- sierra/plugins/engine/ros1gazebo/variables/__init__.py +15 -0
- sierra/plugins/engine/ros1gazebo/variables/population_size.py +214 -0
- sierra/plugins/engine/ros1robot/__init__.py +18 -0
- sierra/plugins/engine/ros1robot/cmdline.py +159 -0
- sierra/plugins/{platform/ros1gazebo → engine/ros1robot}/generators/__init__.py +4 -0
- sierra/plugins/engine/ros1robot/generators/engine.py +95 -0
- sierra/plugins/engine/ros1robot/plugin.py +410 -0
- sierra/plugins/{hpc/local → engine/ros1robot/variables}/__init__.py +5 -0
- sierra/plugins/engine/ros1robot/variables/population_size.py +146 -0
- sierra/plugins/execenv/__init__.py +11 -0
- sierra/plugins/execenv/hpc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/adhoc/plugin.py +131 -0
- sierra/plugins/execenv/hpc/cmdline.py +137 -0
- sierra/plugins/execenv/hpc/local/__init__.py +18 -0
- sierra/plugins/execenv/hpc/local/cmdline.py +31 -0
- sierra/plugins/execenv/hpc/local/plugin.py +145 -0
- sierra/plugins/execenv/hpc/pbs/__init__.py +18 -0
- sierra/plugins/execenv/hpc/pbs/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/pbs/plugin.py +121 -0
- sierra/plugins/execenv/hpc/slurm/__init__.py +18 -0
- sierra/plugins/execenv/hpc/slurm/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/slurm/plugin.py +133 -0
- sierra/plugins/execenv/prefectserver/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/dockerremote/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/plugin.py +132 -0
- sierra/plugins/execenv/prefectserver/flow.py +66 -0
- sierra/plugins/execenv/prefectserver/local/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/local/cmdline.py +29 -0
- sierra/plugins/execenv/prefectserver/local/plugin.py +133 -0
- sierra/plugins/{hpc/adhoc → execenv/robot}/__init__.py +1 -0
- sierra/plugins/execenv/robot/turtlebot3/__init__.py +18 -0
- sierra/plugins/execenv/robot/turtlebot3/plugin.py +204 -0
- sierra/plugins/expdef/__init__.py +14 -0
- sierra/plugins/expdef/json/__init__.py +14 -0
- sierra/plugins/expdef/json/plugin.py +504 -0
- sierra/plugins/expdef/xml/__init__.py +14 -0
- sierra/plugins/expdef/xml/plugin.py +386 -0
- sierra/{core/hpc → plugins/proc}/__init__.py +1 -1
- sierra/plugins/proc/collate/__init__.py +15 -0
- sierra/plugins/proc/collate/cmdline.py +47 -0
- sierra/plugins/proc/collate/plugin.py +271 -0
- sierra/plugins/proc/compress/__init__.py +18 -0
- sierra/plugins/proc/compress/cmdline.py +47 -0
- sierra/plugins/proc/compress/plugin.py +123 -0
- sierra/plugins/proc/decompress/__init__.py +18 -0
- sierra/plugins/proc/decompress/plugin.py +96 -0
- sierra/plugins/proc/imagize/__init__.py +15 -0
- sierra/plugins/proc/imagize/cmdline.py +49 -0
- sierra/plugins/proc/imagize/plugin.py +270 -0
- sierra/plugins/proc/modelrunner/__init__.py +16 -0
- sierra/plugins/proc/modelrunner/plugin.py +250 -0
- sierra/plugins/proc/statistics/__init__.py +15 -0
- sierra/plugins/proc/statistics/cmdline.py +64 -0
- sierra/plugins/proc/statistics/plugin.py +390 -0
- sierra/plugins/{hpc → prod}/__init__.py +1 -0
- sierra/plugins/prod/graphs/__init__.py +18 -0
- sierra/plugins/prod/graphs/cmdline.py +269 -0
- sierra/plugins/prod/graphs/collate.py +279 -0
- sierra/plugins/prod/graphs/inter/__init__.py +13 -0
- sierra/plugins/prod/graphs/inter/generate.py +83 -0
- sierra/plugins/prod/graphs/inter/heatmap.py +86 -0
- sierra/plugins/prod/graphs/inter/line.py +134 -0
- sierra/plugins/prod/graphs/intra/__init__.py +15 -0
- sierra/plugins/prod/graphs/intra/generate.py +202 -0
- sierra/plugins/prod/graphs/intra/heatmap.py +74 -0
- sierra/plugins/prod/graphs/intra/line.py +114 -0
- sierra/plugins/prod/graphs/plugin.py +103 -0
- sierra/plugins/prod/graphs/targets.py +63 -0
- sierra/plugins/prod/render/__init__.py +18 -0
- sierra/plugins/prod/render/cmdline.py +72 -0
- sierra/plugins/prod/render/plugin.py +282 -0
- sierra/plugins/storage/__init__.py +5 -0
- sierra/plugins/storage/arrow/__init__.py +18 -0
- sierra/plugins/storage/arrow/plugin.py +38 -0
- sierra/plugins/storage/csv/__init__.py +9 -0
- sierra/plugins/storage/csv/plugin.py +12 -5
- sierra/version.py +3 -2
- sierra_research-1.5.0.dist-info/METADATA +238 -0
- sierra_research-1.5.0.dist-info/RECORD +186 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/WHEEL +1 -2
- sierra/core/experiment/xml.py +0 -454
- sierra/core/generators/controller_generator_parser.py +0 -34
- sierra/core/generators/exp_creator.py +0 -351
- sierra/core/generators/exp_generators.py +0 -142
- sierra/core/graphs/scatterplot2D.py +0 -109
- sierra/core/graphs/stacked_line_graph.py +0 -249
- sierra/core/graphs/stacked_surface_graph.py +0 -220
- sierra/core/graphs/summary_line_graph.py +0 -369
- sierra/core/hpc/cmdline.py +0 -142
- sierra/core/models/graphs.py +0 -87
- sierra/core/pipeline/stage2/exp_runner.py +0 -286
- sierra/core/pipeline/stage3/imagizer.py +0 -149
- sierra/core/pipeline/stage3/run_collator.py +0 -317
- sierra/core/pipeline/stage3/statistics_calculator.py +0 -478
- sierra/core/pipeline/stage4/graph_collator.py +0 -319
- sierra/core/pipeline/stage4/inter_exp_graph_generator.py +0 -240
- sierra/core/pipeline/stage4/intra_exp_graph_generator.py +0 -317
- sierra/core/pipeline/stage4/model_runner.py +0 -168
- sierra/core/pipeline/stage4/rendering.py +0 -283
- sierra/core/pipeline/stage4/yaml_config_loader.py +0 -103
- sierra/core/pipeline/stage5/inter_scenario_comparator.py +0 -328
- sierra/core/pipeline/stage5/intra_scenario_comparator.py +0 -989
- sierra/core/platform.py +0 -493
- sierra/core/plugin_manager.py +0 -369
- sierra/core/root_dirpath_generator.py +0 -241
- sierra/plugins/hpc/adhoc/plugin.py +0 -125
- sierra/plugins/hpc/local/plugin.py +0 -81
- sierra/plugins/hpc/pbs/__init__.py +0 -9
- sierra/plugins/hpc/pbs/plugin.py +0 -126
- sierra/plugins/hpc/slurm/__init__.py +0 -9
- sierra/plugins/hpc/slurm/plugin.py +0 -130
- sierra/plugins/platform/__init__.py +0 -9
- sierra/plugins/platform/argos/__init__.py +0 -9
- sierra/plugins/platform/argos/generators/platform_generators.py +0 -383
- sierra/plugins/platform/argos/plugin.py +0 -337
- sierra/plugins/platform/argos/variables/arena_shape.py +0 -145
- sierra/plugins/platform/argos/variables/cameras.py +0 -243
- sierra/plugins/platform/argos/variables/constant_density.py +0 -136
- sierra/plugins/platform/argos/variables/exp_setup.py +0 -113
- sierra/plugins/platform/argos/variables/population_constant_density.py +0 -175
- sierra/plugins/platform/argos/variables/population_size.py +0 -102
- sierra/plugins/platform/argos/variables/population_variable_density.py +0 -132
- sierra/plugins/platform/argos/variables/rendering.py +0 -104
- sierra/plugins/platform/ros1gazebo/__init__.py +0 -9
- sierra/plugins/platform/ros1gazebo/cmdline.py +0 -213
- sierra/plugins/platform/ros1gazebo/generators/platform_generators.py +0 -137
- sierra/plugins/platform/ros1gazebo/plugin.py +0 -335
- sierra/plugins/platform/ros1gazebo/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1gazebo/variables/population_size.py +0 -204
- sierra/plugins/platform/ros1robot/__init__.py +0 -9
- sierra/plugins/platform/ros1robot/cmdline.py +0 -175
- sierra/plugins/platform/ros1robot/generators/platform_generators.py +0 -112
- sierra/plugins/platform/ros1robot/plugin.py +0 -373
- sierra/plugins/platform/ros1robot/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1robot/variables/population_size.py +0 -146
- sierra/plugins/robot/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/plugin.py +0 -194
- sierra_research-1.3.6.data/data/share/man/man1/sierra-cli.1 +0 -2349
- sierra_research-1.3.6.data/data/share/man/man7/sierra-examples.7 +0 -488
- sierra_research-1.3.6.data/data/share/man/man7/sierra-exec-envs.7 +0 -331
- sierra_research-1.3.6.data/data/share/man/man7/sierra-glossary.7 +0 -285
- sierra_research-1.3.6.data/data/share/man/man7/sierra-platforms.7 +0 -358
- sierra_research-1.3.6.data/data/share/man/man7/sierra-usage.7 +0 -725
- sierra_research-1.3.6.data/data/share/man/man7/sierra.7 +0 -78
- sierra_research-1.3.6.dist-info/METADATA +0 -500
- sierra_research-1.3.6.dist-info/RECORD +0 -133
- sierra_research-1.3.6.dist-info/top_level.txt +0 -1
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/entry_points.txt +0 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info/licenses}/LICENSE +0 -0
sierra/core/execenv.py
ADDED
@@ -0,0 +1,380 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2024 John Harwell, All rights reserved.
|
3
|
+
#
|
4
|
+
# SPDX-License Identifier: MIT
|
5
|
+
#
|
6
|
+
"""Common functionality for ``--execenv`` plugins to use."""
|
7
|
+
|
8
|
+
# Core packages
|
9
|
+
import typing as tp
|
10
|
+
import re
|
11
|
+
import pwd
|
12
|
+
import os
|
13
|
+
import subprocess
|
14
|
+
import shutil
|
15
|
+
import logging
|
16
|
+
import argparse
|
17
|
+
|
18
|
+
# 3rd party packages
|
19
|
+
import implements
|
20
|
+
|
21
|
+
# Project packages
|
22
|
+
from sierra.core import utils, types, config
|
23
|
+
from sierra.core.trampoline import cmdline_parser # noqa: F401
|
24
|
+
from sierra.core.experiment import bindings
|
25
|
+
import sierra.core.plugin as pm
|
26
|
+
|
27
|
+
_logger = logging.getLogger(__name__)
|
28
|
+
|
29
|
+
|
30
|
+
@implements.implements(bindings.IExpShellCmdsGenerator)
|
31
|
+
class ExpShellCmdsGenerator:
|
32
|
+
"""Dispatcher for shell cmd generation for an :term:`Experiment`.
|
33
|
+
|
34
|
+
Dispatches generation to the selected execution environment. Called during
|
35
|
+
stage 2 to run shell commands immediately before running a given
|
36
|
+
:term:`Experiment`, to run shell commands to actually run the experiment,
|
37
|
+
and to run shell commands immediately after the experiment finishes.
|
38
|
+
"""
|
39
|
+
|
40
|
+
def __init__(self, cmdopts: types.Cmdopts, exp_num: int) -> None:
|
41
|
+
self.cmdopts = cmdopts
|
42
|
+
|
43
|
+
module = pm.pipeline.get_plugin_module(self.cmdopts["execenv"])
|
44
|
+
if hasattr(module, "ExpShellCmdsGenerator"):
|
45
|
+
self.env = module.ExpShellCmdsGenerator(self.cmdopts, exp_num)
|
46
|
+
else:
|
47
|
+
_logger.debug(
|
48
|
+
(
|
49
|
+
"Skipping generating experiment shell commands "
|
50
|
+
"for --execenv=%s: does not define ExpShellCmdsGenerator"
|
51
|
+
),
|
52
|
+
self.cmdopts["execenv"],
|
53
|
+
)
|
54
|
+
|
55
|
+
self.env = None
|
56
|
+
|
57
|
+
def pre_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
58
|
+
cmds = []
|
59
|
+
|
60
|
+
if self.env:
|
61
|
+
cmds.extend(self.env.pre_exp_cmds())
|
62
|
+
|
63
|
+
return cmds
|
64
|
+
|
65
|
+
def exec_exp_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
|
66
|
+
cmds = []
|
67
|
+
|
68
|
+
if self.env:
|
69
|
+
cmds.extend(self.env.exec_exp_cmds(exec_opts))
|
70
|
+
|
71
|
+
return cmds
|
72
|
+
|
73
|
+
def post_exp_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
74
|
+
cmds = []
|
75
|
+
|
76
|
+
if self.env:
|
77
|
+
cmds.extend(self.env.post_exp_cmds())
|
78
|
+
|
79
|
+
return cmds
|
80
|
+
|
81
|
+
|
82
|
+
@implements.implements(bindings.IBatchShellCmdsGenerator)
|
83
|
+
class BatchShellCmdsGenerator:
|
84
|
+
"""Dispatcher for shell cmd generation for a :term:`Batch Experiment`.
|
85
|
+
|
86
|
+
Dispatches generation to the selected execution environment. Called during
|
87
|
+
stage 2 to run shell commands immediately before running a given
|
88
|
+
:term:`Batch Experiment`, to run shell commands to actually run the
|
89
|
+
experiment, and to run shell commands immediately after the whole experiment
|
90
|
+
finishes.
|
91
|
+
"""
|
92
|
+
|
93
|
+
def __init__(self, cmdopts: types.Cmdopts) -> None:
|
94
|
+
self.cmdopts = cmdopts
|
95
|
+
|
96
|
+
module = pm.pipeline.get_plugin_module(self.cmdopts["execenv"])
|
97
|
+
if hasattr(module, "BatchShellCmdsGenerator"):
|
98
|
+
self.env = module.BatchShellCmdsGenerator(self.cmdopts)
|
99
|
+
else:
|
100
|
+
_logger.debug(
|
101
|
+
(
|
102
|
+
"Skipping generating batch experiment shell commands "
|
103
|
+
"for --execenv=%s: does not define BatchShellCmdsGenerator"
|
104
|
+
),
|
105
|
+
self.cmdopts["execenv"],
|
106
|
+
)
|
107
|
+
|
108
|
+
self.env = None
|
109
|
+
|
110
|
+
def pre_batch_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
111
|
+
cmds = []
|
112
|
+
|
113
|
+
if self.env:
|
114
|
+
cmds.extend(self.env.pre_batch_cmds())
|
115
|
+
|
116
|
+
return cmds
|
117
|
+
|
118
|
+
def exec_batch_cmds(self, exec_opts: types.StrDict) -> tp.List[types.ShellCmdSpec]:
|
119
|
+
cmds = []
|
120
|
+
|
121
|
+
if self.env:
|
122
|
+
cmds.extend(self.env.exec_batch_cmds(exec_opts))
|
123
|
+
|
124
|
+
return cmds
|
125
|
+
|
126
|
+
def post_batch_cmds(self) -> tp.List[types.ShellCmdSpec]:
|
127
|
+
cmds = []
|
128
|
+
|
129
|
+
if self.env:
|
130
|
+
cmds.extend(self.env.post_batch_cmds())
|
131
|
+
|
132
|
+
return cmds
|
133
|
+
|
134
|
+
|
135
|
+
def cmdline_postparse_configure(
|
136
|
+
execenv: str, args: argparse.Namespace
|
137
|
+
) -> argparse.Namespace:
|
138
|
+
"""Dispatcher for configuring the cmdopts dictionary.
|
139
|
+
|
140
|
+
Dispatches configuring to the selected ``--execenv``. Called before the
|
141
|
+
pipeline starts to add modify existing cmdline arguments after initial
|
142
|
+
parsing.
|
143
|
+
|
144
|
+
``execenv`` is needed as an arguments as it is not present in ``args``; it
|
145
|
+
is a "bootstrap" cmdline arg needed to be parsed first to build the parser
|
146
|
+
for the set of cmdline arguments accepted.
|
147
|
+
"""
|
148
|
+
logger = logging.getLogger(__name__)
|
149
|
+
|
150
|
+
# Configure for selected execution enivornment first, to check for
|
151
|
+
# low-level details.
|
152
|
+
module = pm.pipeline.get_plugin_module(execenv)
|
153
|
+
|
154
|
+
if hasattr(module, "cmdline_postparse_configure"):
|
155
|
+
args = module.cmdline_postparse_configure(args)
|
156
|
+
else:
|
157
|
+
logger.debug(
|
158
|
+
(
|
159
|
+
"Skipping configuring cmdline from --execenv=%s: "
|
160
|
+
"does not define cmdline_postparse_configure()"
|
161
|
+
),
|
162
|
+
execenv,
|
163
|
+
)
|
164
|
+
|
165
|
+
return args
|
166
|
+
|
167
|
+
|
168
|
+
def execenv_check(cmdopts: types.Cmdopts) -> None:
|
169
|
+
"""Dispatcher for verifying execution environments in stage 2.
|
170
|
+
|
171
|
+
This is required because what is needed to create experiments in stage 1 for
|
172
|
+
an execution environment is not necessarily the same as what is needed (in
|
173
|
+
terms of envvars, daemons, etc.) when running them.
|
174
|
+
"""
|
175
|
+
module = pm.pipeline.get_plugin_module(cmdopts["execenv"])
|
176
|
+
if hasattr(module, "execenv_check"):
|
177
|
+
module.execenv_check(cmdopts)
|
178
|
+
else:
|
179
|
+
_logger.debug(
|
180
|
+
(
|
181
|
+
"Skipping execution environment check for "
|
182
|
+
"--execenv=%s: does not define execenv_check()"
|
183
|
+
),
|
184
|
+
cmdopts["execenv"],
|
185
|
+
)
|
186
|
+
|
187
|
+
|
188
|
+
def parse_nodefile(nodefile: str) -> tp.List[types.ParsedNodefileSpec]:
|
189
|
+
"""
|
190
|
+
Parse a text file containing a list of computational resources to use.
|
191
|
+
|
192
|
+
Assumed to be GNU-parallel style.
|
193
|
+
"""
|
194
|
+
ret = []
|
195
|
+
|
196
|
+
with utils.utf8open(nodefile, "r") as f:
|
197
|
+
lines = f.readlines()
|
198
|
+
|
199
|
+
for line in lines:
|
200
|
+
if parsed := _parse_nodefile_line(line):
|
201
|
+
ret.append(parsed)
|
202
|
+
|
203
|
+
return ret
|
204
|
+
|
205
|
+
|
206
|
+
def _parse_nodefile_line(line: str) -> tp.Optional[types.ParsedNodefileSpec]:
|
207
|
+
# Line starts with a comment--no parsing needed
|
208
|
+
comment_re = r"^#"
|
209
|
+
if res := re.search(comment_re, line):
|
210
|
+
return None
|
211
|
+
|
212
|
+
cores_re = r"^[0-9]+/"
|
213
|
+
if res := re.search(cores_re, line):
|
214
|
+
cores = int(line.split("/")[0])
|
215
|
+
ssh = line.split("/")[1]
|
216
|
+
else:
|
217
|
+
cores = 1
|
218
|
+
ssh = line
|
219
|
+
|
220
|
+
identifier_re = r"[a-zA-Z0-9_.:]+"
|
221
|
+
port_re = r"ssh -p\s*([0-9]+)"
|
222
|
+
username_at_host_re = f"({identifier_re})+@({identifier_re})"
|
223
|
+
port_and_username_at_host_re = port_re + r"\*s" + username_at_host_re
|
224
|
+
port_and_hostname_re = port_re + rf"\s+({identifier_re})"
|
225
|
+
|
226
|
+
if res := re.search(port_and_username_at_host_re, ssh):
|
227
|
+
# They specified the port AND 'username@host'
|
228
|
+
port = int(res.group(1))
|
229
|
+
login = res.group(2)
|
230
|
+
hostname = res.group(3)
|
231
|
+
elif res := re.search(port_and_hostname_re, ssh):
|
232
|
+
# They only specified the port and hostname
|
233
|
+
port = int(res.group(1))
|
234
|
+
hostname = res.group(2)
|
235
|
+
login = pwd.getpwuid(os.getuid())[0]
|
236
|
+
elif res := re.search(username_at_host_re, ssh):
|
237
|
+
# They only specified 'username@host'
|
238
|
+
port = 22
|
239
|
+
login = res.group(1)
|
240
|
+
hostname = res.group(2)
|
241
|
+
elif res := re.search(identifier_re, ssh):
|
242
|
+
# They only specified the hostname
|
243
|
+
port = 22
|
244
|
+
login = pwd.getpwuid(os.getuid())[0]
|
245
|
+
hostname = res.group(0)
|
246
|
+
else:
|
247
|
+
raise ValueError(f"Bad ssh/hostname spec {ssh}")
|
248
|
+
|
249
|
+
return types.ParsedNodefileSpec(
|
250
|
+
hostname=hostname, n_cores=cores, login=login, port=port
|
251
|
+
)
|
252
|
+
|
253
|
+
|
254
|
+
def check_connectivity(
|
255
|
+
cmdopts: types.Cmdopts, login: str, hostname: str, port: int, host_type: str
|
256
|
+
) -> None:
|
257
|
+
"""
|
258
|
+
Check if passwordless connection to the specified host+login works.
|
259
|
+
"""
|
260
|
+
hostname = hostname.split(":")[0]
|
261
|
+
_logger.info("Checking connectivity to %s", hostname)
|
262
|
+
ssh_diag = f"{host_type},port={port} via {login}@{hostname}"
|
263
|
+
nc_diag = f"{host_type},port={port} via {hostname}"
|
264
|
+
|
265
|
+
res = None
|
266
|
+
if cmdopts["online_check_method"] == "ping+ssh":
|
267
|
+
try:
|
268
|
+
_logger.debug("Attempt to ping %s, type=%s", hostname, host_type)
|
269
|
+
timeout = config.kEngine["ping_timeout"]
|
270
|
+
res = subprocess.run(
|
271
|
+
f"ping -c 3 -W {timeout} {hostname}",
|
272
|
+
shell=True,
|
273
|
+
check=True,
|
274
|
+
stdout=subprocess.PIPE,
|
275
|
+
stderr=subprocess.PIPE,
|
276
|
+
)
|
277
|
+
except subprocess.CalledProcessError:
|
278
|
+
_logger.fatal("Unable to ping %s, type=%s", hostname, host_type)
|
279
|
+
_logger.fatal(
|
280
|
+
"stdout=%s, stderr=%s",
|
281
|
+
res.stdout.decode("utf-8") if res else None,
|
282
|
+
res.stderr.decode("utf-8") if res else None,
|
283
|
+
)
|
284
|
+
raise
|
285
|
+
_logger.debug("%s is alive, type=%s", hostname, host_type)
|
286
|
+
elif cmdopts["online_check_method"] == "nc+ssh":
|
287
|
+
try:
|
288
|
+
_logger.debug("Check for ssh tunnel to %s", nc_diag)
|
289
|
+
timeout = config.kEngine["ping_timeout"]
|
290
|
+
res = subprocess.run(
|
291
|
+
f"nc -z {hostname} {port}",
|
292
|
+
shell=True,
|
293
|
+
check=True,
|
294
|
+
stdout=subprocess.PIPE,
|
295
|
+
stderr=subprocess.PIPE,
|
296
|
+
)
|
297
|
+
except subprocess.CalledProcessError:
|
298
|
+
_logger.fatal("No ssh tunnel to %s", nc_diag)
|
299
|
+
_logger.fatal(
|
300
|
+
"stdout=%s, stderr=%s",
|
301
|
+
res.stdout.decode("utf-8") if res else None,
|
302
|
+
res.stderr.decode("utf-8") if res else None,
|
303
|
+
)
|
304
|
+
raise
|
305
|
+
_logger.debug("ssh tunnel to %s alive", nc_diag)
|
306
|
+
|
307
|
+
try:
|
308
|
+
|
309
|
+
_logger.debug("Verify ssh to %s", ssh_diag)
|
310
|
+
res2 = subprocess.run(
|
311
|
+
(
|
312
|
+
f"ssh -p{port} "
|
313
|
+
"-o PasswordAuthentication=no "
|
314
|
+
"-o StrictHostKeyChecking=no "
|
315
|
+
"-o BatchMode=yes "
|
316
|
+
f"{login}@{hostname} exit"
|
317
|
+
),
|
318
|
+
shell=True,
|
319
|
+
check=True,
|
320
|
+
stdout=subprocess.PIPE,
|
321
|
+
stderr=subprocess.PIPE,
|
322
|
+
)
|
323
|
+
except subprocess.CalledProcessError:
|
324
|
+
_logger.fatal("Unable to connect to %s", ssh_diag)
|
325
|
+
_logger.fatal(
|
326
|
+
"stdout=%s, stderr=%s",
|
327
|
+
res2.stdout.decode("utf-8") if res2 else None,
|
328
|
+
res2.stderr.decode("utf-8") if res2 else None,
|
329
|
+
)
|
330
|
+
raise
|
331
|
+
_logger.info("%s@%s online", host_type, hostname)
|
332
|
+
|
333
|
+
|
334
|
+
def check_for_simulator(
|
335
|
+
engine: str, execenv: str, name: str
|
336
|
+
) -> subprocess.CompletedProcess[bytes]:
|
337
|
+
"""
|
338
|
+
Check if the specified executable name exists/is findable.
|
339
|
+
|
340
|
+
Returns the version string for the executable. Requires the executable
|
341
|
+
respect/accept ``-v``.
|
342
|
+
|
343
|
+
"""
|
344
|
+
shellname = get_executable_arch_aware(name)
|
345
|
+
|
346
|
+
version_cmd = f"{shellname} -v"
|
347
|
+
_logger.debug("Check version for '%s' via '%s'", shellname, version_cmd)
|
348
|
+
|
349
|
+
if shutil.which(shellname):
|
350
|
+
res = subprocess.run(
|
351
|
+
version_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
|
352
|
+
)
|
353
|
+
return res
|
354
|
+
else:
|
355
|
+
raise RuntimeError(
|
356
|
+
f"Bad --execenv '{execenv}' for engine '{engine}': cannot find '{name}'"
|
357
|
+
)
|
358
|
+
|
359
|
+
|
360
|
+
def get_executable_arch_aware(base: str) -> str:
|
361
|
+
"""
|
362
|
+
Get the executable name in an :envvar:`SIERRA_ARCH`-aware way.
|
363
|
+
|
364
|
+
Returns <base>-<arch> if the envvar is set, and <base> otherwise.
|
365
|
+
"""
|
366
|
+
if "SIERRA_ARCH" in os.environ:
|
367
|
+
arch = os.environ["SIERRA_ARCH"]
|
368
|
+
return f"{base}-{arch}"
|
369
|
+
else:
|
370
|
+
return base
|
371
|
+
|
372
|
+
|
373
|
+
__all__ = [
|
374
|
+
"ExpShellCmdsGenerator",
|
375
|
+
"cmdline_postparse_configure",
|
376
|
+
"parse_nodefile",
|
377
|
+
"check_connectivity",
|
378
|
+
"check_for_simulator",
|
379
|
+
"get_executable_arch_aware",
|
380
|
+
]
|
sierra/core/expdef.py
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Copyright 2024 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""Trampoline bindings for the various ``--expdef`` plugins that come with SIERRA."""
|
5
|
+
|
6
|
+
# Core packages
|
7
|
+
|
8
|
+
# 3rd party packages
|
9
|
+
|
10
|
+
# Project packages
|
11
|
+
from sierra.core.trampoline import cmdline_parser # noqa: F401
|