dayhoff-tools 1.9.8__tar.gz → 1.9.9__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.
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/PKG-INFO +1 -1
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/cli/engine_commands.py +53 -52
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/pyproject.toml +1 -1
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/README.md +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/__init__.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/chemistry/standardizer.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/chemistry/utils.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/cli/__init__.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/cli/cloud_commands.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/cli/main.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/cli/swarm_commands.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/cli/utility_commands.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/deployment/base.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/deployment/deploy_aws.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/deployment/deploy_gcp.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/deployment/deploy_utils.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/deployment/job_runner.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/deployment/processors.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/deployment/swarm.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/embedders.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/fasta.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/file_ops.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/h5.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/intake/gcp.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/intake/gtdb.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/intake/kegg.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/intake/mmseqs.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/intake/structure.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/intake/uniprot.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/logs.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/sqlite.py +0 -0
- {dayhoff_tools-1.9.8 → dayhoff_tools-1.9.9}/dayhoff_tools/warehouse.py +0 -0
@@ -709,11 +709,7 @@ def engine_status(
|
|
709
709
|
engine = resolve_engine(name_or_id, engines)
|
710
710
|
|
711
711
|
# Fast status display (default)
|
712
|
-
if not detailed:
|
713
|
-
# Skip the API call for studios - use basic info we already have
|
714
|
-
attached_studios = []
|
715
|
-
studio_user = engine.get("user") # Use the engine's user as studio owner
|
716
|
-
|
712
|
+
if not detailed:
|
717
713
|
# Fetch idle status via SSM with longer timeout
|
718
714
|
ssm = boto3.client("ssm", region_name="us-east-1")
|
719
715
|
idle_data = None # Use None to indicate no data received
|
@@ -794,7 +790,7 @@ def engine_status(
|
|
794
790
|
|
795
791
|
# Build status lines - minimal info for fast view
|
796
792
|
status_lines = [
|
797
|
-
f"[blue]{engine['name']}[/blue] {run_disp}{idle_disp}
|
793
|
+
f"[blue]{engine['name']}[/blue] {run_disp}{idle_disp}",
|
798
794
|
]
|
799
795
|
|
800
796
|
# Add activity sensors if we have idle data
|
@@ -888,14 +884,14 @@ def engine_status(
|
|
888
884
|
|
889
885
|
# Compose Active/Idle header with extra detail when idle
|
890
886
|
def _compute_active_disp(idle_info: Dict[str, Any]) -> str:
|
887
|
+
# If we don't have idle info or it's explicitly unavailable, show N/A
|
888
|
+
if not idle_info or idle_info.get("available") == False:
|
889
|
+
return "[dim]N/A[/dim]"
|
890
|
+
|
891
891
|
if idle_info.get("status") == "active":
|
892
892
|
return "[green]Active[/green]"
|
893
893
|
if running_state in ("stopped", "stopping"):
|
894
894
|
return "[dim]N/A[/dim]"
|
895
|
-
|
896
|
-
# If we don't have idle info at all, show N/A
|
897
|
-
if not idle_info.get("available"):
|
898
|
-
return "[dim]N/A[/dim]"
|
899
895
|
|
900
896
|
# If idle, show time/threshold with time remaining if available
|
901
897
|
if idle_info.get("status") == "idle":
|
@@ -952,47 +948,51 @@ def engine_status(
|
|
952
948
|
disk_usage = get_disk_usage_via_ssm(engine["instance_id"]) or "-"
|
953
949
|
status_lines.append(f"Disk: {disk_usage}")
|
954
950
|
|
955
|
-
# Idle timeout (show even when not idle)
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
if isinstance(idle_detector.get("idle_threshold"), (int, float)):
|
960
|
-
idle_threshold_secs = int(idle_detector["idle_threshold"])
|
961
|
-
except Exception:
|
962
|
-
idle_threshold_secs = None
|
963
|
-
|
964
|
-
if idle_threshold_secs is None and engine["state"].lower() == "running":
|
965
|
-
# Fallback: read /etc/engine.env via SSM
|
951
|
+
# Idle timeout (show even when not idle) - but only if we have data
|
952
|
+
if idle_detector.get("available"):
|
953
|
+
idle_threshold_secs: Optional[int] = None
|
954
|
+
# Prefer value from idle detector overlay if present
|
966
955
|
try:
|
967
|
-
|
968
|
-
|
969
|
-
InstanceIds=[engine["instance_id"]],
|
970
|
-
DocumentName="AWS-RunShellScript",
|
971
|
-
Parameters={
|
972
|
-
"commands": [
|
973
|
-
"grep -E '^IDLE_TIMEOUT_SECONDS=' /etc/engine.env | cut -d'=' -f2 || echo 1800",
|
974
|
-
],
|
975
|
-
"executionTimeout": ["5"],
|
976
|
-
},
|
977
|
-
)
|
978
|
-
cid = resp["Command"]["CommandId"]
|
979
|
-
time.sleep(1)
|
980
|
-
inv = ssm.get_command_invocation(
|
981
|
-
CommandId=cid, InstanceId=engine["instance_id"]
|
982
|
-
)
|
983
|
-
if inv.get("Status") == "Success":
|
984
|
-
out = (inv.get("StandardOutputContent") or "").strip()
|
985
|
-
if out:
|
986
|
-
idle_threshold_secs = int(out.splitlines()[0].strip())
|
956
|
+
if isinstance(idle_detector.get("idle_threshold"), (int, float)):
|
957
|
+
idle_threshold_secs = int(idle_detector["idle_threshold"])
|
987
958
|
except Exception:
|
988
959
|
idle_threshold_secs = None
|
989
960
|
|
990
|
-
|
991
|
-
|
961
|
+
if idle_threshold_secs is None and engine["state"].lower() == "running":
|
962
|
+
# Fallback: read /etc/engine.env via SSM
|
963
|
+
try:
|
964
|
+
ssm = boto3.client("ssm", region_name="us-east-1")
|
965
|
+
resp = ssm.send_command(
|
966
|
+
InstanceIds=[engine["instance_id"]],
|
967
|
+
DocumentName="AWS-RunShellScript",
|
968
|
+
Parameters={
|
969
|
+
"commands": [
|
970
|
+
"grep -E '^IDLE_TIMEOUT_SECONDS=' /etc/engine.env | cut -d'=' -f2 || echo '?'",
|
971
|
+
],
|
972
|
+
"executionTimeout": ["5"],
|
973
|
+
},
|
974
|
+
)
|
975
|
+
cid = resp["Command"]["CommandId"]
|
976
|
+
time.sleep(1)
|
977
|
+
inv = ssm.get_command_invocation(
|
978
|
+
CommandId=cid, InstanceId=engine["instance_id"]
|
979
|
+
)
|
980
|
+
if inv.get("Status") == "Success":
|
981
|
+
out = (inv.get("StandardOutputContent") or "").strip()
|
982
|
+
if out and out != "?" and out.isdigit():
|
983
|
+
idle_threshold_secs = int(out)
|
984
|
+
except Exception:
|
985
|
+
idle_threshold_secs = None
|
992
986
|
|
993
|
-
|
994
|
-
|
995
|
-
|
987
|
+
if idle_threshold_secs is not None:
|
988
|
+
status_lines.append(
|
989
|
+
f"Idle timeout: {idle_threshold_secs//60}m ({idle_threshold_secs}s)"
|
990
|
+
)
|
991
|
+
else:
|
992
|
+
status_lines.append("Idle timeout: unknown")
|
993
|
+
else:
|
994
|
+
# No idle detector data available
|
995
|
+
status_lines.append("Idle timeout: N/A")
|
996
996
|
|
997
997
|
# Health report (only if bootstrap finished)
|
998
998
|
if stage_val == "finished":
|
@@ -1136,13 +1136,14 @@ def engine_status(
|
|
1136
1136
|
else:
|
1137
1137
|
for k, v in overlay.items():
|
1138
1138
|
idle_detector.setdefault(k, v)
|
1139
|
+
else:
|
1140
|
+
# SSM failed - mark as unavailable if we don't have good data
|
1141
|
+
if not idle_detector.get("available"):
|
1142
|
+
idle_detector = {"available": False} # Mark as unavailable
|
1139
1143
|
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
top_lines[0] = f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n"
|
1144
|
-
except Exception:
|
1145
|
-
pass
|
1144
|
+
# Recompute header display with latest data
|
1145
|
+
active_disp = _compute_active_disp(idle_detector)
|
1146
|
+
top_lines[0] = f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n"
|
1146
1147
|
|
1147
1148
|
# Activity Sensors (show all with YES/no)
|
1148
1149
|
if idle_detector.get("available"):
|
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
|
|
5
5
|
|
6
6
|
[project]
|
7
7
|
name = "dayhoff-tools"
|
8
|
-
version = "1.9.
|
8
|
+
version = "1.9.9"
|
9
9
|
description = "Common tools for all the repos at Dayhoff Labs"
|
10
10
|
authors = [
|
11
11
|
{name = "Daniel Martin-Alarcon", email = "dma@dayhofflabs.com"}
|
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
|
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
|