openVMShell opens a shell session to the currently selected VM/container.
()
| 251 | // openVMShell opens a shell session to the currently selected VM/container. |
| 252 | |
| 253 | func (a *App) openVMShell() { |
| 254 | vm := a.vmList.GetSelectedVM() |
| 255 | if vm == nil { |
| 256 | a.showMessageSafe("Selected VM not found") |
| 257 | return |
| 258 | } |
| 259 | |
| 260 | sshSettings := a.config.ResolveSSHSettings(vm.SourceProfile) |
| 261 | hostShellUser := sshSettings.SSHUser |
| 262 | vmShellUser := sshSettings.VMSSHUser |
| 263 | jumpHost := sshSettings.SSHJumpHost |
| 264 | |
| 265 | if vmShellUser == "" { |
| 266 | vmShellUser = hostShellUser |
| 267 | } |
| 268 | |
| 269 | if vm.Type == vmTypeLXC && hostShellUser == "" { |
| 270 | a.showMessageSafe("SSH user not configured. Please set PROXMOX_SSH_USER environment variable or use --ssh-user flag.") |
| 271 | return |
| 272 | } |
| 273 | if vm.Type == vmTypeQEMU && vmShellUser == "" { |
| 274 | a.showMessageSafe("VM SSH user not configured. Set vm_ssh_user (or fallback ssh_user) to use VM shells.") |
| 275 | return |
| 276 | } |
| 277 | |
| 278 | // Get node IP from the cluster |
| 279 | var nodeIP string |
| 280 | var originalNodeIP string |
| 281 | |
| 282 | client, err := a.getClientForVM(vm) |
| 283 | if err != nil { |
| 284 | a.showMessageSafe(fmt.Sprintf("Error finding VM cluster: %v", err)) |
| 285 | return |
| 286 | } |
| 287 | |
| 288 | if client.Cluster != nil { |
| 289 | for _, node := range client.Cluster.Nodes { |
| 290 | if node.Name == vm.Node { |
| 291 | nodeIP = node.IP |
| 292 | originalNodeIP = nodeIP |
| 293 | // Log the IP immediately when obtained from cluster data |
| 294 | shellLogger.Debug("VM shell for %s (ID: %d): Found node %s with IP from cluster: '%s' (len=%d, bytes=%v)", |
| 295 | vm.Name, vm.ID, vm.Node, nodeIP, len(nodeIP), []byte(nodeIP)) |
| 296 | break |
| 297 | } |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | if nodeIP == "" && client != nil { |
| 302 | fallback := client.BaseHostname() |
| 303 | shellLogger.Debug("Node %s missing IP in cluster data (original='%s'); falling back to API host %s", vm.Node, originalNodeIP, fallback) |
| 304 | nodeIP = fallback |
| 305 | } |
| 306 | |
| 307 | if net.ParseIP(nodeIP) == nil && client != nil { |
| 308 | fallback := client.BaseHostname() |
| 309 | shellLogger.Debug("Node %s has malformed IP '%s' (original='%s', valid=%v); falling back to API host %s", |
| 310 | vm.Node, nodeIP, originalNodeIP, net.ParseIP(nodeIP) != nil, fallback) |
no test coverage detected