mirror of
https://github.com/containers/podman.git
synced 2025-12-03 11:49:18 +08:00
For Podman 6, we still have providers and will continue to have a default provider for each platform. But where a platform has multiple providers, we want users to be able to cross provider boudnaries imposed in Podman 4/5. The key change is to look up virtual machines by name, as before, but to then also iterate all possible providers. As of this PR, init will still only create with the default provider, but a subsequent PR will introdouce an provider override. I also removed the "--all-providers" command line option on `podman machine ls` because it no longer makes sense. And I marked the all provider list test to be skipped. Signed-off-by: Brent Baude <bbaude@redhat.com>
113 lines
2.9 KiB
Go
113 lines
2.9 KiB
Go
//go:build amd64 || arm64
|
|
|
|
package machine
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/containers/podman/v6/cmd/podman/registry"
|
|
"github.com/containers/podman/v6/cmd/podman/utils"
|
|
"github.com/containers/podman/v6/pkg/machine"
|
|
"github.com/containers/podman/v6/pkg/machine/define"
|
|
"github.com/containers/podman/v6/pkg/machine/shim"
|
|
"github.com/containers/podman/v6/pkg/machine/vmconfigs"
|
|
"github.com/spf13/cobra"
|
|
"go.podman.io/common/pkg/completion"
|
|
)
|
|
|
|
var (
|
|
sshCmd = &cobra.Command{
|
|
Use: "ssh [options] [NAME] [COMMAND [ARG ...]]",
|
|
Short: "SSH into an existing machine",
|
|
Long: "SSH into a managed virtual machine ",
|
|
PersistentPreRunE: machinePreRunE,
|
|
RunE: ssh,
|
|
Example: `podman machine ssh podman-machine-default
|
|
podman machine ssh myvm echo hello`,
|
|
ValidArgsFunction: autocompleteMachineSSH,
|
|
}
|
|
)
|
|
|
|
var (
|
|
sshOpts machine.SSHOptions
|
|
)
|
|
|
|
func init() {
|
|
sshCmd.Flags().SetInterspersed(false)
|
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
|
Command: sshCmd,
|
|
Parent: machineCmd,
|
|
})
|
|
flags := sshCmd.Flags()
|
|
usernameFlagName := "username"
|
|
flags.StringVar(&sshOpts.Username, usernameFlagName, "", "Username to use when ssh-ing into the VM.")
|
|
_ = sshCmd.RegisterFlagCompletionFunc(usernameFlagName, completion.AutocompleteNone)
|
|
}
|
|
|
|
func ssh(_ *cobra.Command, args []string) error {
|
|
var (
|
|
err error
|
|
exists bool
|
|
mc *vmconfigs.MachineConfig
|
|
vmProvider vmconfigs.VMProvider
|
|
)
|
|
|
|
// Set the VM to default
|
|
vmName := defaultMachineName
|
|
// If len is greater than 0, it means we may have been
|
|
// provided the VM name. If so, we check. The VM name,
|
|
// if provided, must be in args[0].
|
|
if len(args) > 0 {
|
|
// note: previous incantations of this up by a specific name
|
|
// and errors were ignored. this error is not ignored because
|
|
// it implies podman cannot read its machine files, which is bad
|
|
mc, vmProvider, err = shim.VMExists(args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if errors.Is(err, &define.ErrVMDoesNotExist{}) {
|
|
vmName = args[0]
|
|
} else {
|
|
sshOpts.Args = append(sshOpts.Args, args[0])
|
|
}
|
|
exists = true
|
|
}
|
|
|
|
// If len is greater than 1, it means we might have been
|
|
// given a vmname and args or just args
|
|
if len(args) > 1 {
|
|
if exists {
|
|
sshOpts.Args = args[1:]
|
|
} else {
|
|
sshOpts.Args = args
|
|
}
|
|
}
|
|
|
|
// If the machine config was not loaded earlier, we load it now
|
|
if mc == nil {
|
|
mc, vmProvider, err = shim.VMExists(vmName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
state, err := vmProvider.State(mc, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if state != define.Running {
|
|
return fmt.Errorf("vm %q is not running", mc.Name)
|
|
}
|
|
|
|
if sshOpts.Username == "" {
|
|
if mc.HostUser.Rootful {
|
|
sshOpts.Username = "root"
|
|
} else {
|
|
sshOpts.Username = mc.SSH.RemoteUsername
|
|
}
|
|
}
|
|
|
|
err = machine.LocalhostSSHShell(sshOpts.Username, mc.SSH.IdentityPath, mc.Name, mc.SSH.Port, sshOpts.Args)
|
|
return utils.HandleOSExecError(err)
|
|
}
|