|
| 1 | +// Get detailed info for a single Multipass instance |
| 2 | +var instanceId = clawset.env("INSTANCE_ID"); |
| 3 | +var result = clawset.shell("multipass", ["info", instanceId, "--format", "json"]); |
| 4 | + |
| 5 | +if (result.exitCode !== 0) { |
| 6 | + clawset.log("multipass info failed: " + result.stderr); |
| 7 | + return null; |
| 8 | +} |
| 9 | + |
| 10 | +var data = JSON.parse(result.stdout); |
| 11 | +var info = data.info && data.info[instanceId]; |
| 12 | + |
| 13 | +if (!info) { |
| 14 | + return null; |
| 15 | +} |
| 16 | + |
| 17 | +// Parse resources |
| 18 | +var memory = null; |
| 19 | +if (info.memory) { |
| 20 | + var memTotal = info.memory.total || 0; |
| 21 | + var memUsed = info.memory.used || 0; |
| 22 | + memory = Math.round(memUsed / 1024 / 1024) + " MB / " + Math.round(memTotal / 1024 / 1024) + " MB"; |
| 23 | +} |
| 24 | + |
| 25 | +var cpus = null; |
| 26 | +if (info.cpu_count) { |
| 27 | + cpus = String(info.cpu_count); |
| 28 | +} |
| 29 | + |
| 30 | +var storage = null; |
| 31 | +if (info.disks && info.disks.sda1) { |
| 32 | + var diskTotal = parseInt(info.disks.sda1.total || "0"); |
| 33 | + var diskUsed = parseInt(info.disks.sda1.used || "0"); |
| 34 | + storage = Math.round(diskUsed / 1024 / 1024 / 1024) + " GB / " + Math.round(diskTotal / 1024 / 1024 / 1024) + " GB"; |
| 35 | +} |
| 36 | + |
| 37 | +// Parse mounts |
| 38 | +var mounts = {}; |
| 39 | +if (info.mounts) { |
| 40 | + for (var mountPoint in info.mounts) { |
| 41 | + mounts[mountPoint] = info.mounts[mountPoint].source_path || ""; |
| 42 | + } |
| 43 | +} |
| 44 | + |
| 45 | +var ip = ""; |
| 46 | +if (info.ipv4 && info.ipv4.length > 0) { |
| 47 | + ip = info.ipv4[0]; |
| 48 | +} |
| 49 | + |
| 50 | +// Check node/openclaw/provisioning status inside the VM |
| 51 | +var innerResult = clawset.shell("multipass", [ |
| 52 | + "exec", instanceId, "--", "bash", "-ic", |
| 53 | + "source ~/.bashrc; echo '===NODE==='; node -v || echo 'NOT_FOUND'; echo '===OPENCLAW_VER==='; openclaw --version || echo 'NOT_FOUND'; echo '===PROVISIONING==='; if [ -f /tmp/provisioning ]; then echo 'YES'; else echo 'NO'; fi" |
| 54 | +]); |
| 55 | + |
| 56 | +var nodeInstalled = null; |
| 57 | +var openclawInstalled = false; |
| 58 | +var isProvisioning = false; |
| 59 | + |
| 60 | +if (innerResult.exitCode === 0) { |
| 61 | + var lines = innerResult.stdout.split("\n"); |
| 62 | + var section = ""; |
| 63 | + for (var i = 0; i < lines.length; i++) { |
| 64 | + var line = lines[i].trim(); |
| 65 | + if (line === "===NODE===") { section = "node"; continue; } |
| 66 | + if (line === "===OPENCLAW_VER===") { section = "openclaw"; continue; } |
| 67 | + if (line === "===PROVISIONING===") { section = "provisioning"; continue; } |
| 68 | + |
| 69 | + if (section === "node" && line !== "NOT_FOUND" && line !== "") { |
| 70 | + nodeInstalled = line; |
| 71 | + } |
| 72 | + if (section === "openclaw" && line !== "NOT_FOUND" && line !== "") { |
| 73 | + openclawInstalled = true; |
| 74 | + } |
| 75 | + if (section === "provisioning") { |
| 76 | + isProvisioning = (line === "YES"); |
| 77 | + } |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +return { |
| 82 | + id: instanceId, |
| 83 | + name: instanceId, |
| 84 | + status: info.state || "Unknown", |
| 85 | + ip: ip, |
| 86 | + provider: "multipass", |
| 87 | + meta: { |
| 88 | + os: info.image_release || "Ubuntu" |
| 89 | + }, |
| 90 | + resources: { |
| 91 | + cpus: cpus, |
| 92 | + memory: memory, |
| 93 | + storage: storage |
| 94 | + }, |
| 95 | + mounts: mounts, |
| 96 | + node_installed: nodeInstalled, |
| 97 | + openclaw_installed: openclawInstalled, |
| 98 | + is_provisioning: isProvisioning |
| 99 | +}; |
0 commit comments