| 81 | } |
| 82 | |
| 83 | std::string BuildRuntimeCommand(const std::string& exe, const VmSpec& spec, |
| 84 | const std::string& pipe, |
| 85 | const std::vector<GuestForward>& guest_forwards = {}) { |
| 86 | std::ostringstream cmd; |
| 87 | cmd << '"' << exe << '"' |
| 88 | << " --vm-id " << spec.vm_id |
| 89 | << " --control-endpoint " << pipe |
| 90 | << " --interactive off" |
| 91 | << " --kernel \"" << spec.kernel_path << "\""; |
| 92 | if (!spec.vm_dir.empty()) { |
| 93 | cmd << " --vm-dir \"" << spec.vm_dir << '"'; |
| 94 | } |
| 95 | if (!spec.initrd_path.empty()) { |
| 96 | cmd << " --initrd \"" << spec.initrd_path << '"'; |
| 97 | } |
| 98 | if (!spec.disk_path.empty()) { |
| 99 | cmd << " --disk \"" << spec.disk_path << '"'; |
| 100 | } |
| 101 | cmd << " --memory " << spec.memory_mb |
| 102 | << " --cpus " << spec.cpu_count; |
| 103 | cmd << " --net"; |
| 104 | if (spec.debug_mode) { |
| 105 | cmd << " --debug"; |
| 106 | } |
| 107 | // Port forwards are now configured dynamically after VM starts (via IPC) |
| 108 | // to ensure uniform error feedback. The runtime CLI still supports --forward. |
| 109 | for (const auto& gf : guest_forwards) { |
| 110 | cmd << " --guestfwd " << gf.ToGuestfwd(); |
| 111 | } |
| 112 | for (const auto& sf : spec.shared_folders) { |
| 113 | cmd << " --share \"" << sf.tag << ':' << sf.host_path; |
| 114 | if (sf.readonly) cmd << ":ro"; |
| 115 | cmd << '"'; |
| 116 | } |
| 117 | return cmd.str(); |
| 118 | } |
| 119 | |
| 120 | bool CopyFileChecked(const std::string& src, const std::string& dst, std::string* error) { |
| 121 | if (src.empty()) return true; |