sliderule-cli 5.6.2__tar.gz → 5.6.3__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.
- {sliderule_cli-5.6.2/src/sliderule_cli.egg-info → sliderule_cli-5.6.3}/PKG-INFO +1 -1
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3/src/sliderule_cli.egg-info}/PKG-INFO +1 -1
- sliderule_cli-5.6.3/src/sliderule_cli.egg-info/scm_version.json +8 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cluster/main.py +16 -15
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_provisioner/main.py +16 -4
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_runner/main.py +61 -43
- sliderule_cli-5.6.2/src/sliderule_cli.egg-info/scm_version.json +0 -8
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/.gitignore +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/LICENSE +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/README.md +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/pyproject.toml +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/setup.cfg +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cli.egg-info/SOURCES.txt +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cli.egg-info/dependency_links.txt +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cli.egg-info/entry_points.txt +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cli.egg-info/requires.txt +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cli.egg-info/scm_file_list.json +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cli.egg-info/top_level.txt +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_cluster/__init__.py +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_provisioner/__init__.py +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_recorder/__init__.py +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_recorder/environment.yml +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_recorder/main.py +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_runner/__init__.py +0 -0
- {sliderule_cli-5.6.2 → sliderule_cli-5.6.3}/src/sliderule_runner/database.py +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
import json
|
|
2
3
|
import uuid
|
|
3
4
|
import tempfile
|
|
@@ -42,10 +43,9 @@ class Tool:
|
|
|
42
43
|
|
|
43
44
|
# whoami
|
|
44
45
|
def whoami(self):
|
|
45
|
-
|
|
46
|
-
result =
|
|
47
|
-
|
|
48
|
-
return result
|
|
46
|
+
result = self.session.source("whoami", parm={}, path="/discovery", retries=0, rethrow=True)
|
|
47
|
+
self.__display_result(result, reformat=True)
|
|
48
|
+
return json.dumps(result)
|
|
49
49
|
|
|
50
50
|
# status
|
|
51
51
|
def status(self):
|
|
@@ -53,22 +53,21 @@ class Tool:
|
|
|
53
53
|
parm = {"service":self.session.service}
|
|
54
54
|
else:
|
|
55
55
|
parm = {}
|
|
56
|
-
|
|
57
|
-
result =
|
|
58
|
-
|
|
59
|
-
return result
|
|
56
|
+
result = self.session.source("status", parm=parm, path="/discovery", retries=0, rethrow=True)
|
|
57
|
+
self.__display_result(result, reformat=True)
|
|
58
|
+
return json.dumps(result)
|
|
60
59
|
|
|
61
60
|
# version
|
|
62
61
|
def version(self):
|
|
63
62
|
result = sliderule.get_version(session=self.session)
|
|
64
63
|
self.__display_result(result, reformat=True)
|
|
65
|
-
return result
|
|
64
|
+
return json.dumps(result)
|
|
66
65
|
|
|
67
66
|
# defaults
|
|
68
67
|
def defaults(self):
|
|
69
68
|
result = sliderule.source("defaults", session=self.session)
|
|
70
69
|
self.__display_result(result, reformat=True)
|
|
71
|
-
return result
|
|
70
|
+
return json.dumps(result)
|
|
72
71
|
|
|
73
72
|
# earthdata
|
|
74
73
|
def earthdata(self):
|
|
@@ -84,13 +83,13 @@ class Tool:
|
|
|
84
83
|
}.items() if v is not None })
|
|
85
84
|
result = sliderule.source("earthdata", parms, rethrow=True, session=self.session)
|
|
86
85
|
self.__display_result(result, reformat=True)
|
|
87
|
-
return result
|
|
86
|
+
return json.dumps(result)
|
|
88
87
|
|
|
89
88
|
# run
|
|
90
89
|
def run(self):
|
|
91
90
|
# get request parameters
|
|
92
|
-
if self.args.parms.startswith('
|
|
93
|
-
parms = self.args.parms
|
|
91
|
+
if self.args.parms.startswith('{'):
|
|
92
|
+
parms = json.loads(self.args.parms)
|
|
94
93
|
else:
|
|
95
94
|
parms = self.__get_parms()
|
|
96
95
|
# build output parameters (if not supplied in request)
|
|
@@ -117,7 +116,7 @@ class Tool:
|
|
|
117
116
|
break
|
|
118
117
|
# set and return results
|
|
119
118
|
result = output_path
|
|
120
|
-
self.__display_result(result, reformat=
|
|
119
|
+
self.__display_result(result, reformat=False)
|
|
121
120
|
return result
|
|
122
121
|
|
|
123
122
|
#########################################
|
|
@@ -157,7 +156,7 @@ def main():
|
|
|
157
156
|
# earthdata
|
|
158
157
|
earthdata = subparsers.add_parser("earthdata", parents=[common], help="earthdata search")
|
|
159
158
|
earthdata.add_argument('--asset', type=str, default="icesat2", help="SlideRule asset name")
|
|
160
|
-
earthdata.add_argument('--poly', type=float, nargs='+', default=None, help="closed counter-clockwise list of latitude
|
|
159
|
+
earthdata.add_argument('--poly', type=float, nargs='+', default=None, help="closed counter-clockwise list of longitude/latitude pairs defining the area of interest; e.g. lon1 lat1 lon2 lat2 lon3 lat3 ... lon1 lat1")
|
|
161
160
|
earthdata.add_argument('--geojson', type=str, default=None, help="geojson filename defining the area of interest")
|
|
162
161
|
earthdata.add_argument('--bbox', type=float, nargs='+', default=None, help="bounding box defining the area of interest; e.g. lon_ll lat_ll lon_ur lat_ur")
|
|
163
162
|
earthdata.add_argument('--t0', type=str, default=None, help="start time as an ISO datetime string YYYY-MM-DDTHH:MM:SSZ") # datetime.fromisoformat(args.t0)
|
|
@@ -166,6 +165,7 @@ def main():
|
|
|
166
165
|
earthdata.add_argument('--short_name', type=str, default=None, help="CMR dataset name")
|
|
167
166
|
earthdata.add_argument('--with_meta', action='store_true', default=False, help="return metadata along with query results")
|
|
168
167
|
earthdata.add_argument('--name_filter', type=str, default=None, help="regular expression to evaluate against resource names returned by query")
|
|
168
|
+
earthdata.add_argument('--parms', type=str, default=None, help="string or filename containing json parameters to use in request")
|
|
169
169
|
earthdata.set_defaults(func=Tool.earthdata)
|
|
170
170
|
|
|
171
171
|
# run
|
|
@@ -189,6 +189,7 @@ def main():
|
|
|
189
189
|
except Exception as e:
|
|
190
190
|
if args.verbose: raise
|
|
191
191
|
print(f"Unhandled error: {e}")
|
|
192
|
+
sys.exit(1) # returns error back to system
|
|
192
193
|
|
|
193
194
|
# running via direct invocation
|
|
194
195
|
if __name__ == "__main__": main()
|
|
@@ -69,6 +69,14 @@ class Tool:
|
|
|
69
69
|
def info(self):
|
|
70
70
|
return self.session.provisioner.info()
|
|
71
71
|
|
|
72
|
+
# S3 Access
|
|
73
|
+
def s3access(self):
|
|
74
|
+
credentials = self.session.provisioner.s3access()
|
|
75
|
+
print(f'export AWS_ACCESS_KEY_ID={credentials["access_key_id"]}')
|
|
76
|
+
print(f'export AWS_SECRET_ACCESS_KEY={credentials["secret_access_key"]}')
|
|
77
|
+
print(f'export AWS_SESSION_TOKEN={credentials["session_token"]}')
|
|
78
|
+
print(f'export AWS_CREDENTIAL_EXPIRATION={credentials["expiration"]}')
|
|
79
|
+
|
|
72
80
|
# Authenticate
|
|
73
81
|
def authenticate(self):
|
|
74
82
|
return self.session.authenticate(force_login=True)
|
|
@@ -81,7 +89,7 @@ class Tool:
|
|
|
81
89
|
def main():
|
|
82
90
|
|
|
83
91
|
# command line arguments
|
|
84
|
-
parser = argparse.ArgumentParser(prog="sliderule-
|
|
92
|
+
parser = argparse.ArgumentParser(prog="sliderule-provisioner", description="""SlideRule Provisioner""")
|
|
85
93
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
86
94
|
|
|
87
95
|
# options shared by every subcommand; parents= lets them appear after the command name
|
|
@@ -89,7 +97,6 @@ def main():
|
|
|
89
97
|
common.add_argument('--domain', type=str, default="slideruleearth.io")
|
|
90
98
|
common.add_argument('--cluster', type=str, default="developers")
|
|
91
99
|
common.add_argument('--user_service', action='store_true', default=False)
|
|
92
|
-
common.add_argument('--concise', action='store_true', default=False)
|
|
93
100
|
common.add_argument('--verbose', action='store_true', default=False)
|
|
94
101
|
common.add_argument('--timezone', type=str, default="America/New_York")
|
|
95
102
|
|
|
@@ -120,7 +127,7 @@ def main():
|
|
|
120
127
|
|
|
121
128
|
# report
|
|
122
129
|
report = subparsers.add_parser("report", parents=[common], help="report metadata of active clusters")
|
|
123
|
-
report.add_argument('--kind', type=str, default="
|
|
130
|
+
report.add_argument('--kind', type=str, default="cluster", help="'cluster' for cluster report, 'test' for test report")
|
|
124
131
|
report.set_defaults(func=Tool.report)
|
|
125
132
|
|
|
126
133
|
# test
|
|
@@ -132,6 +139,10 @@ def main():
|
|
|
132
139
|
info = subparsers.add_parser("info", parents=[common], help="display information about provisioner")
|
|
133
140
|
info.set_defaults(func=Tool.info)
|
|
134
141
|
|
|
142
|
+
# s3access
|
|
143
|
+
s3access = subparsers.add_parser("s3access", parents=[common], help="sets AWS credentials by outputting shell commands to 'eval' into current environment")
|
|
144
|
+
s3access.set_defaults(func=Tool.s3access)
|
|
145
|
+
|
|
135
146
|
# authenticate
|
|
136
147
|
authenticate = subparsers.add_parser("authenticate", parents=[common], help="force re-authentication of user account")
|
|
137
148
|
authenticate.set_defaults(func=Tool.authenticate)
|
|
@@ -145,7 +156,8 @@ def main():
|
|
|
145
156
|
# route command
|
|
146
157
|
try:
|
|
147
158
|
result = args.func(tool)
|
|
148
|
-
|
|
159
|
+
if result:
|
|
160
|
+
print(f'{json.dumps(result, indent=2)}')
|
|
149
161
|
except Exception as e:
|
|
150
162
|
if args.verbose: raise
|
|
151
163
|
print(f"Unhandled error: {e}")
|
|
@@ -4,6 +4,7 @@ import boto3
|
|
|
4
4
|
import random
|
|
5
5
|
import string
|
|
6
6
|
import argparse
|
|
7
|
+
import traceback
|
|
7
8
|
from sliderule import sliderule
|
|
8
9
|
from .database import Database, JobState, QueuePriority, JobStatus
|
|
9
10
|
from pathlib import Path
|
|
@@ -27,7 +28,7 @@ class Tool:
|
|
|
27
28
|
# open database
|
|
28
29
|
self.database = Database(args.database)
|
|
29
30
|
# create sliderule session
|
|
30
|
-
self.session = sliderule.create_session(verbose=args.verbose)
|
|
31
|
+
self.session = sliderule.create_session(domain=args.domain, verbose=args.verbose)
|
|
31
32
|
self.session.authenticate() # gives privileges to access SlideRule Runner
|
|
32
33
|
# aws clients
|
|
33
34
|
self.s3 = boto3.client("s3", region_name="us-west-2")
|
|
@@ -36,7 +37,10 @@ class Tool:
|
|
|
36
37
|
def __load_remote_file(self, bucket, key):
|
|
37
38
|
obj = self.s3.get_object(Bucket=bucket, Key=key)
|
|
38
39
|
contents = obj["Body"].read().decode("utf-8")
|
|
39
|
-
|
|
40
|
+
try:
|
|
41
|
+
return json.loads(contents)
|
|
42
|
+
except Exception:
|
|
43
|
+
return contents
|
|
40
44
|
|
|
41
45
|
# Get Results for a Job Run
|
|
42
46
|
# output of job must include the following fields for this to work:
|
|
@@ -51,15 +55,22 @@ class Tool:
|
|
|
51
55
|
bucket = run_url.split("s3://")[-1].split("/")[0]
|
|
52
56
|
prefix = "/".join(run_url.split("s3://")[-1].split("/")[1:])
|
|
53
57
|
receipt = self.__load_remote_file(bucket, f"{prefix}/receipt.json") # {"name": ..., "username": ... "args": <path to arg file>, "environment": ...}
|
|
54
|
-
|
|
58
|
+
args_bucket = receipt["args"].split("s3://")[-1].split("/")[0]
|
|
59
|
+
args_file = "/".join(receipt["args"].split("s3://")[-1].split("/")[1:])
|
|
60
|
+
args_content = self.__load_remote_file(args_bucket, args_file)
|
|
61
|
+
if isinstance(args_content, list):
|
|
62
|
+
args_list = args_content
|
|
63
|
+
elif isinstance(args_content, dict) or isinstance(args_content, str):
|
|
64
|
+
args_list = [args_content]
|
|
55
65
|
for i in tqdm(range(len(args_list)), total=len(args_list), desc=f"{run_url}", unit="granule"):
|
|
66
|
+
result_file = f"{prefix}/result{len(args_list) > 1 and str(i) or ''}.json"
|
|
56
67
|
try:
|
|
57
68
|
result = {
|
|
58
|
-
"file": f"{
|
|
69
|
+
"file": f"s3://{bucket}/{result_file}",
|
|
59
70
|
"environment": receipt["environment"],
|
|
60
71
|
"arg": args_list[i]
|
|
61
72
|
}
|
|
62
|
-
rsps = self.__load_remote_file(bucket,
|
|
73
|
+
rsps = self.__load_remote_file(bucket, result_file)
|
|
63
74
|
try:
|
|
64
75
|
result |= {
|
|
65
76
|
"status": rsps["status"] and JobStatus.SUCCESS or JobStatus.FAILURE,
|
|
@@ -89,7 +100,8 @@ class Tool:
|
|
|
89
100
|
# pull out arguments
|
|
90
101
|
name = self.args.name
|
|
91
102
|
script_file = self.args.script
|
|
92
|
-
|
|
103
|
+
arguments_input = self.args.arguments
|
|
104
|
+
arg_as_str = self.args.arg_as_str
|
|
93
105
|
batch_size = self.args.batch_size
|
|
94
106
|
vcpus = self.args.vcpus
|
|
95
107
|
memory = self.args.memory
|
|
@@ -99,9 +111,12 @@ class Tool:
|
|
|
99
111
|
with open(script_file, "r") as file:
|
|
100
112
|
script = file.read()
|
|
101
113
|
# read arguments
|
|
102
|
-
|
|
103
|
-
arguments = [
|
|
104
|
-
|
|
114
|
+
if arg_as_str:
|
|
115
|
+
arguments = [str(arguments_input)]
|
|
116
|
+
else:
|
|
117
|
+
with open(arguments_input, "r") as file:
|
|
118
|
+
arguments = [line.strip() for line in file.readlines()]
|
|
119
|
+
# process job in batches
|
|
105
120
|
for i in range(0, len(arguments), batch_size):
|
|
106
121
|
# build and check name
|
|
107
122
|
job_name = f"{name}_{i}"
|
|
@@ -111,12 +126,12 @@ class Tool:
|
|
|
111
126
|
# submit & save job
|
|
112
127
|
args_list = arguments[i:i+batch_size]
|
|
113
128
|
rsps = self.session.runner.submit(name=job_name, script=script, args=args_list, optional_args={"vcpus":vcpus, "memory":memory, "image":image, "queue":queue})
|
|
114
|
-
self.database.submissions[job_name] = rsps | {"complete": False}
|
|
129
|
+
self.database.submissions[job_name] = rsps | {"complete": False, "job_size": len(args_list)}
|
|
115
130
|
print(f"Submitted job {job_name} using script {script_file} with {len(args_list)} entries: {rsps}")
|
|
116
131
|
|
|
117
132
|
# Scrape Submissions
|
|
118
133
|
def scrape_submissions(self):
|
|
119
|
-
|
|
134
|
+
output_list = []
|
|
120
135
|
for name,submission in self.database.submissions.items():
|
|
121
136
|
if self.args.name and self.args.name != name: continue
|
|
122
137
|
try:
|
|
@@ -125,16 +140,20 @@ class Tool:
|
|
|
125
140
|
for i in range(len(submission["results"])):
|
|
126
141
|
result = submission["results"][i]
|
|
127
142
|
if result["status"] in self.args.status:
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
if self.args.verbose:
|
|
144
|
+
print(f'{i:-5d}: {result}\n')
|
|
145
|
+
output_list.append(json.dumps(result))
|
|
146
|
+
else:
|
|
147
|
+
print(f'{i:-5d}: {result["arg"]}')
|
|
148
|
+
output_list.append(result["arg"])
|
|
130
149
|
else:
|
|
131
150
|
print(f"Skipping {name} because it is still pending")
|
|
132
151
|
except Exception as e:
|
|
133
152
|
print(f"Failed to scrape {name}: {e}")
|
|
134
153
|
if self.args.output:
|
|
135
154
|
with open(self.args.output, "w") as file:
|
|
136
|
-
for
|
|
137
|
-
file.write(f"{
|
|
155
|
+
for output in output_list:
|
|
156
|
+
file.write(f"{output}\n")
|
|
138
157
|
|
|
139
158
|
# Get Status
|
|
140
159
|
def get_status(self):
|
|
@@ -143,12 +162,14 @@ class Tool:
|
|
|
143
162
|
complete = job["complete"]
|
|
144
163
|
print(f"Statusing {name} ...")
|
|
145
164
|
if not complete:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
165
|
+
if job["job_size"] > 1: # array processing, use parent job id
|
|
166
|
+
queue_status = self.session.runner.queue(job_id=job["job_id"], queue=queue, verbose=True)
|
|
167
|
+
child_jobs = queue_status["jobs"]
|
|
168
|
+
self.database.submissions[name]["jobs"] = {}
|
|
169
|
+
for child_job in child_jobs:
|
|
170
|
+
self.database.submissions[name]["jobs"][int(child_job["index"])] = child_job
|
|
171
|
+
else: # single job, use name
|
|
172
|
+
queue_status = self.session.runner.queue(name=name, queue=queue, verbose=False)
|
|
152
173
|
# report
|
|
153
174
|
report = queue_status["report"]
|
|
154
175
|
self.database.submissions[name]["status"] = report
|
|
@@ -172,30 +193,21 @@ class Tool:
|
|
|
172
193
|
|
|
173
194
|
# Generate Report
|
|
174
195
|
def generate_report(self):
|
|
175
|
-
|
|
176
|
-
duration = {"avg": 0.0, "total": 0.0}
|
|
177
|
-
processed = 0
|
|
178
|
-
pending = 0
|
|
179
|
-
errors = 0
|
|
196
|
+
print(",".join([f"{c:>30}" for c in ["name"]] + [f"{c:>12}" for c in ["processed"]] + [f"{c:>12}" for c in list(JobStatus)] + [f"{c:>12}" for c in ["duration"]]))
|
|
180
197
|
for name,submission in self.database.submissions.items():
|
|
181
198
|
if self.args.name and self.args.name != name: continue
|
|
199
|
+
stats = {status.value: 0 for status in JobStatus}
|
|
200
|
+
duration = {"avg": 0.0, "total": 0.0}
|
|
201
|
+
processed = 0
|
|
182
202
|
if submission["complete"]:
|
|
183
203
|
for result in submission["results"]:
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
stats[result["status"]] += 1
|
|
205
|
+
if "duration" in result:
|
|
186
206
|
duration["total"] += result["duration"]
|
|
187
207
|
processed += 1
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
pending += 1
|
|
192
|
-
if processed > 0:
|
|
193
|
-
duration["avg"] = duration["total"] / processed
|
|
194
|
-
print("Processed:", processed)
|
|
195
|
-
print("Pending:", pending)
|
|
196
|
-
print("Errors:", errors)
|
|
197
|
-
print("Status:", json.dumps(stats, indent=2))
|
|
198
|
-
print("Duration:", json.dumps(duration, indent=2))
|
|
208
|
+
if processed > 0:
|
|
209
|
+
duration["avg"] = duration["total"] / processed
|
|
210
|
+
print(",".join([f"{c:>30}" for c in [name]] + [f"{c:>12}" for c in [processed]] + [f"{c:>12}" for c in [stats[status] for status in list(JobStatus)]] + [f"{c:>12.3}" for c in [duration["avg"]]]))
|
|
199
211
|
|
|
200
212
|
# Cancel Job
|
|
201
213
|
def cancel_job(self):
|
|
@@ -209,10 +221,13 @@ class Tool:
|
|
|
209
221
|
def get_logs(self):
|
|
210
222
|
name = self.args.name
|
|
211
223
|
index = self.args.index
|
|
212
|
-
|
|
224
|
+
if index is not None:
|
|
225
|
+
job_id = self.database.submissions[name]["jobs"][str(index)]["job_id"]
|
|
226
|
+
else:
|
|
227
|
+
job_id = self.database.submissions[name]["job_id"]
|
|
213
228
|
events = self.session.runner.logs(job_id=job_id)
|
|
214
229
|
for event in events:
|
|
215
|
-
print(event)
|
|
230
|
+
print("->", event)
|
|
216
231
|
|
|
217
232
|
# Finish
|
|
218
233
|
def finish(self):
|
|
@@ -232,6 +247,7 @@ def main():
|
|
|
232
247
|
|
|
233
248
|
# options shared by every subcommand; parents= lets them appear after the command name
|
|
234
249
|
common = argparse.ArgumentParser(add_help=False)
|
|
250
|
+
common.add_argument('--domain', type=str, default="slideruleearth.io")
|
|
235
251
|
common.add_argument('--database', type=Path, default=Path.home() / ".cache" / "sliderule" / "runner_database.json")
|
|
236
252
|
common.add_argument('--queue', type=QueuePriority, default=QueuePriority.DEFAULT, choices=list(QueuePriority))
|
|
237
253
|
common.add_argument('--verbose', action='store_true', default=False)
|
|
@@ -247,6 +263,7 @@ def main():
|
|
|
247
263
|
submit.add_argument('name', metavar="<name>")
|
|
248
264
|
submit.add_argument('script', metavar="<script.lua>", type=Path)
|
|
249
265
|
submit.add_argument('arguments', metavar="<arguments.txt>", type=Path)
|
|
266
|
+
submit.add_argument('--arg_as_str', action='store_true', default=False) # changes arguments to be just a string instead of a file
|
|
250
267
|
submit.add_argument('--vcpus', type=int, default=4)
|
|
251
268
|
submit.add_argument('--memory', type=int, default=16000)
|
|
252
269
|
submit.add_argument('--batch_size', type=int, default=10000)
|
|
@@ -265,7 +282,7 @@ def main():
|
|
|
265
282
|
status.set_defaults(func=Tool.get_status)
|
|
266
283
|
|
|
267
284
|
# report
|
|
268
|
-
report = subparsers.add_parser("report", parents=[common], help="generate report of
|
|
285
|
+
report = subparsers.add_parser("report", parents=[common], help="generate report of completed jobs")
|
|
269
286
|
report.add_argument('--name', type=str, default=None) # name of submission
|
|
270
287
|
report.set_defaults(func=Tool.generate_report)
|
|
271
288
|
|
|
@@ -277,7 +294,7 @@ def main():
|
|
|
277
294
|
# logs
|
|
278
295
|
logs = subparsers.add_parser("logs", parents=[common], help="get log messages for a child job")
|
|
279
296
|
logs.add_argument('--name', type=str, required=True) # name of submission
|
|
280
|
-
logs.add_argument('--index', type=int,
|
|
297
|
+
logs.add_argument('--index', type=int, default=None) # job index
|
|
281
298
|
logs.set_defaults(func=Tool.get_logs)
|
|
282
299
|
|
|
283
300
|
# parse command line
|
|
@@ -293,6 +310,7 @@ def main():
|
|
|
293
310
|
except Exception as e:
|
|
294
311
|
if args.verbose: raise
|
|
295
312
|
print(f"Unhandled error: {e}")
|
|
313
|
+
traceback.print_exc()
|
|
296
314
|
|
|
297
315
|
# running via direct invocation
|
|
298
316
|
if __name__ == "__main__": main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|