motoko 0.0.1__tar.gz
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.
- motoko-0.0.1/.gitignore +17 -0
- motoko-0.0.1/.gitlab-ci.yml +41 -0
- motoko-0.0.1/.pre-commit-config.yaml +25 -0
- motoko-0.0.1/PKG-INFO +65 -0
- motoko-0.0.1/README.md +51 -0
- motoko-0.0.1/motoko/__init__.py +0 -0
- motoko-0.0.1/motoko/bd_study.py +115 -0
- motoko-0.0.1/motoko/daemon.py +13 -0
- motoko-0.0.1/motoko/scripts/__init__.py +0 -0
- motoko-0.0.1/motoko/scripts/create_studies.py +29 -0
- motoko-0.0.1/motoko/scripts/info.py +36 -0
- motoko-0.0.1/motoko/scripts/kill.py +26 -0
- motoko-0.0.1/motoko/scripts/launcher.py +23 -0
- motoko-0.0.1/motoko/scripts/main.py +37 -0
- motoko-0.0.1/motoko/scripts/orchestrator.py +104 -0
- motoko-0.0.1/motoko/task_manager.py +155 -0
- motoko-0.0.1/motoko/workflow.py +84 -0
- motoko-0.0.1/motoko.egg-info/PKG-INFO +65 -0
- motoko-0.0.1/motoko.egg-info/SOURCES.txt +36 -0
- motoko-0.0.1/motoko.egg-info/dependency_links.txt +1 -0
- motoko-0.0.1/motoko.egg-info/entry_points.txt +2 -0
- motoko-0.0.1/motoko.egg-info/requires.txt +2 -0
- motoko-0.0.1/motoko.egg-info/top_level.txt +1 -0
- motoko-0.0.1/pyproject.toml +32 -0
- motoko-0.0.1/setup.cfg +4 -0
- motoko-0.0.1/tests/local/local_test.py +71 -0
- motoko-0.0.1/tests/local/workflow/add/bd.yaml +6 -0
- motoko-0.0.1/tests/local/workflow/add/doIt.py +27 -0
- motoko-0.0.1/tests/local/workflow/add/launch.sh +8 -0
- motoko-0.0.1/tests/local/workflow/motoko.yaml +8 -0
- motoko-0.0.1/tests/local/workflow/mult/bd.yaml +6 -0
- motoko-0.0.1/tests/local/workflow/mult/doIt.py +43 -0
- motoko-0.0.1/tests/local/workflow/mult/launch.sh +8 -0
- motoko-0.0.1/tests/local/workflow/norm/bd.yaml +6 -0
- motoko-0.0.1/tests/local/workflow/norm/doIt.py +56 -0
- motoko-0.0.1/tests/local/workflow/norm/launch.sh +8 -0
- motoko-0.0.1/tests/local/workflow/orchestrator.py +60 -0
- motoko-0.0.1/uv.lock +1490 -0
motoko-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
BD-*-runs
|
|
2
|
+
.bd
|
|
3
|
+
*.txt
|
|
4
|
+
*.pyc
|
|
5
|
+
*.xyz
|
|
6
|
+
*.mtp
|
|
7
|
+
*.cfg
|
|
8
|
+
*.als
|
|
9
|
+
examples/**/*.yaml
|
|
10
|
+
!examples/alotf/**/*.mtp
|
|
11
|
+
!examples/alotf/**/*.cfg
|
|
12
|
+
!examples/alotf/**/*.yaml
|
|
13
|
+
examples/**/databases/*
|
|
14
|
+
examples/**/db/*
|
|
15
|
+
!files/**/*
|
|
16
|
+
*.egg-info
|
|
17
|
+
tests/db
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
stages:
|
|
3
|
+
- version
|
|
4
|
+
- build
|
|
5
|
+
- test
|
|
6
|
+
- code_quality
|
|
7
|
+
- deploy
|
|
8
|
+
|
|
9
|
+
#-------------------------------------------------------------------------------
|
|
10
|
+
test:
|
|
11
|
+
stage: test
|
|
12
|
+
image: python:3.10.9
|
|
13
|
+
script:
|
|
14
|
+
- pip install pytest pep8 pyright
|
|
15
|
+
- pip install .
|
|
16
|
+
- python3 -m pytest
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
package:
|
|
20
|
+
stage: build
|
|
21
|
+
image: python:latest
|
|
22
|
+
script:
|
|
23
|
+
- pip install build
|
|
24
|
+
- python3 -m build
|
|
25
|
+
artifacts:
|
|
26
|
+
when: on_success
|
|
27
|
+
paths:
|
|
28
|
+
- dist/
|
|
29
|
+
expire_in: 30 mins
|
|
30
|
+
|
|
31
|
+
python_pypi:
|
|
32
|
+
stage: deploy
|
|
33
|
+
image: python:latest
|
|
34
|
+
needs:
|
|
35
|
+
- job: package
|
|
36
|
+
script:
|
|
37
|
+
- pip install twine
|
|
38
|
+
- TWINE_PASSWORD=${PYPI_TOKEN} TWINE_USERNAME=__token__
|
|
39
|
+
python3 -m twine upload --verbose dist/*
|
|
40
|
+
only:
|
|
41
|
+
- tags
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# See https://pre-commit.com for more information
|
|
2
|
+
# See https://pre-commit.com/hooks.html for more hooks
|
|
3
|
+
repos:
|
|
4
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
5
|
+
rev: v4.5.0
|
|
6
|
+
hooks:
|
|
7
|
+
- id: trailing-whitespace
|
|
8
|
+
- id: end-of-file-fixer
|
|
9
|
+
- id: check-json
|
|
10
|
+
- id: check-yaml
|
|
11
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
12
|
+
rev: v0.11.8
|
|
13
|
+
hooks:
|
|
14
|
+
- id: ruff # Linter
|
|
15
|
+
args: [ --fix ]
|
|
16
|
+
- id: ruff-format # Formatter
|
|
17
|
+
- id: ruff # Check annotations and docstrings
|
|
18
|
+
args: [ --select, "D,ANN0,ANN2", --fix, --unsafe-fixes ]
|
|
19
|
+
stages: [ manual ]
|
|
20
|
+
- repo: https://github.com/codespell-project/codespell
|
|
21
|
+
rev: v2.2.6
|
|
22
|
+
hooks:
|
|
23
|
+
- id: codespell
|
|
24
|
+
additional_dependencies:
|
|
25
|
+
- tomli
|
motoko-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: motoko
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Versatile Workflow Manager
|
|
5
|
+
Author-email: Guillaume Anciaux <guillaume.anciaux@epfl.ch>, Max Ludwig Hodapp <MaxLudwig.Hodapp@mcl.at>
|
|
6
|
+
License: GPL-3.0-or-later
|
|
7
|
+
Project-URL: homepage, https://gitlab.com/blackdynamite/motoko
|
|
8
|
+
Project-URL: repository, https://gitlab.com/blackdynamite/motoko
|
|
9
|
+
Project-URL: documentation, https://gitlab.com/blackdynamite/motoko
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: ase<4.0.0,>=3.24.0
|
|
13
|
+
Requires-Dist: blackdynamite>=1.1.9
|
|
14
|
+
|
|
15
|
+
# Install the package in development mode with dependencies
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
pip install -e .
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Run the tests
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
pytest
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# How to use Kusanagi
|
|
30
|
+
|
|
31
|
+
## Command line interface (CLI)
|
|
32
|
+
|
|
33
|
+
Kusanagi is provided with a few command lines.
|
|
34
|
+
In a Kusanagi directory equipped with a `motoko.yaml`file,
|
|
35
|
+
you can initialize the work flow with:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
motoko create workflow_dir
|
|
39
|
+
cd workflow_dir
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
where `workflow_dir` is such a directory
|
|
43
|
+
|
|
44
|
+
You can then fetch for info of the current state:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
motoko info
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
and to be more verbose
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
motoko info --verbose
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
You can finally kill every running daemon with:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
motoko kill
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## Python interface
|
|
64
|
+
|
|
65
|
+
TODO
|
motoko-0.0.1/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Install the package in development mode with dependencies
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
pip install -e .
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Run the tests
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
pytest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# How to use Kusanagi
|
|
16
|
+
|
|
17
|
+
## Command line interface (CLI)
|
|
18
|
+
|
|
19
|
+
Kusanagi is provided with a few command lines.
|
|
20
|
+
In a Kusanagi directory equipped with a `motoko.yaml`file,
|
|
21
|
+
you can initialize the work flow with:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
motoko create workflow_dir
|
|
25
|
+
cd workflow_dir
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
where `workflow_dir` is such a directory
|
|
29
|
+
|
|
30
|
+
You can then fetch for info of the current state:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
motoko info
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
and to be more verbose
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
motoko info --verbose
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
You can finally kill every running daemon with:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
motoko kill
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
## Python interface
|
|
50
|
+
|
|
51
|
+
TODO
|
|
File without changes
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Scripts for creating and launching BlackDynamite studies"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import shutil
|
|
6
|
+
from BlackDynamite.scripts import createDB, bd_zeo_server
|
|
7
|
+
from BlackDynamite import bdparser
|
|
8
|
+
|
|
9
|
+
################################################################
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_bd_study(task_manager):
|
|
13
|
+
if not os.path.exists(task_manager.study_dir):
|
|
14
|
+
raise RuntimeError(f"not existing study dir {task_manager.study_dir}")
|
|
15
|
+
|
|
16
|
+
# Stop any existing BD server and delete files
|
|
17
|
+
if os.path.exists(task_manager.study_dir):
|
|
18
|
+
subprocess.run(["canYouDigIt", "server", "stop"], cwd=task_manager.study_dir)
|
|
19
|
+
# make a bd command to do the cleaning (to be working in remate also)
|
|
20
|
+
subprocess.run(["git", "clean", "-fxd", task_manager.study_dir])
|
|
21
|
+
|
|
22
|
+
os.makedirs(task_manager.bd_dir, exist_ok=True)
|
|
23
|
+
|
|
24
|
+
cwd = os.getcwd()
|
|
25
|
+
os.chdir(task_manager.study_dir)
|
|
26
|
+
# TODO: BD seems not to allow to create servers using tcp => fix this in BD
|
|
27
|
+
createDB.main(["--truerun", "--study", task_manager.study])
|
|
28
|
+
bd_zeo_server.main(["--action", "stop"])
|
|
29
|
+
bd_zeo_server.main(
|
|
30
|
+
[
|
|
31
|
+
"--action",
|
|
32
|
+
"start",
|
|
33
|
+
"--host",
|
|
34
|
+
task_manager.host,
|
|
35
|
+
"--study",
|
|
36
|
+
task_manager.study,
|
|
37
|
+
]
|
|
38
|
+
)
|
|
39
|
+
os.chdir(cwd)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
################################################################
|
|
43
|
+
def remote_launch(study, study_dir, study_files, host, ssh, local_dir):
|
|
44
|
+
try:
|
|
45
|
+
# Remove previous database
|
|
46
|
+
cmd = f"mkdir -p {study_dir}; "
|
|
47
|
+
cmd += f"cd {study_dir}; "
|
|
48
|
+
cmd += "canYouDigIt server stop; "
|
|
49
|
+
cmd += "rm -rf * .bd"
|
|
50
|
+
ssh.cmd(cmd)
|
|
51
|
+
ssh.copy(study_files, study_dir)
|
|
52
|
+
# Initialize database
|
|
53
|
+
cmd = f"cd {study_dir}; "
|
|
54
|
+
cmd += "canYouDigIt init --truerun; "
|
|
55
|
+
cmd += "canYouDigIt server stop; "
|
|
56
|
+
cmd += f"canYouDigIt server start --host zeo://{host} --study {study}"
|
|
57
|
+
ssh.cmd(cmd)
|
|
58
|
+
except subprocess.CalledProcessError as e:
|
|
59
|
+
print(e.stderr)
|
|
60
|
+
|
|
61
|
+
# Assume that we want to access from the current work dir, create jobs/runs etc., we
|
|
62
|
+
# need all files and a dummy .db folder in it
|
|
63
|
+
if local_dir is not None:
|
|
64
|
+
local_study_dir = local_dir + "/" + study
|
|
65
|
+
os.makedirs(local_study_dir + "/.bd", exist_ok=True)
|
|
66
|
+
for f in study_files:
|
|
67
|
+
try:
|
|
68
|
+
shutil.copy(f, local_study_dir)
|
|
69
|
+
except shutil.SameFileError:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
################################################################
|
|
74
|
+
def create_bd_studies(
|
|
75
|
+
workflow,
|
|
76
|
+
validated=None,
|
|
77
|
+
):
|
|
78
|
+
if validated is None or not validated:
|
|
79
|
+
validated = bdparser.validate_question(
|
|
80
|
+
"Reset and drop content of Kusanagi database", {"yes": False}, False
|
|
81
|
+
)
|
|
82
|
+
if validated is False:
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
for name, task_manager in workflow.task_managers.items():
|
|
86
|
+
create_bd_study(task_manager)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
################################################################
|
|
90
|
+
class SSH:
|
|
91
|
+
def __init__(self, host, user, port=None, profile=""):
|
|
92
|
+
self.host = host
|
|
93
|
+
self.user = user
|
|
94
|
+
self.profile = profile
|
|
95
|
+
|
|
96
|
+
self.remote = f"{user}@{host}"
|
|
97
|
+
|
|
98
|
+
self.ssh_cmd = ["ssh"]
|
|
99
|
+
self.scp_cmd = ["scp"]
|
|
100
|
+
if port is not None:
|
|
101
|
+
self.ssh_cmd += ["-p", f"{port}"]
|
|
102
|
+
self.scp_cmd += ["-P", f"{port}"]
|
|
103
|
+
|
|
104
|
+
def cmd(self, cmd):
|
|
105
|
+
if self.profile == "":
|
|
106
|
+
result = subprocess.run(self.ssh_cmd + [self.remote, cmd])
|
|
107
|
+
else:
|
|
108
|
+
result = subprocess.run(
|
|
109
|
+
self.ssh_cmd + [self.remote, f"source {self.profile}; {cmd}"]
|
|
110
|
+
)
|
|
111
|
+
print(result.stdout)
|
|
112
|
+
|
|
113
|
+
def copy(self, files, dest):
|
|
114
|
+
result = subprocess.run(self.scp_cmd + files + [f"{self.remote}:{dest}"])
|
|
115
|
+
print(result.stdout)
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from motoko.workflow import Workflow
|
|
5
|
+
|
|
6
|
+
command = "create"
|
|
7
|
+
command_help = "Create the sub studies of the workflow"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def populate_arg_parser(parser):
|
|
11
|
+
parser.add_argument(
|
|
12
|
+
"--validated",
|
|
13
|
+
action="store_true",
|
|
14
|
+
help="Answer yes to validation questions",
|
|
15
|
+
)
|
|
16
|
+
parser.add_argument(
|
|
17
|
+
"directory",
|
|
18
|
+
type=str,
|
|
19
|
+
default="./",
|
|
20
|
+
help="Directory where the description of the workflow is provided",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def main(args):
|
|
25
|
+
fullpath = os.path.join(args.directory, "motoko.yaml")
|
|
26
|
+
|
|
27
|
+
wf = Workflow(fullpath)
|
|
28
|
+
wf.create(args.validated)
|
|
29
|
+
return wf
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
from motoko.workflow import Workflow
|
|
5
|
+
|
|
6
|
+
command = "info"
|
|
7
|
+
command_help = "Get info from sub-studies"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def populate_arg_parser(parser):
|
|
11
|
+
parser.add_argument("--verbose", action="store_true", help="show verbose details")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main(args):
|
|
15
|
+
fullpath = "motoko.yaml"
|
|
16
|
+
wf = Workflow(fullpath)
|
|
17
|
+
|
|
18
|
+
for name, task_manager in wf.task_managers.items():
|
|
19
|
+
print("*" * 30)
|
|
20
|
+
print(f"TaskManager: {name}")
|
|
21
|
+
print("*" * 30)
|
|
22
|
+
if not args.verbose:
|
|
23
|
+
subprocess.call("canYouDigIt info", cwd=task_manager.study_dir, shell=True)
|
|
24
|
+
|
|
25
|
+
else:
|
|
26
|
+
subprocess.call(
|
|
27
|
+
"canYouDigIt jobs info", cwd=task_manager.study_dir, shell=True
|
|
28
|
+
)
|
|
29
|
+
subprocess.call(
|
|
30
|
+
"canYouDigIt runs info", cwd=task_manager.study_dir, shell=True
|
|
31
|
+
)
|
|
32
|
+
subprocess.call(
|
|
33
|
+
"canYouDigIt launch_daemon --status",
|
|
34
|
+
cwd=task_manager.study_dir,
|
|
35
|
+
shell=True,
|
|
36
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from motoko.workflow import Workflow
|
|
6
|
+
|
|
7
|
+
command = "kill"
|
|
8
|
+
command_help = "Kill all the running daemons"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def populate_arg_parser(parser):
|
|
12
|
+
parser.add_argument("--verbose", action="store_true", help="show verbose details")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main(args):
|
|
16
|
+
fullpath = "motoko.yaml"
|
|
17
|
+
|
|
18
|
+
wf = Workflow(fullpath)
|
|
19
|
+
|
|
20
|
+
for name, task_manager in wf.task_managers.items():
|
|
21
|
+
print(f"Kill daemons in study: {task_manager.study}")
|
|
22
|
+
cmds = ["canYouDigIt launch_daemon --stop", "canYouDigIt server stop"]
|
|
23
|
+
for cmd in cmds:
|
|
24
|
+
if args.verbose:
|
|
25
|
+
print(f"({task_manager.study}) {cmd}")
|
|
26
|
+
subprocess.call(cmd, cwd=task_manager.study_dir, shell=True)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
from motoko.workflow import Workflow
|
|
4
|
+
|
|
5
|
+
command = "launcher"
|
|
6
|
+
command_help = "Spawn the launcher daemon"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def populate_arg_parser(parser):
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main(args):
|
|
14
|
+
fullpath = "motoko.yaml"
|
|
15
|
+
wf = Workflow(fullpath)
|
|
16
|
+
wf.start_launcher_daemons()
|
|
17
|
+
|
|
18
|
+
# for name, task_manager in wf.task_managers.items():
|
|
19
|
+
# subprocess.call(
|
|
20
|
+
# "canYouDigIt launch_daemon --start --detach",
|
|
21
|
+
# cwd=task_manager.study_dir,
|
|
22
|
+
# shell=True,
|
|
23
|
+
# )
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from motoko.scripts import create_studies, info, kill, launcher, orchestrator
|
|
4
|
+
|
|
5
|
+
commands = [create_studies, info, kill, launcher, orchestrator]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main() -> None:
|
|
9
|
+
"""Entry point for the command line interface."""
|
|
10
|
+
args = parse_args()
|
|
11
|
+
|
|
12
|
+
for command in commands:
|
|
13
|
+
if args.command == command.command:
|
|
14
|
+
command.main(args)
|
|
15
|
+
break
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def parse_args():
|
|
19
|
+
parser = argparse.ArgumentParser()
|
|
20
|
+
parser.prog = "motoko"
|
|
21
|
+
|
|
22
|
+
# Create subparsers for each command
|
|
23
|
+
command_parsers = parser.add_subparsers(dest="command", help="command to run")
|
|
24
|
+
command_parsers.required = True
|
|
25
|
+
|
|
26
|
+
for command in commands:
|
|
27
|
+
command_parser = command_parsers.add_parser(
|
|
28
|
+
command.command, help=command.command_help
|
|
29
|
+
)
|
|
30
|
+
command.populate_arg_parser(command_parser)
|
|
31
|
+
|
|
32
|
+
args = parser.parse_args()
|
|
33
|
+
return args
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
if __name__ == "__main__":
|
|
37
|
+
main()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import importlib.util
|
|
6
|
+
from BlackDynamite.scripts.launch_daemon import find_pids
|
|
7
|
+
|
|
8
|
+
from motoko.workflow import Workflow
|
|
9
|
+
|
|
10
|
+
command = "orchestrator"
|
|
11
|
+
command_help = "Start the workflow"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def populate_arg_parser(parser):
|
|
15
|
+
subparsers = parser.add_subparsers(dest="what")
|
|
16
|
+
parser_start = subparsers.add_parser("start", help="start orchestrator daemon")
|
|
17
|
+
|
|
18
|
+
parser_start.add_argument(
|
|
19
|
+
"--detach",
|
|
20
|
+
"-d",
|
|
21
|
+
action="store_true",
|
|
22
|
+
help="For starting: run in detach/daemon mode with Zdaemon manager",
|
|
23
|
+
)
|
|
24
|
+
parser_start.add_argument(
|
|
25
|
+
"--wait",
|
|
26
|
+
type=str,
|
|
27
|
+
default=5,
|
|
28
|
+
help="Waiting time between state checks in seconds",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Add arguments specific to workflow
|
|
32
|
+
|
|
33
|
+
fullpath = "motoko.yaml"
|
|
34
|
+
wf = Workflow(fullpath)
|
|
35
|
+
|
|
36
|
+
fname, _ = wf.orchestrator_script.split(".")
|
|
37
|
+
file_path = os.path.join(wf.directory, fname + ".py")
|
|
38
|
+
module_name = "orchestrator"
|
|
39
|
+
print(f"loading {file_path}")
|
|
40
|
+
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
|
41
|
+
module = importlib.util.module_from_spec(spec)
|
|
42
|
+
sys.modules[module_name] = module
|
|
43
|
+
spec.loader.exec_module(module)
|
|
44
|
+
parser_function = getattr(module, "populate_arg_parser")
|
|
45
|
+
parser_function(parser_start)
|
|
46
|
+
|
|
47
|
+
# parser_stop = subparsers.add_parser("stop", help="stop orchestrator daemon")
|
|
48
|
+
# parser_stat = subparsers.add_parser(
|
|
49
|
+
# "status", help="get status of detached orchestrator daemon"
|
|
50
|
+
# )
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def main(args):
|
|
54
|
+
fullpath = "motoko.yaml"
|
|
55
|
+
wf = Workflow(fullpath)
|
|
56
|
+
wf_root_dir = wf.directory
|
|
57
|
+
wf_conf_dir = os.path.join(wf_root_dir, ".wf_conf")
|
|
58
|
+
|
|
59
|
+
conf_fname = os.path.join(wf_conf_dir, "orch_daemon.conf")
|
|
60
|
+
|
|
61
|
+
if args.what == "start" and not args.detach:
|
|
62
|
+
params = vars(args)
|
|
63
|
+
wf.execute(**params)
|
|
64
|
+
sys.exit(0)
|
|
65
|
+
|
|
66
|
+
elif args.what == "start" and args.detach:
|
|
67
|
+
exclude = ["--detach", "-d"]
|
|
68
|
+
argv = sys.argv[3:]
|
|
69
|
+
clargs = " ".join([a for a in argv if a not in exclude])
|
|
70
|
+
|
|
71
|
+
prog = f"motoko {command} start {clargs}"
|
|
72
|
+
|
|
73
|
+
zdaemon_conf = f"""
|
|
74
|
+
<runner>
|
|
75
|
+
program {prog}
|
|
76
|
+
socket-name {wf_conf_dir}/orch_daemon.socket
|
|
77
|
+
transcript {wf_conf_dir}/orch.log
|
|
78
|
+
exit-codes 0
|
|
79
|
+
</runner>
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
os.makedirs(wf_conf_dir, exist_ok=True)
|
|
83
|
+
with open(conf_fname, "w") as f:
|
|
84
|
+
f.write(zdaemon_conf)
|
|
85
|
+
|
|
86
|
+
os.system(f"zdaemon -C {conf_fname} start")
|
|
87
|
+
os.system(f"zdaemon -C {conf_fname} status")
|
|
88
|
+
|
|
89
|
+
elif args.what == "status":
|
|
90
|
+
print("ZDaemon status:")
|
|
91
|
+
os.system(f"zdaemon -C {conf_fname} status")
|
|
92
|
+
|
|
93
|
+
pids = find_pids(wf_root_dir)
|
|
94
|
+
print(f"Running orchestrator pids: {pids}")
|
|
95
|
+
|
|
96
|
+
elif args.what == "stop":
|
|
97
|
+
os.system(f"zdaemon -C {conf_fname} stop")
|
|
98
|
+
pids = find_pids(wf_root_dir)
|
|
99
|
+
if pids:
|
|
100
|
+
print(f"Killing: {pids}")
|
|
101
|
+
pids = [str(e) for e in pids]
|
|
102
|
+
os.system(f"kill -9 {' '.join(pids)}")
|
|
103
|
+
|
|
104
|
+
# shutil.rmtree(wf_conf_dir)
|