machineconfig 2.1__py3-none-any.whl → 2.3__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.
Potentially problematic release.
This version of machineconfig might be problematic. Click here for more details.
- machineconfig/cluster/sessions_managers/enhanced_command_runner.py +0 -2
- machineconfig/cluster/sessions_managers/layout_types.py +29 -0
- machineconfig/cluster/sessions_managers/wt_local.py +68 -62
- machineconfig/cluster/sessions_managers/wt_local_manager.py +51 -22
- machineconfig/cluster/sessions_managers/wt_remote.py +30 -108
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +14 -11
- machineconfig/cluster/sessions_managers/wt_utils/layout_generator.py +33 -37
- machineconfig/cluster/sessions_managers/wt_utils/process_monitor.py +22 -17
- machineconfig/cluster/sessions_managers/wt_utils/session_manager.py +59 -10
- machineconfig/cluster/sessions_managers/wt_utils/status_reporter.py +16 -14
- machineconfig/cluster/sessions_managers/zellij_local.py +75 -57
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +51 -23
- machineconfig/cluster/sessions_managers/zellij_remote.py +47 -27
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +13 -12
- machineconfig/cluster/sessions_managers/zellij_utils/example_usage.py +14 -10
- machineconfig/cluster/sessions_managers/zellij_utils/layout_generator.py +31 -15
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +47 -21
- machineconfig/cluster/sessions_managers/zellij_utils/session_manager.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_utils/status_reporter.py +8 -7
- machineconfig/cluster/templates/utils.py +0 -35
- machineconfig/jobs/python/check_installations.py +1 -1
- machineconfig/jobs/python_custom_installers/dev/code.py +0 -13
- machineconfig/jobs/python_generic_installers/config.json +1 -1
- machineconfig/profile/create.py +13 -4
- machineconfig/profile/create_hardlinks.py +3 -1
- machineconfig/profile/shell.py +8 -7
- machineconfig/scripts/__init__.py +0 -2
- machineconfig/scripts/linux/devops +6 -4
- machineconfig/scripts/python/ai/generate_files.py +14 -15
- machineconfig/scripts/python/ai/mcinit.py +8 -5
- machineconfig/scripts/python/archive/tmate_conn.py +5 -5
- machineconfig/scripts/python/archive/tmate_start.py +7 -7
- machineconfig/scripts/python/choose_wezterm_theme.py +35 -32
- machineconfig/scripts/python/cloud_copy.py +22 -13
- machineconfig/scripts/python/cloud_mount.py +35 -23
- machineconfig/scripts/python/cloud_repo_sync.py +38 -25
- machineconfig/scripts/python/cloud_sync.py +4 -4
- machineconfig/scripts/python/croshell.py +37 -28
- machineconfig/scripts/python/devops.py +46 -27
- machineconfig/scripts/python/devops_add_identity.py +15 -25
- machineconfig/scripts/python/devops_add_ssh_key.py +7 -7
- machineconfig/scripts/python/devops_backup_retrieve.py +17 -15
- machineconfig/scripts/python/devops_devapps_install.py +26 -20
- machineconfig/scripts/python/devops_update_repos.py +142 -57
- machineconfig/scripts/python/dotfile.py +16 -14
- machineconfig/scripts/python/fire_agents.py +30 -23
- machineconfig/scripts/python/fire_jobs.py +86 -98
- machineconfig/scripts/python/fire_jobs_args_helper.py +84 -0
- machineconfig/scripts/python/fire_jobs_layout_helper.py +66 -0
- machineconfig/scripts/python/ftpx.py +24 -14
- machineconfig/scripts/python/get_zellij_cmd.py +8 -7
- machineconfig/scripts/python/helpers/cloud_helpers.py +33 -28
- machineconfig/scripts/python/helpers/helpers2.py +25 -14
- machineconfig/scripts/python/helpers/helpers4.py +44 -31
- machineconfig/scripts/python/helpers/helpers5.py +1 -1
- machineconfig/scripts/python/helpers/repo_sync_helpers.py +31 -9
- machineconfig/scripts/python/mount_nfs.py +8 -15
- machineconfig/scripts/python/mount_nw_drive.py +10 -5
- machineconfig/scripts/python/mount_ssh.py +8 -6
- machineconfig/scripts/python/repos.py +215 -57
- machineconfig/scripts/python/snapshot.py +0 -1
- machineconfig/scripts/python/start_slidev.py +10 -5
- machineconfig/scripts/python/start_terminals.py +22 -16
- machineconfig/scripts/python/viewer_template.py +0 -1
- machineconfig/scripts/python/wifi_conn.py +49 -76
- machineconfig/scripts/python/wsl_windows_transfer.py +8 -6
- machineconfig/settings/lf/linux/lfrc +1 -0
- machineconfig/setup_linux/web_shortcuts/croshell.sh +5 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +1 -1
- machineconfig/setup_linux/web_shortcuts/ssh.sh +0 -4
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +3 -12
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +1 -1
- machineconfig/utils/code.py +2 -3
- machineconfig/utils/installer.py +2 -2
- machineconfig/utils/installer_utils/installer_abc.py +2 -4
- machineconfig/utils/installer_utils/installer_class.py +6 -4
- machineconfig/utils/links.py +103 -33
- machineconfig/utils/notifications.py +52 -38
- machineconfig/utils/options.py +14 -21
- machineconfig/utils/path.py +12 -12
- machineconfig/utils/path_reduced.py +239 -200
- machineconfig/utils/procs.py +1 -1
- machineconfig/utils/source_of_truth.py +27 -0
- machineconfig/utils/ssh.py +9 -19
- machineconfig/utils/terminal.py +4 -2
- machineconfig/utils/upgrade_packages.py +91 -0
- machineconfig/utils/utils2.py +1 -2
- machineconfig/utils/utils5.py +23 -11
- machineconfig/utils/ve.py +4 -1
- {machineconfig-2.1.dist-info → machineconfig-2.3.dist-info}/METADATA +13 -13
- {machineconfig-2.1.dist-info → machineconfig-2.3.dist-info}/RECORD +105 -121
- machineconfig-2.3.dist-info/entry_points.txt +2 -0
- machineconfig/cluster/sessions_managers/archive/create_zellij_template.py +0 -59
- machineconfig/cluster/sessions_managers/archive/session_managers.py +0 -183
- machineconfig/cluster/sessions_managers/demo_rich_zellij.py +0 -0
- machineconfig/jobs/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_custom_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_generic_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/jobs/python_linux_installers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/croshell.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
- machineconfig/scripts/python/__pycache__/fire_jobs.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/generate_files.cpython-313.pyc +0 -0
- machineconfig/scripts/python/ai/__pycache__/mcinit.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/__init__.cpython-313.pyc +0 -0
- machineconfig/scripts/python/helpers/__pycache__/helpers4.cpython-313.pyc +0 -0
- machineconfig/setup_linux/web_shortcuts/all.sh +0 -48
- machineconfig/setup_linux/web_shortcuts/update_system.sh +0 -48
- machineconfig/utils/utils.py +0 -97
- /machineconfig/cluster/{cloud_manager.py → remote/cloud_manager.py} +0 -0
- /machineconfig/cluster/{data_transfer.py → remote/data_transfer.py} +0 -0
- /machineconfig/cluster/{distribute.py → remote/distribute.py} +0 -0
- /machineconfig/cluster/{file_manager.py → remote/file_manager.py} +0 -0
- /machineconfig/cluster/{job_params.py → remote/job_params.py} +0 -0
- /machineconfig/cluster/{loader_runner.py → remote/loader_runner.py} +0 -0
- /machineconfig/cluster/{remote_machine.py → remote/remote_machine.py} +0 -0
- /machineconfig/cluster/{script_execution.py → remote/script_execution.py} +0 -0
- /machineconfig/cluster/{script_notify_upon_completion.py → remote/script_notify_upon_completion.py} +0 -0
- /machineconfig/{cluster/sessions_managers/archive/__init__.py → scripts/python/fire_jobs_streamlit_helper.py} +0 -0
- /machineconfig/setup_linux/web_shortcuts/{tmp.sh → android.sh} +0 -0
- {machineconfig-2.1.dist-info → machineconfig-2.3.dist-info}/WHEEL +0 -0
- {machineconfig-2.1.dist-info → machineconfig-2.3.dist-info}/top_level.txt +0 -0
|
@@ -2,10 +2,11 @@ from datetime import datetime
|
|
|
2
2
|
import json
|
|
3
3
|
import uuid
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Optional
|
|
5
|
+
from typing import Optional, Dict
|
|
6
6
|
from machineconfig.utils.utils5 import Scheduler
|
|
7
7
|
from machineconfig.cluster.sessions_managers.zellij_local import run_command_in_zellij_tab
|
|
8
8
|
from machineconfig.cluster.sessions_managers.zellij_remote import ZellijRemoteLayoutGenerator
|
|
9
|
+
from machineconfig.cluster.sessions_managers.layout_types import LayoutConfig
|
|
9
10
|
from machineconfig.logger import get_logger
|
|
10
11
|
|
|
11
12
|
|
|
@@ -14,13 +15,13 @@ logger = get_logger("cluster.sessions_managers.zellij_remote_manager")
|
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class ZellijSessionManager:
|
|
17
|
-
def __init__(self,
|
|
18
|
+
def __init__(self, machine_layouts: Dict[str, LayoutConfig], session_name_prefix: str = "JobMgr"):
|
|
18
19
|
self.session_name_prefix = session_name_prefix
|
|
19
|
-
self.
|
|
20
|
+
self.machine_layouts = machine_layouts # Store the original config
|
|
20
21
|
self.managers: list[ZellijRemoteLayoutGenerator] = []
|
|
21
|
-
for machine,
|
|
22
|
+
for machine, layout_config in machine_layouts.items():
|
|
22
23
|
an_m = ZellijRemoteLayoutGenerator(remote_name=machine, session_name_prefix=self.session_name_prefix)
|
|
23
|
-
an_m.create_zellij_layout(
|
|
24
|
+
an_m.create_zellij_layout(layout_config=layout_config)
|
|
24
25
|
self.managers.append(an_m)
|
|
25
26
|
|
|
26
27
|
def ssh_to_all_machines(self) -> str:
|
|
@@ -93,13 +94,13 @@ class ZellijSessionManager:
|
|
|
93
94
|
session_dir = TMP_SERIALIAZATION_DIR / session_id
|
|
94
95
|
session_dir.mkdir(parents=True, exist_ok=True)
|
|
95
96
|
|
|
96
|
-
# Save the
|
|
97
|
-
config_file = session_dir / "
|
|
98
|
-
text = json.dumps(self.
|
|
97
|
+
# Save the machine_layouts configuration
|
|
98
|
+
config_file = session_dir / "machine_layouts.json"
|
|
99
|
+
text = json.dumps(self.machine_layouts, indent=2, ensure_ascii=False)
|
|
99
100
|
config_file.write_text(text, encoding="utf-8")
|
|
100
101
|
|
|
101
102
|
# Save session metadata
|
|
102
|
-
metadata = {"session_name_prefix": self.session_name_prefix, "created_at": str(datetime.now()), "num_managers": len(self.managers), "machines": list(self.
|
|
103
|
+
metadata = {"session_name_prefix": self.session_name_prefix, "created_at": str(datetime.now()), "num_managers": len(self.managers), "machines": list(self.machine_layouts.keys())}
|
|
103
104
|
metadata_file = session_dir / "metadata.json"
|
|
104
105
|
text = json.dumps(metadata, indent=2, ensure_ascii=False)
|
|
105
106
|
metadata_file.write_text(text, encoding="utf-8")
|
|
@@ -120,11 +121,11 @@ class ZellijSessionManager:
|
|
|
120
121
|
|
|
121
122
|
if not session_dir.exists():
|
|
122
123
|
raise FileNotFoundError(f"Session directory not found: {session_dir}")
|
|
123
|
-
config_file = session_dir / "
|
|
124
|
+
config_file = session_dir / "machine_layouts.json"
|
|
124
125
|
if not config_file.exists():
|
|
125
126
|
raise FileNotFoundError(f"Configuration file not found: {config_file}")
|
|
126
127
|
with open(config_file, "r", encoding="utf-8") as f:
|
|
127
|
-
|
|
128
|
+
machine_layouts = json.load(f)
|
|
128
129
|
|
|
129
130
|
# Load metadata
|
|
130
131
|
metadata_file = session_dir / "metadata.json"
|
|
@@ -134,7 +135,7 @@ class ZellijSessionManager:
|
|
|
134
135
|
metadata = json.load(f)
|
|
135
136
|
session_name_prefix = metadata.get("session_name_prefix", "JobMgr")
|
|
136
137
|
# Create new instance (this will create new managers)
|
|
137
|
-
instance = cls(
|
|
138
|
+
instance = cls(machine_layouts=machine_layouts, session_name_prefix=session_name_prefix)
|
|
138
139
|
# Load saved managers to restore their states
|
|
139
140
|
managers_dir = session_dir / "managers"
|
|
140
141
|
if managers_dir.exists():
|
|
@@ -4,17 +4,21 @@ Example usage of the modularized Zellij remote layout generator.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from machineconfig.cluster.sessions_managers.zellij_remote import ZellijRemoteLayoutGenerator
|
|
7
|
+
from machineconfig.cluster.sessions_managers.layout_types import LayoutConfig
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def example_usage():
|
|
10
11
|
"""Demonstrate the refactored modular usage."""
|
|
11
12
|
|
|
12
|
-
# Sample
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
# Sample layout configuration using new schema
|
|
14
|
+
sample_layout: LayoutConfig = {
|
|
15
|
+
"layoutName": "ExampleRemoteSession",
|
|
16
|
+
"layoutTabs": [
|
|
17
|
+
{"tabName": "🤖Bot1", "startDir": "~/code/bytesense/bithence", "command": "~/scripts/fire -mO go1.py bot1 --kw create_new_bot True"},
|
|
18
|
+
{"tabName": "🤖Bot2", "startDir": "~/code/bytesense/bithence", "command": "~/scripts/fire -mO go2.py bot2 --kw create_new_bot True"},
|
|
19
|
+
{"tabName": "📊Monitor", "startDir": "~", "command": "htop"},
|
|
20
|
+
{"tabName": "📝Logs", "startDir": "/var/log", "command": "tail -f /var/log/app.log"},
|
|
21
|
+
],
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
# Replace 'myserver' with an actual SSH config alias
|
|
@@ -26,11 +30,11 @@ def example_usage():
|
|
|
26
30
|
generator = ZellijRemoteLayoutGenerator(remote_name=remote_name, session_name_prefix=session_name)
|
|
27
31
|
|
|
28
32
|
# Create layout file
|
|
29
|
-
layout_path = generator.create_zellij_layout(
|
|
33
|
+
layout_path = generator.create_zellij_layout(sample_layout)
|
|
30
34
|
print(f"✅ Remote layout created successfully: {layout_path}")
|
|
31
35
|
|
|
32
36
|
# Preview the layout content
|
|
33
|
-
preview = generator.get_layout_preview(
|
|
37
|
+
preview = generator.get_layout_preview(sample_layout)
|
|
34
38
|
print(f"📄 Layout preview:\n{preview}")
|
|
35
39
|
|
|
36
40
|
# Check status using the modular components
|
|
@@ -44,11 +48,11 @@ def example_usage():
|
|
|
44
48
|
print(f"Remote executor: {generator.remote_executor.remote_name}")
|
|
45
49
|
|
|
46
50
|
# Use layout generator directly
|
|
47
|
-
layout_content = generator.layout_generator.generate_layout_content(
|
|
51
|
+
layout_content = generator.layout_generator.generate_layout_content(sample_layout)
|
|
48
52
|
print(f"Layout content length: {len(layout_content)} characters")
|
|
49
53
|
|
|
50
54
|
# Use process monitor directly
|
|
51
|
-
status = generator.process_monitor.check_all_commands_status(
|
|
55
|
+
status = generator.process_monitor.check_all_commands_status(sample_layout)
|
|
52
56
|
print(f"Command status check completed for {len(status)} commands")
|
|
53
57
|
|
|
54
58
|
print("\n✅ All modular components working correctly!")
|
|
@@ -6,11 +6,12 @@ Zellij layout generation utilities for creating KDL layout files.
|
|
|
6
6
|
import shlex
|
|
7
7
|
import random
|
|
8
8
|
import string
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import List, Tuple
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
import logging
|
|
12
12
|
|
|
13
13
|
from rich.console import Console
|
|
14
|
+
from machineconfig.cluster.sessions_managers.layout_types import LayoutConfig
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
console = Console()
|
|
@@ -77,36 +78,51 @@ class LayoutGenerator:
|
|
|
77
78
|
return tab_section
|
|
78
79
|
|
|
79
80
|
@staticmethod
|
|
80
|
-
def validate_tab_config(
|
|
81
|
-
"""Validate
|
|
82
|
-
if not
|
|
83
|
-
raise ValueError("
|
|
84
|
-
|
|
81
|
+
def validate_tab_config(layout_config: LayoutConfig) -> None:
|
|
82
|
+
"""Validate layout configuration format and content."""
|
|
83
|
+
if not layout_config:
|
|
84
|
+
raise ValueError("Layout configuration cannot be empty")
|
|
85
|
+
|
|
86
|
+
if not layout_config.get("layoutName", "").strip():
|
|
87
|
+
raise ValueError("Layout name cannot be empty")
|
|
88
|
+
|
|
89
|
+
layout_tabs = layout_config.get("layoutTabs", [])
|
|
90
|
+
if not layout_tabs:
|
|
91
|
+
raise ValueError("Layout must have at least one tab")
|
|
92
|
+
|
|
93
|
+
for tab in layout_tabs:
|
|
94
|
+
tab_name = tab.get("tabName", "")
|
|
95
|
+
command = tab.get("command", "")
|
|
96
|
+
start_dir = tab.get("startDir", "")
|
|
97
|
+
|
|
85
98
|
if not tab_name.strip():
|
|
86
99
|
raise ValueError(f"Invalid tab name: {tab_name}")
|
|
87
100
|
if not command.strip():
|
|
88
101
|
raise ValueError(f"Invalid command for tab '{tab_name}': {command}")
|
|
89
|
-
if not
|
|
90
|
-
raise ValueError(f"Invalid
|
|
102
|
+
if not start_dir.strip():
|
|
103
|
+
raise ValueError(f"Invalid startDir for tab '{tab_name}': {start_dir}")
|
|
91
104
|
|
|
92
|
-
def generate_layout_content(self,
|
|
105
|
+
def generate_layout_content(self, layout_config: LayoutConfig) -> str:
|
|
93
106
|
"""Generate complete KDL layout content."""
|
|
94
|
-
self.validate_tab_config(
|
|
107
|
+
self.validate_tab_config(layout_config)
|
|
95
108
|
|
|
96
109
|
layout_content = self.LAYOUT_TEMPLATE
|
|
97
|
-
for
|
|
98
|
-
|
|
110
|
+
for tab in layout_config["layoutTabs"]:
|
|
111
|
+
tab_name = tab["tabName"]
|
|
112
|
+
start_dir = tab["startDir"]
|
|
113
|
+
command = tab["command"]
|
|
114
|
+
layout_content += "\n" + self.create_tab_section(tab_name, start_dir, command)
|
|
99
115
|
layout_content += "\n}\n"
|
|
100
116
|
|
|
101
117
|
return layout_content
|
|
102
118
|
|
|
103
|
-
def create_layout_file(self,
|
|
119
|
+
def create_layout_file(self, layout_config: LayoutConfig, output_dir: Path, session_name: str) -> str:
|
|
104
120
|
"""Create a layout file and return its absolute path."""
|
|
105
|
-
self.validate_tab_config(
|
|
121
|
+
self.validate_tab_config(layout_config)
|
|
106
122
|
|
|
107
123
|
# Generate unique suffix for this layout
|
|
108
124
|
random_suffix = self.generate_random_suffix()
|
|
109
|
-
layout_content = self.generate_layout_content(
|
|
125
|
+
layout_content = self.generate_layout_content(layout_config)
|
|
110
126
|
|
|
111
127
|
try:
|
|
112
128
|
# Create output directory if it doesn't exist
|
|
@@ -6,8 +6,9 @@ Process monitoring and status checking utilities for remote commands.
|
|
|
6
6
|
import json
|
|
7
7
|
import shlex
|
|
8
8
|
import logging
|
|
9
|
-
from typing import Dict,
|
|
10
|
-
from .remote_executor import RemoteExecutor
|
|
9
|
+
from typing import Dict, Any
|
|
10
|
+
from machineconfig.cluster.sessions_managers.zellij_utils.remote_executor import RemoteExecutor
|
|
11
|
+
from machineconfig.cluster.sessions_managers.layout_types import LayoutConfig
|
|
11
12
|
|
|
12
13
|
logger = logging.getLogger(__name__)
|
|
13
14
|
|
|
@@ -18,20 +19,37 @@ class ProcessMonitor:
|
|
|
18
19
|
def __init__(self, remote_executor: RemoteExecutor):
|
|
19
20
|
self.remote_executor = remote_executor
|
|
20
21
|
|
|
21
|
-
def check_command_status(self, tab_name: str,
|
|
22
|
+
def check_command_status(self, tab_name: str, layout_config: LayoutConfig, use_verification: bool = True) -> Dict[str, Any]:
|
|
22
23
|
"""Check command status with optional process verification."""
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
# Find the tab with the given name
|
|
25
|
+
tab_config = None
|
|
26
|
+
for tab in layout_config["layoutTabs"]:
|
|
27
|
+
if tab["tabName"] == tab_name:
|
|
28
|
+
tab_config = tab
|
|
29
|
+
break
|
|
30
|
+
|
|
31
|
+
if tab_config is None:
|
|
32
|
+
return {"status": "unknown", "error": f"Tab '{tab_name}' not found in layout config", "running": False, "pid": None, "command": None, "remote": self.remote_executor.remote_name}
|
|
25
33
|
|
|
26
34
|
# Use the verified method by default for more accurate results
|
|
27
35
|
if use_verification:
|
|
28
|
-
return self.get_verified_process_status(tab_name,
|
|
36
|
+
return self.get_verified_process_status(tab_name, layout_config)
|
|
29
37
|
|
|
30
|
-
return self._basic_process_check(tab_name,
|
|
38
|
+
return self._basic_process_check(tab_name, layout_config)
|
|
31
39
|
|
|
32
|
-
def _basic_process_check(self, tab_name: str,
|
|
40
|
+
def _basic_process_check(self, tab_name: str, layout_config: LayoutConfig) -> Dict[str, Any]:
|
|
33
41
|
"""Basic process checking without verification."""
|
|
34
|
-
|
|
42
|
+
# Find the tab with the given name
|
|
43
|
+
tab_config = None
|
|
44
|
+
for tab in layout_config["layoutTabs"]:
|
|
45
|
+
if tab["tabName"] == tab_name:
|
|
46
|
+
tab_config = tab
|
|
47
|
+
break
|
|
48
|
+
|
|
49
|
+
if tab_config is None:
|
|
50
|
+
return {"status": "unknown", "error": f"Tab '{tab_name}' not found in layout config", "running": False, "command": None, "remote": self.remote_executor.remote_name}
|
|
51
|
+
|
|
52
|
+
command = tab_config["command"]
|
|
35
53
|
|
|
36
54
|
try:
|
|
37
55
|
check_script = self._create_process_check_script(command)
|
|
@@ -106,12 +124,19 @@ if __name__ == "__main__":
|
|
|
106
124
|
print(json.dumps(processes))
|
|
107
125
|
"""
|
|
108
126
|
|
|
109
|
-
def force_fresh_process_check(self, tab_name: str,
|
|
127
|
+
def force_fresh_process_check(self, tab_name: str, layout_config: LayoutConfig) -> Dict[str, Any]:
|
|
110
128
|
"""Force a fresh process check with additional validation."""
|
|
111
|
-
|
|
112
|
-
|
|
129
|
+
# Find the tab with the given name
|
|
130
|
+
tab_config = None
|
|
131
|
+
for tab in layout_config["layoutTabs"]:
|
|
132
|
+
if tab["tabName"] == tab_name:
|
|
133
|
+
tab_config = tab
|
|
134
|
+
break
|
|
135
|
+
|
|
136
|
+
if tab_config is None:
|
|
137
|
+
return {"status": "unknown", "error": f"Tab '{tab_name}' not found in layout config", "running": False, "command": None, "remote": self.remote_executor.remote_name}
|
|
113
138
|
|
|
114
|
-
|
|
139
|
+
command = tab_config["command"]
|
|
115
140
|
|
|
116
141
|
try:
|
|
117
142
|
# Get timestamp for freshness validation
|
|
@@ -230,9 +255,9 @@ if __name__ == "__main__":
|
|
|
230
255
|
except Exception:
|
|
231
256
|
return False
|
|
232
257
|
|
|
233
|
-
def get_verified_process_status(self, tab_name: str,
|
|
258
|
+
def get_verified_process_status(self, tab_name: str, layout_config: LayoutConfig) -> Dict[str, Any]:
|
|
234
259
|
"""Get process status with additional verification that processes are actually alive."""
|
|
235
|
-
status = self.force_fresh_process_check(tab_name,
|
|
260
|
+
status = self.force_fresh_process_check(tab_name, layout_config)
|
|
236
261
|
|
|
237
262
|
if status.get("running") and status.get("processes"):
|
|
238
263
|
verified_processes = []
|
|
@@ -252,13 +277,14 @@ if __name__ == "__main__":
|
|
|
252
277
|
|
|
253
278
|
return status
|
|
254
279
|
|
|
255
|
-
def check_all_commands_status(self,
|
|
256
|
-
"""Check status of all commands in the
|
|
257
|
-
if not
|
|
258
|
-
logger.warning("No
|
|
280
|
+
def check_all_commands_status(self, layout_config: LayoutConfig) -> Dict[str, Dict[str, Any]]:
|
|
281
|
+
"""Check status of all commands in the layout configuration."""
|
|
282
|
+
if not layout_config or not layout_config.get("layoutTabs"):
|
|
283
|
+
logger.warning("No layout configuration provided.")
|
|
259
284
|
return {}
|
|
260
285
|
|
|
261
286
|
status_report = {}
|
|
262
|
-
for
|
|
263
|
-
|
|
287
|
+
for tab in layout_config["layoutTabs"]:
|
|
288
|
+
tab_name = tab["tabName"]
|
|
289
|
+
status_report[tab_name] = self.check_command_status(tab_name, layout_config)
|
|
264
290
|
return status_report
|
|
@@ -9,7 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
|
|
10
10
|
from rich.console import Console
|
|
11
11
|
|
|
12
|
-
from .remote_executor import RemoteExecutor
|
|
12
|
+
from machineconfig.cluster.sessions_managers.zellij_utils.remote_executor import RemoteExecutor
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
console = Console()
|
|
@@ -4,9 +4,10 @@ Status reporting utilities for Zellij remote layouts.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
|
-
from typing import Dict, Any
|
|
8
|
-
from .process_monitor import ProcessMonitor
|
|
9
|
-
from .session_manager import SessionManager
|
|
7
|
+
from typing import Dict, Any
|
|
8
|
+
from machineconfig.cluster.sessions_managers.zellij_utils.process_monitor import ProcessMonitor
|
|
9
|
+
from machineconfig.cluster.sessions_managers.zellij_utils.session_manager import SessionManager
|
|
10
|
+
from machineconfig.cluster.sessions_managers.layout_types import LayoutConfig
|
|
10
11
|
|
|
11
12
|
logger = logging.getLogger(__name__)
|
|
12
13
|
|
|
@@ -18,10 +19,10 @@ class StatusReporter:
|
|
|
18
19
|
self.process_monitor = process_monitor
|
|
19
20
|
self.session_manager = session_manager
|
|
20
21
|
|
|
21
|
-
def get_comprehensive_status(self,
|
|
22
|
+
def get_comprehensive_status(self, layout_config: LayoutConfig) -> Dict[str, Any]:
|
|
22
23
|
"""Get comprehensive status including Zellij session and all commands."""
|
|
23
24
|
zellij_status = self.session_manager.check_zellij_session_status()
|
|
24
|
-
commands_status = self.process_monitor.check_all_commands_status(
|
|
25
|
+
commands_status = self.process_monitor.check_all_commands_status(layout_config)
|
|
25
26
|
|
|
26
27
|
running_count = sum(1 for status in commands_status.values() if status.get("running", False))
|
|
27
28
|
total_count = len(commands_status)
|
|
@@ -38,9 +39,9 @@ class StatusReporter:
|
|
|
38
39
|
},
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
def print_status_report(self,
|
|
42
|
+
def print_status_report(self, layout_config: LayoutConfig) -> None:
|
|
42
43
|
"""Print a formatted status report to console."""
|
|
43
|
-
status = self.get_comprehensive_status(
|
|
44
|
+
status = self.get_comprehensive_status(layout_config)
|
|
44
45
|
remote_name = self.session_manager.remote_executor.remote_name
|
|
45
46
|
session_name = self.session_manager.session_name
|
|
46
47
|
|
|
@@ -1,41 +1,6 @@
|
|
|
1
|
-
# """
|
|
2
|
-
# This module contains utility functions for the cluster module.
|
|
3
|
-
# """
|
|
4
|
-
|
|
5
|
-
# import inspect
|
|
6
|
-
# from machineconfig.utils.io_save import save_pickle
|
|
7
|
-
|
|
8
|
-
# from machineconfig.cluster.remote_machine import WorkloadParams
|
|
9
1
|
from typing import Optional
|
|
10
2
|
from machineconfig.utils.path_reduced import PathExtended, PLike
|
|
11
3
|
|
|
12
|
-
# def expensive_function(workload_params: WorkloadParams, sim_dict: Optional[dict[str, Any]] = None) -> P:
|
|
13
|
-
# import time
|
|
14
|
-
# from rich.progress import track
|
|
15
|
-
# print("Hello, I am one thread of an expensive function, and I just started running ...")
|
|
16
|
-
# print(f"Oh, I recieved this parameter: {sim_dict=} & {workload_params=} ")
|
|
17
|
-
# execution_time_in_seconds = 60 * 1
|
|
18
|
-
# steps = 100
|
|
19
|
-
# for _ in track(range(steps), description="Progress bar ..."):
|
|
20
|
-
# time.sleep(execution_time_in_seconds / steps) # Simulate work being done
|
|
21
|
-
# print(f"I'm done, I crunched numbers from {workload_params.idx_start} to {workload_params.idx_end}.")
|
|
22
|
-
# _ = workload_params.idx_max
|
|
23
|
-
|
|
24
|
-
# save_dir = PathExtended.tmp().joinpath("tmp_dirs/expensive_function_single_thread").joinpath(workload_params.save_suffix, f"thread_{workload_params.idx_start}_{workload_params.idx_end}")
|
|
25
|
-
# save_dir.mkdir(parents=True, exist_ok=True)
|
|
26
|
-
# save_pickle(obj={'a': 1}, path=save_dir.joinpath("trial_func_result.pkl"))
|
|
27
|
-
# return save_dir
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
# def assert_has_workload_params(func_or_method: Callable[..., Any]):
|
|
31
|
-
# if not inspect.isfunction(func_or_method) and not inspect.ismethod(func_or_method): raise TypeError(f"{func_or_method} is not a function or method.")
|
|
32
|
-
# try: params = inspect.signature(func_or_method).parameters
|
|
33
|
-
# except ValueError as e: raise ValueError(f"Failed to inspect signature of {func_or_method}: {e}") from e
|
|
34
|
-
# if 'workload_params' not in params: raise ValueError(f"{func_or_method.__name__}() does not have 'workload_params' parameter.")
|
|
35
|
-
# if params['workload_params'].kind != inspect.Parameter.POSITIONAL_OR_KEYWORD: raise ValueError(f"{func_or_method.__name__}() 'workload_params' parameter is not a positional or keyword parameter.")
|
|
36
|
-
# if params['workload_params'].default is not inspect.Parameter.empty: raise ValueError(f"{func_or_method.__name__}() 'workload_params' parameter should not have a default value.")
|
|
37
|
-
# return True
|
|
38
|
-
|
|
39
4
|
|
|
40
5
|
def to_cloud(
|
|
41
6
|
localpath: PLike,
|
|
@@ -9,7 +9,7 @@ import platform
|
|
|
9
9
|
# from rich.console import Console
|
|
10
10
|
# from machineconfig.utils.utils2 import pprint
|
|
11
11
|
# # from rich.progress import track
|
|
12
|
-
from machineconfig.utils.
|
|
12
|
+
from machineconfig.utils.source_of_truth import LIBRARY_ROOT
|
|
13
13
|
# from machineconfig.utils.installer import get_installed_cli_apps
|
|
14
14
|
|
|
15
15
|
# from tqdm import tqdm
|
|
@@ -36,20 +36,7 @@ def main(version: Optional[str] = None):
|
|
|
36
36
|
{"⚠️" * 20}
|
|
37
37
|
""")
|
|
38
38
|
raise NotImplementedError(error_msg)
|
|
39
|
-
|
|
40
39
|
_ = version
|
|
41
|
-
|
|
42
|
-
print(f"""
|
|
43
|
-
{"=" * 150}
|
|
44
|
-
ℹ️ INFO | VS Code features:
|
|
45
|
-
📝 Powerful code editor with IntelliSense
|
|
46
|
-
🧩 Thousands of extensions available
|
|
47
|
-
🔍 Integrated debugging
|
|
48
|
-
🔄 Git integration
|
|
49
|
-
⚙️ Highly customizable
|
|
50
|
-
{"=" * 150}
|
|
51
|
-
""")
|
|
52
|
-
|
|
53
40
|
return install_script
|
|
54
41
|
|
|
55
42
|
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
"doc": "🚀 Fly through your shell history. Great Scott!",
|
|
220
220
|
"filename_template_linux_amd_64": "mcfly-v{}-x86_64-unknown-linux-musl.tar.gz",
|
|
221
221
|
"filename_template_linux_arm_64": "mcfly-v{}-aarch64-unknown-linux-musl.tar.gz",
|
|
222
|
-
"filename_template_windows_amd_64": "
|
|
222
|
+
"filename_template_windows_amd_64": "",
|
|
223
223
|
"filename_template_macos_amd_64": "mcfly-v{}-x86_64-apple-darwin.tar.gz",
|
|
224
224
|
"filename_template_macos_arm_64": "",
|
|
225
225
|
"filename_template_windows_arm_64": "",
|
machineconfig/profile/create.py
CHANGED
|
@@ -5,7 +5,9 @@ This script Takes away all config files from the computer, place them in one dir
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
8
|
-
from machineconfig.utils.
|
|
8
|
+
from machineconfig.utils.links import symlink_func, symlink_copy
|
|
9
|
+
from machineconfig.utils.options import display_options
|
|
10
|
+
from machineconfig.utils.source_of_truth import LIBRARY_ROOT, REPO_ROOT
|
|
9
11
|
from machineconfig.utils.utils2 import read_toml
|
|
10
12
|
from machineconfig.profile.shell import create_default_shell_profile
|
|
11
13
|
|
|
@@ -19,11 +21,18 @@ from typing import Optional, Any, TypedDict
|
|
|
19
21
|
|
|
20
22
|
system = platform.system() # Linux or Windows
|
|
21
23
|
ERROR_LIST: list[Any] = [] # append to this after every exception captured.
|
|
22
|
-
|
|
23
|
-
OTHER_SYSTEM = "windows" if system == "Linux" else "linux"
|
|
24
|
+
|
|
24
25
|
SYSTEM = system.lower()
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
def get_other_systems(current_system: str) -> list[str]:
|
|
29
|
+
all_systems = ["linux", "windows", "darwin"]
|
|
30
|
+
return [s for s in all_systems if s != current_system.lower()]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
OTHER_SYSTEMS = get_other_systems(SYSTEM)
|
|
34
|
+
|
|
35
|
+
|
|
27
36
|
class SymlinkMapper(TypedDict):
|
|
28
37
|
this: str
|
|
29
38
|
to_this: str
|
|
@@ -38,7 +47,7 @@ def main_symlinks(choice: Optional[str] = None):
|
|
|
38
47
|
program_keys_raw: list[str] = list(symlink_mapper.keys())
|
|
39
48
|
program_keys: list[str] = []
|
|
40
49
|
for program_key in program_keys_raw:
|
|
41
|
-
if program_key in exclude or
|
|
50
|
+
if program_key in exclude or any([another_system in program_key for another_system in OTHER_SYSTEMS]):
|
|
42
51
|
continue
|
|
43
52
|
else:
|
|
44
53
|
program_keys.append(program_key)
|
|
@@ -6,7 +6,9 @@ This script Takes away all config files from the computer, place them in one dir
|
|
|
6
6
|
|
|
7
7
|
import platform
|
|
8
8
|
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
9
|
-
from machineconfig.utils.
|
|
9
|
+
from machineconfig.utils.links import symlink_copy as symlink_func
|
|
10
|
+
from machineconfig.utils.options import display_options
|
|
11
|
+
from machineconfig.utils.source_of_truth import LIBRARY_ROOT, REPO_ROOT
|
|
10
12
|
from machineconfig.utils.utils2 import read_toml
|
|
11
13
|
from machineconfig.profile.shell import create_default_shell_profile
|
|
12
14
|
|
machineconfig/profile/shell.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""shell"""
|
|
2
2
|
|
|
3
3
|
from machineconfig.utils.utils2 import randstr
|
|
4
|
-
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
4
|
+
from machineconfig.utils.path_reduced import PathExtended as PathExtended
|
|
5
5
|
from machineconfig.utils.terminal import Terminal
|
|
6
|
-
from machineconfig.utils.
|
|
6
|
+
from machineconfig.utils.options import display_options
|
|
7
|
+
from machineconfig.utils.source_of_truth import LIBRARY_ROOT, REPO_ROOT
|
|
7
8
|
import platform
|
|
8
9
|
import os
|
|
9
10
|
from typing import Literal, Optional
|
|
@@ -27,9 +28,9 @@ def create_default_shell_profile() -> None:
|
|
|
27
28
|
profile_path = get_shell_profile_path()
|
|
28
29
|
profile = profile_path.read_text(encoding="utf-8")
|
|
29
30
|
if system == "Windows":
|
|
30
|
-
source = f""". {str(LIBRARY_ROOT.joinpath("settings/shells/pwsh/init.ps1").collapseuser()).replace("~", "$HOME")}"""
|
|
31
|
+
source = f""". {str(PathExtended(LIBRARY_ROOT).joinpath("settings/shells/pwsh/init.ps1").collapseuser()).replace("~", "$HOME")}"""
|
|
31
32
|
else:
|
|
32
|
-
source = f"""source {str(LIBRARY_ROOT.joinpath("settings/shells/bash/init.sh").collapseuser()).replace("~", "$HOME")}"""
|
|
33
|
+
source = f"""source {str(PathExtended(LIBRARY_ROOT).joinpath("settings/shells/bash/init.sh").collapseuser()).replace("~", "$HOME")}"""
|
|
33
34
|
|
|
34
35
|
if source in profile:
|
|
35
36
|
console.print(Panel("🔄 PROFILE | Skipping init script sourcing - already present in profile", title="[bold blue]Profile[/bold blue]", border_style="blue"))
|
|
@@ -116,9 +117,9 @@ def main_env_path(choice: Optional[str], profile_path: Optional[str]) -> None:
|
|
|
116
117
|
profile_path_obj = PathExtended(profile_path) if isinstance(profile_path, str) else get_shell_profile_path()
|
|
117
118
|
profile_path_obj.copy(name=profile_path_obj.name + ".orig_" + randstr())
|
|
118
119
|
console.print(f"💾 Created backup of profile: {profile_path_obj.name}.orig_*")
|
|
119
|
-
# Inline deprecated
|
|
120
|
+
# Inline deprecated modify_text: if file missing, seed with search text before modification
|
|
120
121
|
current = profile_path_obj.read_text(encoding="utf-8") if profile_path_obj.exists() else addition
|
|
121
|
-
updated =
|
|
122
|
+
updated = current if addition in current else current + "\n" + addition
|
|
122
123
|
profile_path_obj.write_text(updated, encoding="utf-8")
|
|
123
124
|
console.print(Panel("✅ PATH variables added to profile successfully", title="[bold blue]Environment[/bold blue]", border_style="blue"))
|
|
124
125
|
|
|
@@ -172,7 +173,7 @@ def main_add_sources_to_shell_profile(profile_path: Optional[str], choice: Optio
|
|
|
172
173
|
|
|
173
174
|
|
|
174
175
|
def main_add_patches_to_shell_profile(profile_path: Optional[str], choice: Optional[str]) -> None:
|
|
175
|
-
patches: list[str] = [item.as_posix() for item in LIBRARY_ROOT.joinpath(f"profile/patches/{system.lower()}").search()]
|
|
176
|
+
patches: list[str] = [item.as_posix() for item in PathExtended(LIBRARY_ROOT).joinpath(f"profile/patches/{system.lower()}").search()]
|
|
176
177
|
|
|
177
178
|
console.print(Panel("🩹 Adding patches to shell profile", title="[bold blue]Patches[/bold blue]", border_style="blue"))
|
|
178
179
|
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
|
|
3
|
-
source ~/code/machineconfig/.venv/bin/activate
|
|
4
|
-
|
|
5
3
|
op_script=$HOME/tmp_results/shells/python_return_command.sh
|
|
6
4
|
if [ -f "$op_script" ]; then
|
|
7
5
|
rm $op_script
|
|
8
6
|
fi
|
|
9
7
|
|
|
10
|
-
#
|
|
11
|
-
python -m machineconfig.scripts.python.devops "$@"
|
|
8
|
+
# source ~/code/machineconfig/.venv/bin/activate
|
|
9
|
+
# python -m machineconfig.scripts.python.devops "$@"
|
|
10
|
+
# echo "🔄 Running devops script..."
|
|
11
|
+
uv run --no-dev --project $HOME/code/machineconfig python -m machineconfig.scripts.python.devops "$@"
|
|
12
|
+
# uv run --with machineconfig python -m machineconfig.scripts.python.devops "$@"
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
if [ -f "$op_script" ]; then
|
|
14
16
|
chmod +x $op_script
|