|
37 | 37 | # VMM discovery directories |
38 | 38 | # Each user's instances are in $XDG_RUNTIME_DIR/dstack-vmm (typically /run/user/<uid>/dstack-vmm). |
39 | 39 | # CLI scans all users' directories so operators can see every instance on the host. |
40 | | -def _get_discovery_dirs() -> List[str]: |
| 40 | +def _get_discovery_dirs() -> List[Tuple[str, Optional[str]]]: |
| 41 | + """Return list of (discovery_dir, username) tuples.""" |
| 42 | + import pwd |
41 | 43 | dirs = [] |
42 | | - # Scan all /run/user/*/dstack-vmm |
43 | 44 | run_user = "/run/user" |
44 | 45 | if os.path.isdir(run_user): |
45 | 46 | try: |
46 | | - for uid_dir in os.listdir(run_user): |
47 | | - candidate = os.path.join(run_user, uid_dir, "dstack-vmm") |
| 47 | + for uid_str in os.listdir(run_user): |
| 48 | + candidate = os.path.join(run_user, uid_str, "dstack-vmm") |
48 | 49 | if os.path.isdir(candidate): |
49 | | - dirs.append(candidate) |
| 50 | + try: |
| 51 | + username = pwd.getpwuid(int(uid_str)).pw_name |
| 52 | + except (KeyError, ValueError): |
| 53 | + username = f"uid:{uid_str}" |
| 54 | + dirs.append((candidate, username)) |
50 | 55 | except PermissionError: |
51 | 56 | pass |
52 | 57 | return dirs |
@@ -76,27 +81,15 @@ def discover_vmm_instances() -> List[Dict[str, Any]]: |
76 | 81 | Returns: |
77 | 82 | List of VMM instance info dicts, sorted by started_at. |
78 | 83 | """ |
79 | | - import pwd |
80 | 84 | instances = [] |
81 | | - for discovery_dir in _get_discovery_dirs(): |
82 | | - # Extract uid from /run/user/<uid>/dstack-vmm path |
83 | | - parts = discovery_dir.split('/') |
84 | | - uid_str = parts[3] if len(parts) > 3 and parts[1] == 'run' and parts[2] == 'user' else None |
85 | | - username = None |
86 | | - if uid_str and uid_str.isdigit(): |
87 | | - try: |
88 | | - username = pwd.getpwuid(int(uid_str)).pw_name |
89 | | - except KeyError: |
90 | | - username = f"uid:{uid_str}" |
91 | | - |
| 85 | + for discovery_dir, username in _get_discovery_dirs(): |
92 | 86 | for fname in os.listdir(discovery_dir): |
93 | 87 | if not fname.endswith('.json'): |
94 | 88 | continue |
95 | 89 | fpath = os.path.join(discovery_dir, fname) |
96 | 90 | try: |
97 | 91 | with open(fpath, 'r') as f: |
98 | 92 | info = json.load(f) |
99 | | - # Check if process is still alive |
100 | 93 | pid = info.get('pid') |
101 | 94 | if pid and not os.path.exists(f'/proc/{pid}'): |
102 | 95 | continue |
@@ -185,7 +178,7 @@ def cmd_ls_vmm(args): |
185 | 178 |
|
186 | 179 | if not instances: |
187 | 180 | print("No running VMM instances found.") |
188 | | - print(f" (scanned: {', '.join(_get_discovery_dirs()) or '/run/user/*/dstack-vmm'})") |
| 181 | + print(f" (scanned: {', '.join(d for d, _ in _get_discovery_dirs()) or '/run/user/*/dstack-vmm'})") |
189 | 182 | return |
190 | 183 |
|
191 | 184 | if getattr(args, 'json', False): |
|
0 commit comments