Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Feature/links dev merge #329

Open
wants to merge 83 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
8c6e50d
Merge pull request #1 from LLNL/develop
crkrenn May 17, 2020
8eb7b3e
starting to add links
crkrenn Aug 21, 2020
00b4447
added TODO
crkrenn Aug 21, 2020
1161a44
adding directory linking help documentation
crkrenn Oct 13, 2020
60fb7ab
adding link coding
crkrenn Oct 13, 2020
832fc83
making progress
crkrenn Oct 14, 2020
3337fac
working on Linker templates
Oct 14, 2020
e325759
progress
Oct 14, 2020
bf45d58
progress
crkrenn Oct 15, 2020
1bdf809
progress
crkrenn Oct 15, 2020
a9452bd
beta version
crkrenn Oct 15, 2020
0e5c2b4
beta
crkrenn Oct 15, 2020
020016f
Merge pull request #2 from LLNL/develop
crkrenn Oct 15, 2020
20fd99a
merged
crkrenn Oct 15, 2020
6d87ca2
fixing flake8
crkrenn Oct 15, 2020
76ee6ca
flake 8 fixes
crkrenn Oct 15, 2020
9c05113
fixed out_name error
crkrenn Oct 15, 2020
996add8
added more tests
crkrenn Oct 16, 2020
82144ad
fixed flake8 errors
Oct 16, 2020
bd6d30a
removed @pytest.mark.unit
Oct 20, 2020
d79e2d1
fixed python35 flake8 error
Oct 20, 2020
07991ee
Addition of jinja2 to setup.py
Nov 12, 2020
0e86b6b
Merge branch 'develop' into feature/links_dev_merge_3_25_21
crkrenn Mar 25, 2021
9e2e026
updated poetry.lock
crkrenn Mar 25, 2021
9b5a2d8
responding to comments
crkrenn Mar 25, 2021
8adeb6b
removed TODO
crkrenn Mar 25, 2021
d107578
final cleanup
crkrenn Mar 25, 2021
0ab9613
still responding to comments
crkrenn Mar 25, 2021
82cdf25
fixed flake8 error
crkrenn Apr 9, 2021
013b48e
Merge branch 'develop' into feature/links_dev_merge
crkrenn Apr 28, 2021
bc68ebf
Merge branch 'feature/links_dev_merge' of https://github.com/crkrenn/…
crkrenn Apr 28, 2021
fe53dbe
added error checking for template and unique link naming
crkrenn Apr 29, 2021
ce0aa5d
fixed flake8 errors
crkrenn Apr 29, 2021
861541e
Tweaks to help message formatting.
FrankD412 May 10, 2021
93396ac
Merge branch 'LLNL:develop' into develop
crkrenn Feb 12, 2022
e535080
Merge pull request #3 from LLNL/develop
crkrenn Aug 12, 2022
d766f54
merged in current dev branch
crkrenn Aug 13, 2022
ae9721a
removed all requirements on 'step_label'
crkrenn Aug 13, 2022
f9751e2
added temp readme file for make links
crkrenn Aug 13, 2022
26b6e0b
disables make_links if directories are hashed
crkrenn Aug 13, 2022
fc4e332
progress on short dir links
crkrenn Aug 14, 2022
febc456
linking w/o hashing seems to work
crkrenn Aug 14, 2022
72e168d
fixed two typos before merge
crkrenn Aug 14, 2022
66fa0fb
added integration tests for linking
crkrenn Aug 18, 2022
f15f5f6
fixed bug in test_lik.py
crkrenn Aug 18, 2022
8593ec3
ram disk experiment
crkrenn Aug 19, 2022
32967d1
removed link_directory; renamed output_root to output_path
crkrenn Aug 20, 2022
98b4b72
refactored Linker and passed tests
crkrenn Aug 21, 2022
972239e
replaced {{instance}} with {{combo}}
crkrenn Aug 21, 2022
a3115a6
renamed {{INDEX} to {{study_index}} updated validation
crkrenn Aug 21, 2022
804b5e0
added tests
crkrenn Aug 23, 2022
7830e6e
added error checking and tests for combo links
crkrenn Aug 25, 2022
6ce8e20
starting new index link coding
crkrenn Aug 26, 2022
2a3a424
working on indexing code
crkrenn Aug 26, 2022
c5a41b3
working on indexing code
crkrenn Aug 26, 2022
f67e5b5
making links
Aug 29, 2022
6264c6e
new_link for index is working
crkrenn Sep 2, 2022
522beb3
Revert "new_link for index is working"
crkrenn Sep 2, 2022
03fb705
Revert "Revert "new_link for index is working""
crkrenn Sep 2, 2022
de2ac07
removed output test directories
crkrenn Sep 2, 2022
270dd8e
study and combo index seem to be working
crkrenn Sep 2, 2022
ddd4073
added test for combo_index
crkrenn Sep 2, 2022
451e5d9
still working on hashed workspaces
crkrenn Sep 2, 2022
5576b43
links working with hashws
crkrenn Sep 6, 2022
5c070c9
linker.py refactor is working
crkrenn Sep 6, 2022
1b9a2f3
finished linting
crkrenn Sep 9, 2022
54a6d17
removed test links
crkrenn Sep 9, 2022
6d354cf
Update executiongraph.py
crkrenn Sep 9, 2022
81c54ce
Delete maestro.py_short_link_dir
crkrenn Sep 9, 2022
044cfca
Update hello_bye_parameterized.yaml
crkrenn Sep 9, 2022
13449de
Update lulesh_sample1_macosx.yaml
crkrenn Sep 9, 2022
c30ad69
Delete lulesh_sample1_macosx_short_dirs.yaml
crkrenn Sep 9, 2022
b798ef6
cleaned up readme
crkrenn Sep 9, 2022
a92a113
adding step validation
crkrenn Sep 9, 2022
ae2c1a1
'stepping' forward
crkrenn Sep 10, 2022
fd0628a
{step} validation and tests working
crkrenn Sep 10, 2022
bc82c3f
update readme
crkrenn Sep 10, 2022
d8c3b1d
merging step changes
crkrenn Sep 10, 2022
26bc668
adding maestro user key/value replacements
crkrenn Sep 10, 2022
7645a42
passing tests; preparing for variable conflict tests
Sep 12, 2022
a77fd61
add test_validate_variable_conflict code and test
Sep 16, 2022
72fb688
tests passed
Sep 21, 2022
1317d59
updated readme
Sep 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
datastructures/core/executiongraph.py

extend setup workspace

in utils, setup replacement dictionary
add unique run
use recursive render in Linker.link
need to make one run-000x for each maestro run...
14 changes: 13 additions & 1 deletion maestrowf/datastructures/core/executiongraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,16 @@ def name(self):
"""
return self.step.real_name

@property
def step_label(self):
"""
Get step label of the step represented by the record instance.
This is the name of the step without any parameter substitutions.

:returns: The step label of the StudyStep contained within the record.
"""
return self.step.step_label

@property
def walltime(self):
"""
Expand Down Expand Up @@ -318,6 +328,7 @@ def __init__(self, submission_attempts=1, submission_throttle=0,
# Member variables for execution.
self._adapter = None
self._description = OrderedDict()
self.linker = None

# Generate tempdir (if specfied)
if use_tmp:
Expand Down Expand Up @@ -516,7 +527,6 @@ def generate_scripts(self):
continue

# Record generates its own script.
record.setup_workspace()
record.generate_script(adapter, self._tmp_dir)

def _execute_record(self, record, adapter, restart=False):
Expand Down Expand Up @@ -546,6 +556,8 @@ def _execute_record(self, record, adapter, restart=False):
# Generate the script for execution on the fly.
record.setup_workspace() # Generate the workspace.
record.generate_script(adapter, self._tmp_dir)
if self.linker:
self.linker.link(record)

if self.dry_run:
record.mark_end(State.DRYRUN)
Expand Down
18 changes: 14 additions & 4 deletions maestrowf/datastructures/core/study.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class StudyStep:

def __init__(self):
"""Object that represents a single workflow step."""
self._name = ""
self.name = ""
self.step_label = ""
self.description = ""
self.nickname = ""
self.run = {
Expand Down Expand Up @@ -368,7 +369,7 @@ def add_step(self, step):
self.add_node(step.real_name, step)
LOGGER.info(
"Adding step '%s' to study '%s'...", step.name, self.name)
# Apply the environment to the incoming step.
# Apply the dag to the incoming step.
step.__dict__ = \
apply_function(step.__dict__, self.environment.apply_environment)

Expand Down Expand Up @@ -421,7 +422,7 @@ def setup_environment(self):

def configure_study(self, submission_attempts=1, restart_limit=1,
throttle=0, use_tmp=False, hash_ws=False,
dry_run=False):
dry_run=False, linker=None):
"""
Perform initial configuration of a study. \

Expand All @@ -438,6 +439,7 @@ def configure_study(self, submission_attempts=1, restart_limit=1,
ExecutionGraph dumps its information into a temporary directory. \
:param dry_run: Boolean value that toggles dry run to just generate \
study workspaces and scripts without execution or status checking. \
:param linker: Linker object.
:returns: True if the Study is successfully setup, False otherwise. \
"""

Expand All @@ -447,6 +449,10 @@ def configure_study(self, submission_attempts=1, restart_limit=1,
self._use_tmp = use_tmp
self._hash_ws = hash_ws
self._dry_run = dry_run
self.linker = linker
make_links_flag = False
if linker:
make_links_flag = linker.make_links_flag

LOGGER.info(
"\n------------------------------------------\n"
Expand All @@ -456,10 +462,11 @@ def configure_study(self, submission_attempts=1, restart_limit=1,
"Use temporary directory = %s\n"
"Hash workspaces = %s\n"
"Dry run enabled = %s\n"
"Make links enabled = %s\n"
"Output path = %s\n"
"------------------------------------------",
submission_attempts, restart_limit, throttle,
use_tmp, hash_ws, dry_run, self._out_path
use_tmp, hash_ws, dry_run, make_links_flag, self._out_path
)

self.is_configured = True
Expand Down Expand Up @@ -679,6 +686,7 @@ def _stage(self, dag):

modified, step_exp = node.apply_parameters(combo)
step_exp.name = combo_str
step_exp.step_label = step
step_exp.nickname = nickname

# Substitute workspaces into the combination.
Expand Down Expand Up @@ -806,6 +814,7 @@ def _stage_linear(self, dag):
r_cmd = r_cmd.replace(workspace_var, ws)
node.run["cmd"] = cmd
node.run["restart"] = r_cmd
node.study_label = step

# Add the step
dag.add_step(step, node, ws, rlimit)
Expand Down Expand Up @@ -874,6 +883,7 @@ def stage(self):
use_tmp=self._use_tmp, dry_run=self._dry_run)
dag.add_description(**self.description)
dag.log_description()
dag.linker = self.linker

# Because we're working within a Study class whose steps have already
# been verified to not contain a cycle, we can override the check for
Expand Down
99 changes: 70 additions & 29 deletions maestrowf/maestro.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,25 @@

"""A script for launching a YAML study specification."""
from argparse import ArgumentParser, ArgumentError, RawTextHelpFormatter
import jsonschema

import logging
import os
import shutil
import six
import sys
import tabulate
import time

import tabulate
import six
import jsonschema

from maestrowf import __version__
from maestrowf.conductor import Conductor
from maestrowf.specification import YAMLSpecification
from maestrowf.datastructures.core import Study
from maestrowf.datastructures.environment import Variable
from maestrowf.utils import \
create_parentdir, create_dictionary, LoggerUtility, make_safe_path, \
start_process
start_process, Linker


# Program Globals
Expand Down Expand Up @@ -167,6 +169,7 @@ def run_study(args):

# Set up the output directory.
out_dir = environment.remove("OUTPUT_PATH")
out_name = ""
if args.out:
# If out is specified in the args, ignore OUTPUT_PATH.
output_path = os.path.abspath(args.out)
Expand Down Expand Up @@ -263,11 +266,18 @@ def run_study(args):
raise ArgumentError(_msg)

# Set up the study workspace and configure it for execution.
linker = Linker(
make_links_flag=args.make_links,
link_directory=args.link_directory,
link_template=args.link_template,
output_name=out_name,
output_root=out_dir
)
study.setup_workspace()
study.configure_study(
throttle=args.throttle, submission_attempts=args.attempts,
restart_limit=args.rlimit, use_tmp=args.usetmp, hash_ws=args.hashws,
dry_run=args.dry)
dry_run=args.dry, linker=linker)
study.setup_environment()

if args.dry:
Expand Down Expand Up @@ -346,43 +356,74 @@ def setup_argparser():
cancel.set_defaults(func=cancel_study)

# subparser for a run subcommand
run = subparsers.add_parser('run',
help="Launch a study based on a specification")
# need manual line breaks to allow formatted template documentation.
run = subparsers.add_parser(
'run',
help="Launch a study based on a specification",
formatter_class=RawTextHelpFormatter)

run.add_argument("-a", "--attempts", type=int, default=1,
help="Maximum number of submission attempts before a "
help="Maximum number of submission attempts before a\n"
"step is marked as failed. [Default: %(default)d]")
run.add_argument("-r", "--rlimit", type=int, default=1,
help="Maximum number of restarts allowed when steps. "
"specify a restart command (0 denotes no limit). "
help="Maximum number of restarts allowed when steps. \n"
"specify a restart command (0 denotes no limit). \n"
"[Default: %(default)d]")
run.add_argument("-t", "--throttle", type=int, default=0,
help="Maximum number of inflight jobs allowed to execute "
"simultaneously (0 denotes not throttling). "
help="Maximum number of inflight jobs allowed to \n"
"execute simultaneously (0 denotes not throttling). "
"[Default: %(default)d]")
run.add_argument("-s", "--sleeptime", type=int, default=60,
help="Amount of time (in seconds) for the manager to "
help="Amount of time (in seconds) for the manager to \n"
"wait between job status checks. [Default: %(default)d]")
run.add_argument("--dry", action="store_true", default=False,
help="Generate the directory structure and scripts for a "
"study but do not launch it. [Default: %(default)s]")
help="Generate the directory structure and scripts for \n"
"a study but do not launch it. [Default: %(default)s]")
run.add_argument("-p", "--pgen", type=str,
help="Path to a Python code file containing a function "
"that returns a custom filled ParameterGenerator "
help="Path to a Python code file containing a function \n"
"that returns a custom filled ParameterGenerator \n"
"instance.")
run.add_argument("--pargs", type=str, action="append", default=[],
help="A string that represents a single argument to pass "
"a custom parameter generation function. Reuse '--parg' "
"to pass multiple arguments. [Use with '--pgen']")
help="A string that represents a single argument to \n"
"pass a custom parameter generation function. Reuse ' \n"
"'--parg to pass multiple arguments. [Use with '--pgen']")
run.add_argument("-o", "--out", type=str,
help="Output path to place study in. [NOTE: overrides "
help="Output path to place study in. [NOTE: overrides \n"
"OUTPUT_PATH in the specified specification]")
run.add_argument("-fg", action="store_true", default=False,
help="Runs the backend conductor in the foreground "
help="Runs the backend conductor in the foreground \n"
"instead of using nohup. [Default: %(default)s]")
run.add_argument("--hashws", action="store_true", default=False,
help="Enable hashing of subdirectories in parameterized "
"studies (NOTE: breaks commands that use parameter labels"
" to search directories). [Default: %(default)s]")
help="Enable hashing of subdirectories in \n"
"parameterized studies (NOTE: breaks commands that use \n"
"parameter labels to search directories). \n"
" [Default: %(default)s]")
run.add_argument("--make-links", action="store_true", default=False,
help="Automatically make customizable, human-readable \n"
"links to run directories. [Default: %(default)s]")
run.add_argument(
"--link-directory",
type=str,
default="{{output_root}}/links",
help="Jinja template for path where links to run directories \n"
"are made. [Default: %(default)s]")

run.add_argument(
"--link-template",
type=str,
default=(
"{{link_directory}}/{{date}}/run-{{INDEX}}/{{instance}}/{{step}}"),
help="Jinja template for links to run directories\n"
"[Default: %(default)s]\n \n"
"Currently supported Jinja variables:\n"
"{{output_root}} - Parent directory for this maestro study\n"
"{{link_directory}} - Link directory for this maestro study\n"
"{{date}} - Human-readable date (e.g. '2020_07_28')\n"
"{{instance}} - Maestro label for a set of parameters\n"
" (e.g. 'X1.5.X2.5.X3.20')\n"
" [maximum length: 255 characters]\n"
"{{step}} - Maestro label for a given step (e.g. 'run')\n"
"{{INDEX}} - Unique number for each maestro execution (e.g. '0001')")

prompt_opts = run.add_mutually_exclusive_group()
prompt_opts.add_argument(
Expand All @@ -395,12 +436,12 @@ def setup_argparser():
# The only required positional argument for 'run' is a specification path.
run.add_argument(
"specification", type=str,
help="The path to a Study YAML specification that will be loaded and "
"executed.")
help="The path to a Study YAML specification that will be loaded \n"
"and executed.")
run.add_argument(
"--usetmp", action="store_true", default=False,
help="Make use of a temporary directory for dumping scripts and other "
"Maestro related files.")
help="Make use of a temporary directory for dumping scripts and \n"
"other Maestro related files.")
run.set_defaults(func=run_study)

# subparser for a status subcommand
Expand Down
Loading